0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012 #include <linux/err.h>
0013 #include <linux/regulator/driver.h>
0014 #include <linux/debugfs.h>
0015 #include <linux/seq_file.h>
0016 #include <linux/slab.h>
0017 #include <linux/module.h>
0018
0019 #include "dbx500-prcmu.h"
0020
0021
0022
0023
0024 static int power_state_active_cnt;
0025 static DEFINE_SPINLOCK(power_state_active_lock);
0026
0027 void power_state_active_enable(void)
0028 {
0029 unsigned long flags;
0030
0031 spin_lock_irqsave(&power_state_active_lock, flags);
0032 power_state_active_cnt++;
0033 spin_unlock_irqrestore(&power_state_active_lock, flags);
0034 }
0035
0036 int power_state_active_disable(void)
0037 {
0038 int ret = 0;
0039 unsigned long flags;
0040
0041 spin_lock_irqsave(&power_state_active_lock, flags);
0042 if (power_state_active_cnt <= 0) {
0043 pr_err("power state: unbalanced enable/disable calls\n");
0044 ret = -EINVAL;
0045 goto out;
0046 }
0047
0048 power_state_active_cnt--;
0049 out:
0050 spin_unlock_irqrestore(&power_state_active_lock, flags);
0051 return ret;
0052 }
0053
0054 #ifdef CONFIG_REGULATOR_DEBUG
0055
0056 static int power_state_active_get(void)
0057 {
0058 unsigned long flags;
0059 int cnt;
0060
0061 spin_lock_irqsave(&power_state_active_lock, flags);
0062 cnt = power_state_active_cnt;
0063 spin_unlock_irqrestore(&power_state_active_lock, flags);
0064
0065 return cnt;
0066 }
0067
0068 static struct ux500_regulator_debug {
0069 struct dentry *dir;
0070 struct dbx500_regulator_info *regulator_array;
0071 int num_regulators;
0072 u8 *state_before_suspend;
0073 u8 *state_after_suspend;
0074 } rdebug;
0075
0076 static int ux500_regulator_power_state_cnt_show(struct seq_file *s, void *p)
0077 {
0078
0079 seq_printf(s, "ux500-regulator power state count: %i\n",
0080 power_state_active_get());
0081
0082 return 0;
0083 }
0084 DEFINE_SHOW_ATTRIBUTE(ux500_regulator_power_state_cnt);
0085
0086 static int ux500_regulator_status_show(struct seq_file *s, void *p)
0087 {
0088 int i;
0089
0090
0091 seq_puts(s, "ux500-regulator status:\n");
0092 seq_printf(s, "%31s : %8s : %8s\n", "current", "before", "after");
0093
0094 for (i = 0; i < rdebug.num_regulators; i++) {
0095 struct dbx500_regulator_info *info;
0096
0097 info = &rdebug.regulator_array[i];
0098
0099
0100 seq_printf(s, "%20s : %8s : %8s : %8s\n",
0101 info->desc.name,
0102 info->is_enabled ? "enabled" : "disabled",
0103 rdebug.state_before_suspend[i] ? "enabled" : "disabled",
0104 rdebug.state_after_suspend[i] ? "enabled" : "disabled");
0105 }
0106
0107 return 0;
0108 }
0109 DEFINE_SHOW_ATTRIBUTE(ux500_regulator_status);
0110
0111 int
0112 ux500_regulator_debug_init(struct platform_device *pdev,
0113 struct dbx500_regulator_info *regulator_info,
0114 int num_regulators)
0115 {
0116
0117 rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
0118
0119
0120 debugfs_create_file("status", 0444, rdebug.dir, &pdev->dev,
0121 &ux500_regulator_status_fops);
0122
0123
0124 debugfs_create_file("power-state-count", 0444, rdebug.dir,
0125 &pdev->dev, &ux500_regulator_power_state_cnt_fops);
0126
0127 rdebug.regulator_array = regulator_info;
0128 rdebug.num_regulators = num_regulators;
0129
0130 rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
0131 if (!rdebug.state_before_suspend)
0132 goto exit_destroy_power_state;
0133
0134 rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
0135 if (!rdebug.state_after_suspend)
0136 goto exit_free;
0137
0138 return 0;
0139
0140 exit_free:
0141 kfree(rdebug.state_before_suspend);
0142 exit_destroy_power_state:
0143 debugfs_remove_recursive(rdebug.dir);
0144 return -ENOMEM;
0145 }
0146
0147 int ux500_regulator_debug_exit(void)
0148 {
0149 debugfs_remove_recursive(rdebug.dir);
0150 kfree(rdebug.state_after_suspend);
0151 kfree(rdebug.state_before_suspend);
0152
0153 return 0;
0154 }
0155 #endif