Commit 0c7242c21ab652451d68830f08d5b86d45ab1135

Authored by Todd Poynor
Committed by Afzal Mohammed
1 parent e3c57087ce
Exists in master

OMAP2+: DVFS: add debugfs support for visualizing

Ability to show the dependency table helps debug some of the quirky
issues associated with dvfs when multiple device requests are present

[nm@ti.com: log beautification, few fixes]
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Todd Poynor <toddpoynor@google.com>
[vaibhav.bedia@ti.com: Pull in for AM33xx]
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>

Showing 1 changed file with 174 additions and 0 deletions Side-by-side Diff

arch/arm/mach-omap2/dvfs.c
... ... @@ -17,6 +17,8 @@
17 17 #include <linux/slab.h>
18 18 #include <linux/opp.h>
19 19 #include <linux/clk.h>
  20 +#include <linux/debugfs.h>
  21 +#include <linux/seq_file.h>
20 22 #include <plat/common.h>
21 23 #include <plat/omap_device.h>
22 24 #include <plat/omap_hwmod.h>
... ... @@ -880,6 +882,176 @@
880 882 }
881 883 EXPORT_SYMBOL(omap_device_scale);
882 884  
  885 +#ifdef CONFIG_PM_DEBUG
  886 +static int dvfs_dump_vdd(struct seq_file *sf, void *unused)
  887 +{
  888 + int k;
  889 + struct omap_vdd_dvfs_info *dvfs_info;
  890 + struct omap_vdd_dev_list *tdev;
  891 + struct omap_dev_user_list *duser;
  892 + struct omap_vdd_user_list *vuser;
  893 + struct omap_vdd_info *vdd;
  894 + struct omap_vdd_dep_info *dep_info;
  895 + struct voltagedomain *voltdm;
  896 + struct omap_volt_data *volt_data;
  897 + int anyreq;
  898 + int anyreq2;
  899 +
  900 + dvfs_info = (struct omap_vdd_dvfs_info *)sf->private;
  901 + if (IS_ERR_OR_NULL(dvfs_info)) {
  902 + pr_err("%s: NO DVFS?\n", __func__);
  903 + return -EINVAL;
  904 + }
  905 +
  906 + voltdm = dvfs_info->voltdm;
  907 + if (IS_ERR_OR_NULL(voltdm)) {
  908 + pr_err("%s: NO voltdm?\n", __func__);
  909 + return -EINVAL;
  910 + }
  911 +
  912 + vdd = voltdm->vdd;
  913 + if (IS_ERR_OR_NULL(vdd)) {
  914 + pr_err("%s: NO vdd data?\n", __func__);
  915 + return -EINVAL;
  916 + }
  917 +
  918 + seq_printf(sf, "vdd_%s\n", voltdm->name);
  919 + mutex_lock(&omap_dvfs_lock);
  920 + spin_lock(&dvfs_info->user_lock);
  921 +
  922 + seq_printf(sf, "|- voltage requests\n| |\n");
  923 + anyreq = 0;
  924 + plist_for_each_entry(vuser, &dvfs_info->vdd_user_list, node) {
  925 + seq_printf(sf, "| |-%d: %s:%s\n",
  926 + vuser->node.prio,
  927 + dev_driver_string(vuser->dev), dev_name(vuser->dev));
  928 + anyreq = 1;
  929 + }
  930 +
  931 + spin_unlock(&dvfs_info->user_lock);
  932 +
  933 + if (!anyreq)
  934 + seq_printf(sf, "| `-none\n");
  935 + else
  936 + seq_printf(sf, "| X\n");
  937 + seq_printf(sf, "|\n");
  938 +
  939 + seq_printf(sf, "|- frequency requests\n| |\n");
  940 + anyreq2 = 0;
  941 + list_for_each_entry(tdev, &dvfs_info->dev_list, node) {
  942 + anyreq = 0;
  943 + seq_printf(sf, "| |- %s:%s\n",
  944 + dev_driver_string(tdev->dev), dev_name(tdev->dev));
  945 + spin_lock(&tdev->user_lock);
  946 + plist_for_each_entry(duser, &tdev->freq_user_list, node) {
  947 + seq_printf(sf, "| | |-%d: %s:%s\n",
  948 + duser->node.prio,
  949 + dev_driver_string(duser->dev),
  950 + dev_name(duser->dev));
  951 + anyreq = 1;
  952 + }
  953 +
  954 + spin_unlock(&tdev->user_lock);
  955 +
  956 + if (!anyreq)
  957 + seq_printf(sf, "| | `-none\n");
  958 + else
  959 + seq_printf(sf, "| | X\n");
  960 + anyreq2 = 1;
  961 + }
  962 + if (!anyreq2)
  963 + seq_printf(sf, "| `-none\n");
  964 + else
  965 + seq_printf(sf, "| X\n");
  966 +
  967 + volt_data = vdd->volt_data;
  968 + seq_printf(sf, "|- Supported voltages\n| |\n");
  969 + anyreq = 0;
  970 + while (volt_data && volt_data->volt_nominal) {
  971 + seq_printf(sf, "| |-%d\n", volt_data->volt_nominal);
  972 + anyreq = 1;
  973 + volt_data++;
  974 + }
  975 + if (!anyreq)
  976 + seq_printf(sf, "| `-none\n");
  977 + else
  978 + seq_printf(sf, "| X\n");
  979 +
  980 + dep_info = vdd->dep_vdd_info;
  981 + seq_printf(sf, "`- voltage dependencies\n |\n");
  982 + anyreq = 0;
  983 + while (dep_info && dep_info->nr_dep_entries) {
  984 + struct omap_vdd_dep_volt *dep_table = dep_info->dep_table;
  985 +
  986 + seq_printf(sf, " |-on vdd_%s\n", dep_info->name);
  987 +
  988 + for (k = 0; k < dep_info->nr_dep_entries; k++) {
  989 + seq_printf(sf, " | |- %d => %d\n",
  990 + dep_table[k].main_vdd_volt,
  991 + dep_table[k].dep_vdd_volt);
  992 + }
  993 +
  994 + anyreq = 1;
  995 + dep_info++;
  996 + }
  997 +
  998 + if (!anyreq)
  999 + seq_printf(sf, " `- none\n");
  1000 + else
  1001 + seq_printf(sf, " X X\n");
  1002 +
  1003 + mutex_unlock(&omap_dvfs_lock);
  1004 + return 0;
  1005 +}
  1006 +
  1007 +static int dvfs_dbg_open(struct inode *inode, struct file *file)
  1008 +{
  1009 + return single_open(file, dvfs_dump_vdd, inode->i_private);
  1010 +}
  1011 +
  1012 +static struct file_operations debugdvfs_fops = {
  1013 + .open = dvfs_dbg_open,
  1014 + .read = seq_read,
  1015 + .llseek = seq_lseek,
  1016 + .release = single_release,
  1017 +};
  1018 +
  1019 +static struct dentry __initdata *dvfsdebugfs_dir;
  1020 +
  1021 +static void __init dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info)
  1022 +{
  1023 + struct dentry *ddir;
  1024 +
  1025 + /* create a base dir */
  1026 + if (!dvfsdebugfs_dir)
  1027 + dvfsdebugfs_dir = debugfs_create_dir("dvfs", NULL);
  1028 + if (IS_ERR_OR_NULL(dvfsdebugfs_dir)) {
  1029 + WARN_ONCE("%s: Unable to create base DVFS dir\n", __func__);
  1030 + return;
  1031 + }
  1032 +
  1033 + if (IS_ERR_OR_NULL(dvfs_info->voltdm)) {
  1034 + pr_err("%s: no voltdm\n", __func__);
  1035 + return;
  1036 + }
  1037 +
  1038 + ddir = debugfs_create_dir(dvfs_info->voltdm->name, dvfsdebugfs_dir);
  1039 + if (IS_ERR_OR_NULL(ddir)) {
  1040 + pr_warning("%s: unable to create subdir %s\n", __func__,
  1041 + dvfs_info->voltdm->name);
  1042 + return;
  1043 + }
  1044 +
  1045 + debugfs_create_file("info", S_IRUGO, ddir,
  1046 + (void *)dvfs_info, &debugdvfs_fops);
  1047 +}
  1048 +#else /* CONFIG_PM_DEBUG */
  1049 +static inline void dvfs_dbg_init(struct omap_vdd_dvfs_info *dvfs_info)
  1050 +{
  1051 + return;
  1052 +}
  1053 +#endif /* CONFIG_PM_DEBUG */
  1054 +
883 1055 /**
884 1056 * omap_dvfs_register_device - Add a parent device into dvfs managed list
885 1057 * @dev: Device to be added
... ... @@ -940,6 +1112,8 @@
940 1112 INIT_LIST_HEAD(&dvfs_info->dev_list);
941 1113  
942 1114 list_add(&dvfs_info->node, &omap_dvfs_info_list);
  1115 +
  1116 + dvfs_dbg_init(dvfs_info);
943 1117 }
944 1118  
945 1119 /* If device already added, we dont need to do more.. */