diff options
| author | Aneesh V <aneesh@ti.com> | 2012-04-27 08:24:09 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-02 14:00:08 -0400 |
| commit | aac10aaa8cc65a6fef6f5bc7d0b96035b0225a61 (patch) | |
| tree | 3c61053e233eacdc80f4cb02bf598246c9547cce /drivers/memory | |
| parent | 98231c4fc3b95a0e9d37ba3711ad993bb27605c8 (diff) | |
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: Aneesh V <aneesh@ti.com>
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Benoit Cousson <b-cousson@ti.com>
[santosh.shilimkar@ti.com: Moved to drivers/memory from drivers/misc]
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/memory')
| -rw-r--r-- | drivers/memory/emif.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 3dfffbb8ab40..33a4396b24cb 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/debugfs.h> | ||
| 21 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 23 | #include <linux/list.h> | 24 | #include <linux/list.h> |
| @@ -47,6 +48,7 @@ | |||
| 47 | * frequency change (i.e. corresponding to the | 48 | * frequency change (i.e. corresponding to the |
| 48 | * frequency in effect at the moment) | 49 | * frequency in effect at the moment) |
| 49 | * @plat_data: Pointer to saved platform data. | 50 | * @plat_data: Pointer to saved platform data. |
| 51 | * @debugfs_root: dentry to the root folder for EMIF in debugfs | ||
| 50 | */ | 52 | */ |
| 51 | struct emif_data { | 53 | struct emif_data { |
| 52 | u8 duplicate; | 54 | u8 duplicate; |
| @@ -60,6 +62,7 @@ struct emif_data { | |||
| 60 | struct emif_regs *regs_cache[EMIF_MAX_NUM_FREQUENCIES]; | 62 | struct emif_regs *regs_cache[EMIF_MAX_NUM_FREQUENCIES]; |
| 61 | struct emif_regs *curr_regs; | 63 | struct emif_regs *curr_regs; |
| 62 | struct emif_platform_data *plat_data; | 64 | struct emif_platform_data *plat_data; |
| 65 | struct dentry *debugfs_root; | ||
| 63 | }; | 66 | }; |
| 64 | 67 | ||
| 65 | static struct emif_data *emif1; | 68 | static struct emif_data *emif1; |
| @@ -68,6 +71,130 @@ static unsigned long irq_state; | |||
| 68 | static u32 t_ck; /* DDR clock period in ps */ | 71 | static u32 t_ck; /* DDR clock period in ps */ |
| 69 | static LIST_HEAD(device_list); | 72 | static LIST_HEAD(device_list); |
| 70 | 73 | ||
| 74 | static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif, | ||
| 75 | struct emif_regs *regs) | ||
| 76 | { | ||
| 77 | u32 type = emif->plat_data->device_info->type; | ||
| 78 | u32 ip_rev = emif->plat_data->ip_rev; | ||
| 79 | |||
| 80 | seq_printf(s, "EMIF register cache dump for %dMHz\n", | ||
| 81 | regs->freq/1000000); | ||
| 82 | |||
| 83 | seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw); | ||
| 84 | seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw); | ||
| 85 | seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw); | ||
| 86 | seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw); | ||
| 87 | |||
| 88 | if (ip_rev == EMIF_4D) { | ||
| 89 | seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n", | ||
| 90 | regs->read_idle_ctrl_shdw_normal); | ||
| 91 | seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n", | ||
| 92 | regs->read_idle_ctrl_shdw_volt_ramp); | ||
| 93 | } else if (ip_rev == EMIF_4D5) { | ||
| 94 | seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n", | ||
| 95 | regs->dll_calib_ctrl_shdw_normal); | ||
| 96 | seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n", | ||
| 97 | regs->dll_calib_ctrl_shdw_volt_ramp); | ||
| 98 | } | ||
| 99 | |||
| 100 | if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) { | ||
| 101 | seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n", | ||
| 102 | regs->ref_ctrl_shdw_derated); | ||
| 103 | seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n", | ||
| 104 | regs->sdram_tim1_shdw_derated); | ||
| 105 | seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n", | ||
| 106 | regs->sdram_tim3_shdw_derated); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | static int emif_regdump_show(struct seq_file *s, void *unused) | ||
| 111 | { | ||
| 112 | struct emif_data *emif = s->private; | ||
| 113 | struct emif_regs **regs_cache; | ||
| 114 | int i; | ||
| 115 | |||
| 116 | if (emif->duplicate) | ||
| 117 | regs_cache = emif1->regs_cache; | ||
| 118 | else | ||
| 119 | regs_cache = emif->regs_cache; | ||
| 120 | |||
| 121 | for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) { | ||
| 122 | do_emif_regdump_show(s, emif, regs_cache[i]); | ||
| 123 | seq_printf(s, "\n"); | ||
| 124 | } | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int emif_regdump_open(struct inode *inode, struct file *file) | ||
| 130 | { | ||
| 131 | return single_open(file, emif_regdump_show, inode->i_private); | ||
| 132 | } | ||
| 133 | |||
| 134 | static const struct file_operations emif_regdump_fops = { | ||
| 135 | .open = emif_regdump_open, | ||
| 136 | .read = seq_read, | ||
| 137 | .release = single_release, | ||
| 138 | }; | ||
| 139 | |||
| 140 | static int emif_mr4_show(struct seq_file *s, void *unused) | ||
| 141 | { | ||
| 142 | struct emif_data *emif = s->private; | ||
| 143 | |||
| 144 | seq_printf(s, "MR4=%d\n", emif->temperature_level); | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int emif_mr4_open(struct inode *inode, struct file *file) | ||
| 149 | { | ||
| 150 | return single_open(file, emif_mr4_show, inode->i_private); | ||
| 151 | } | ||
| 152 | |||
| 153 | static const struct file_operations emif_mr4_fops = { | ||
| 154 | .open = emif_mr4_open, | ||
| 155 | .read = seq_read, | ||
| 156 | .release = single_release, | ||
| 157 | }; | ||
| 158 | |||
| 159 | static int __init_or_module emif_debugfs_init(struct emif_data *emif) | ||
| 160 | { | ||
| 161 | struct dentry *dentry; | ||
| 162 | int ret; | ||
| 163 | |||
| 164 | dentry = debugfs_create_dir(dev_name(emif->dev), NULL); | ||
| 165 | if (IS_ERR(dentry)) { | ||
| 166 | ret = PTR_ERR(dentry); | ||
| 167 | goto err0; | ||
| 168 | } | ||
| 169 | emif->debugfs_root = dentry; | ||
| 170 | |||
| 171 | dentry = debugfs_create_file("regcache_dump", S_IRUGO, | ||
| 172 | emif->debugfs_root, emif, &emif_regdump_fops); | ||
| 173 | if (IS_ERR(dentry)) { | ||
| 174 | ret = PTR_ERR(dentry); | ||
| 175 | goto err1; | ||
| 176 | } | ||
| 177 | |||
| 178 | dentry = debugfs_create_file("mr4", S_IRUGO, | ||
| 179 | emif->debugfs_root, emif, &emif_mr4_fops); | ||
| 180 | if (IS_ERR(dentry)) { | ||
| 181 | ret = PTR_ERR(dentry); | ||
| 182 | goto err1; | ||
| 183 | } | ||
| 184 | |||
| 185 | return 0; | ||
| 186 | err1: | ||
| 187 | debugfs_remove_recursive(emif->debugfs_root); | ||
| 188 | err0: | ||
| 189 | return ret; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void __exit emif_debugfs_exit(struct emif_data *emif) | ||
| 193 | { | ||
| 194 | debugfs_remove_recursive(emif->debugfs_root); | ||
| 195 | emif->debugfs_root = NULL; | ||
| 196 | } | ||
| 197 | |||
| 71 | /* | 198 | /* |
| 72 | * Calculate the period of DDR clock from frequency value | 199 | * Calculate the period of DDR clock from frequency value |
| 73 | */ | 200 | */ |
| @@ -1175,6 +1302,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev) | |||
| 1175 | } | 1302 | } |
| 1176 | 1303 | ||
| 1177 | emif_onetime_settings(emif); | 1304 | emif_onetime_settings(emif); |
| 1305 | emif_debugfs_init(emif); | ||
| 1178 | disable_and_clear_all_interrupts(emif); | 1306 | disable_and_clear_all_interrupts(emif); |
| 1179 | setup_interrupts(emif, irq); | 1307 | setup_interrupts(emif, irq); |
| 1180 | 1308 | ||
| @@ -1198,6 +1326,15 @@ error: | |||
| 1198 | return -ENODEV; | 1326 | return -ENODEV; |
| 1199 | } | 1327 | } |
| 1200 | 1328 | ||
| 1329 | static int __exit emif_remove(struct platform_device *pdev) | ||
| 1330 | { | ||
| 1331 | struct emif_data *emif = platform_get_drvdata(pdev); | ||
| 1332 | |||
| 1333 | emif_debugfs_exit(emif); | ||
| 1334 | |||
| 1335 | return 0; | ||
| 1336 | } | ||
| 1337 | |||
| 1201 | static void emif_shutdown(struct platform_device *pdev) | 1338 | static void emif_shutdown(struct platform_device *pdev) |
| 1202 | { | 1339 | { |
| 1203 | struct emif_data *emif = platform_get_drvdata(pdev); | 1340 | struct emif_data *emif = platform_get_drvdata(pdev); |
| @@ -1508,6 +1645,7 @@ static void __attribute__((unused)) freq_post_notify_handling(void) | |||
| 1508 | } | 1645 | } |
| 1509 | 1646 | ||
| 1510 | static struct platform_driver emif_driver = { | 1647 | static struct platform_driver emif_driver = { |
| 1648 | .remove = __exit_p(emif_remove), | ||
| 1511 | .shutdown = emif_shutdown, | 1649 | .shutdown = emif_shutdown, |
| 1512 | .driver = { | 1650 | .driver = { |
| 1513 | .name = "emif", | 1651 | .name = "emif", |
