Commit aac10aaa authored by Aneesh V's avatar Aneesh V Committed by Greg Kroah-Hartman

memory: emif: add debugfs entries for emif

Add debug entries for:
	1. calculated registers per frequency
	2. last polled value of MR4(temperature level
	   of LPDDR2 memory)
Signed-off-by: default avatarAneesh V <aneesh@ti.com>
Reviewed-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: default avatarBenoit Cousson <b-cousson@ti.com>
[santosh.shilimkar@ti.com: Moved to drivers/memory from drivers/misc]
Signed-off-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: default avatarLokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 98231c4f
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -47,6 +48,7 @@ ...@@ -47,6 +48,7 @@
* frequency change (i.e. corresponding to the * frequency change (i.e. corresponding to the
* frequency in effect at the moment) * frequency in effect at the moment)
* @plat_data: Pointer to saved platform data. * @plat_data: Pointer to saved platform data.
* @debugfs_root: dentry to the root folder for EMIF in debugfs
*/ */
struct emif_data { struct emif_data {
u8 duplicate; u8 duplicate;
...@@ -60,6 +62,7 @@ struct emif_data { ...@@ -60,6 +62,7 @@ struct emif_data {
struct emif_regs *regs_cache[EMIF_MAX_NUM_FREQUENCIES]; struct emif_regs *regs_cache[EMIF_MAX_NUM_FREQUENCIES];
struct emif_regs *curr_regs; struct emif_regs *curr_regs;
struct emif_platform_data *plat_data; struct emif_platform_data *plat_data;
struct dentry *debugfs_root;
}; };
static struct emif_data *emif1; static struct emif_data *emif1;
...@@ -68,6 +71,130 @@ static unsigned long irq_state; ...@@ -68,6 +71,130 @@ static unsigned long irq_state;
static u32 t_ck; /* DDR clock period in ps */ static u32 t_ck; /* DDR clock period in ps */
static LIST_HEAD(device_list); static LIST_HEAD(device_list);
static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif,
struct emif_regs *regs)
{
u32 type = emif->plat_data->device_info->type;
u32 ip_rev = emif->plat_data->ip_rev;
seq_printf(s, "EMIF register cache dump for %dMHz\n",
regs->freq/1000000);
seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw);
seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw);
seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw);
seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw);
if (ip_rev == EMIF_4D) {
seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n",
regs->read_idle_ctrl_shdw_normal);
seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n",
regs->read_idle_ctrl_shdw_volt_ramp);
} else if (ip_rev == EMIF_4D5) {
seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n",
regs->dll_calib_ctrl_shdw_normal);
seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n",
regs->dll_calib_ctrl_shdw_volt_ramp);
}
if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n",
regs->ref_ctrl_shdw_derated);
seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n",
regs->sdram_tim1_shdw_derated);
seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n",
regs->sdram_tim3_shdw_derated);
}
}
static int emif_regdump_show(struct seq_file *s, void *unused)
{
struct emif_data *emif = s->private;
struct emif_regs **regs_cache;
int i;
if (emif->duplicate)
regs_cache = emif1->regs_cache;
else
regs_cache = emif->regs_cache;
for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
do_emif_regdump_show(s, emif, regs_cache[i]);
seq_printf(s, "\n");
}
return 0;
}
static int emif_regdump_open(struct inode *inode, struct file *file)
{
return single_open(file, emif_regdump_show, inode->i_private);
}
static const struct file_operations emif_regdump_fops = {
.open = emif_regdump_open,
.read = seq_read,
.release = single_release,
};
static int emif_mr4_show(struct seq_file *s, void *unused)
{
struct emif_data *emif = s->private;
seq_printf(s, "MR4=%d\n", emif->temperature_level);
return 0;
}
static int emif_mr4_open(struct inode *inode, struct file *file)
{
return single_open(file, emif_mr4_show, inode->i_private);
}
static const struct file_operations emif_mr4_fops = {
.open = emif_mr4_open,
.read = seq_read,
.release = single_release,
};
static int __init_or_module emif_debugfs_init(struct emif_data *emif)
{
struct dentry *dentry;
int ret;
dentry = debugfs_create_dir(dev_name(emif->dev), NULL);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto err0;
}
emif->debugfs_root = dentry;
dentry = debugfs_create_file("regcache_dump", S_IRUGO,
emif->debugfs_root, emif, &emif_regdump_fops);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto err1;
}
dentry = debugfs_create_file("mr4", S_IRUGO,
emif->debugfs_root, emif, &emif_mr4_fops);
if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry);
goto err1;
}
return 0;
err1:
debugfs_remove_recursive(emif->debugfs_root);
err0:
return ret;
}
static void __exit emif_debugfs_exit(struct emif_data *emif)
{
debugfs_remove_recursive(emif->debugfs_root);
emif->debugfs_root = NULL;
}
/* /*
* Calculate the period of DDR clock from frequency value * Calculate the period of DDR clock from frequency value
*/ */
...@@ -1175,6 +1302,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev) ...@@ -1175,6 +1302,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
} }
emif_onetime_settings(emif); emif_onetime_settings(emif);
emif_debugfs_init(emif);
disable_and_clear_all_interrupts(emif); disable_and_clear_all_interrupts(emif);
setup_interrupts(emif, irq); setup_interrupts(emif, irq);
...@@ -1198,6 +1326,15 @@ static int __init_or_module emif_probe(struct platform_device *pdev) ...@@ -1198,6 +1326,15 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
static int __exit emif_remove(struct platform_device *pdev)
{
struct emif_data *emif = platform_get_drvdata(pdev);
emif_debugfs_exit(emif);
return 0;
}
static void emif_shutdown(struct platform_device *pdev) static void emif_shutdown(struct platform_device *pdev)
{ {
struct emif_data *emif = platform_get_drvdata(pdev); struct emif_data *emif = platform_get_drvdata(pdev);
...@@ -1508,6 +1645,7 @@ static void __attribute__((unused)) freq_post_notify_handling(void) ...@@ -1508,6 +1645,7 @@ static void __attribute__((unused)) freq_post_notify_handling(void)
} }
static struct platform_driver emif_driver = { static struct platform_driver emif_driver = {
.remove = __exit_p(emif_remove),
.shutdown = emif_shutdown, .shutdown = emif_shutdown,
.driver = { .driver = {
.name = "emif", .name = "emif",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment