dbx500-prcmu.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2010
  3. *
  4. * License Terms: GNU General Public License v2
  5. * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
  6. * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
  7. *
  8. * UX500 common part of Power domain regulators
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/err.h>
  12. #include <linux/regulator/driver.h>
  13. #include <linux/debugfs.h>
  14. #include <linux/seq_file.h>
  15. #include <linux/slab.h>
  16. #include "dbx500-prcmu.h"
  17. /*
  18. * power state reference count
  19. */
  20. static int power_state_active_cnt; /* will initialize to zero */
  21. static DEFINE_SPINLOCK(power_state_active_lock);
  22. int power_state_active_get(void)
  23. {
  24. unsigned long flags;
  25. int cnt;
  26. spin_lock_irqsave(&power_state_active_lock, flags);
  27. cnt = power_state_active_cnt;
  28. spin_unlock_irqrestore(&power_state_active_lock, flags);
  29. return cnt;
  30. }
  31. void power_state_active_enable(void)
  32. {
  33. unsigned long flags;
  34. spin_lock_irqsave(&power_state_active_lock, flags);
  35. power_state_active_cnt++;
  36. spin_unlock_irqrestore(&power_state_active_lock, flags);
  37. }
  38. int power_state_active_disable(void)
  39. {
  40. int ret = 0;
  41. unsigned long flags;
  42. spin_lock_irqsave(&power_state_active_lock, flags);
  43. if (power_state_active_cnt <= 0) {
  44. pr_err("power state: unbalanced enable/disable calls\n");
  45. ret = -EINVAL;
  46. goto out;
  47. }
  48. power_state_active_cnt--;
  49. out:
  50. spin_unlock_irqrestore(&power_state_active_lock, flags);
  51. return ret;
  52. }
  53. #ifdef CONFIG_REGULATOR_DEBUG
  54. static struct ux500_regulator_debug {
  55. struct dentry *dir;
  56. struct dentry *status_file;
  57. struct dentry *power_state_cnt_file;
  58. struct dbx500_regulator_info *regulator_array;
  59. int num_regulators;
  60. u8 *state_before_suspend;
  61. u8 *state_after_suspend;
  62. } rdebug;
  63. void ux500_regulator_suspend_debug(void)
  64. {
  65. int i;
  66. for (i = 0; i < rdebug.num_regulators; i++)
  67. rdebug.state_before_suspend[i] =
  68. rdebug.regulator_array[i].is_enabled;
  69. }
  70. void ux500_regulator_resume_debug(void)
  71. {
  72. int i;
  73. for (i = 0; i < rdebug.num_regulators; i++)
  74. rdebug.state_after_suspend[i] =
  75. rdebug.regulator_array[i].is_enabled;
  76. }
  77. static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
  78. {
  79. struct device *dev = s->private;
  80. int err;
  81. /* print power state count */
  82. err = seq_printf(s, "ux500-regulator power state count: %i\n",
  83. power_state_active_get());
  84. if (err < 0)
  85. dev_err(dev, "seq_printf overflow\n");
  86. return 0;
  87. }
  88. static int ux500_regulator_power_state_cnt_open(struct inode *inode,
  89. struct file *file)
  90. {
  91. return single_open(file, ux500_regulator_power_state_cnt_print,
  92. inode->i_private);
  93. }
  94. static const struct file_operations ux500_regulator_power_state_cnt_fops = {
  95. .open = ux500_regulator_power_state_cnt_open,
  96. .read = seq_read,
  97. .llseek = seq_lseek,
  98. .release = single_release,
  99. .owner = THIS_MODULE,
  100. };
  101. static int ux500_regulator_status_print(struct seq_file *s, void *p)
  102. {
  103. struct device *dev = s->private;
  104. int err;
  105. int i;
  106. /* print dump header */
  107. err = seq_printf(s, "ux500-regulator status:\n");
  108. if (err < 0)
  109. dev_err(dev, "seq_printf overflow\n");
  110. err = seq_printf(s, "%31s : %8s : %8s\n", "current",
  111. "before", "after");
  112. if (err < 0)
  113. dev_err(dev, "seq_printf overflow\n");
  114. for (i = 0; i < rdebug.num_regulators; i++) {
  115. struct dbx500_regulator_info *info;
  116. /* Access per-regulator data */
  117. info = &rdebug.regulator_array[i];
  118. /* print status */
  119. err = seq_printf(s, "%20s : %8s : %8s : %8s\n", info->desc.name,
  120. info->is_enabled ? "enabled" : "disabled",
  121. rdebug.state_before_suspend[i] ? "enabled" : "disabled",
  122. rdebug.state_after_suspend[i] ? "enabled" : "disabled");
  123. if (err < 0)
  124. dev_err(dev, "seq_printf overflow\n");
  125. }
  126. return 0;
  127. }
  128. static int ux500_regulator_status_open(struct inode *inode, struct file *file)
  129. {
  130. return single_open(file, ux500_regulator_status_print,
  131. inode->i_private);
  132. }
  133. static const struct file_operations ux500_regulator_status_fops = {
  134. .open = ux500_regulator_status_open,
  135. .read = seq_read,
  136. .llseek = seq_lseek,
  137. .release = single_release,
  138. .owner = THIS_MODULE,
  139. };
  140. int __attribute__((weak)) dbx500_regulator_testcase(
  141. struct dbx500_regulator_info *regulator_info,
  142. int num_regulators)
  143. {
  144. return 0;
  145. }
  146. int __devinit
  147. ux500_regulator_debug_init(struct platform_device *pdev,
  148. struct dbx500_regulator_info *regulator_info,
  149. int num_regulators)
  150. {
  151. /* create directory */
  152. rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
  153. if (!rdebug.dir)
  154. goto exit_no_debugfs;
  155. /* create "status" file */
  156. rdebug.status_file = debugfs_create_file("status",
  157. S_IRUGO, rdebug.dir, &pdev->dev,
  158. &ux500_regulator_status_fops);
  159. if (!rdebug.status_file)
  160. goto exit_destroy_dir;
  161. /* create "power-state-count" file */
  162. rdebug.power_state_cnt_file = debugfs_create_file("power-state-count",
  163. S_IRUGO, rdebug.dir, &pdev->dev,
  164. &ux500_regulator_power_state_cnt_fops);
  165. if (!rdebug.power_state_cnt_file)
  166. goto exit_destroy_status;
  167. rdebug.regulator_array = regulator_info;
  168. rdebug.num_regulators = num_regulators;
  169. rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
  170. if (!rdebug.state_before_suspend) {
  171. dev_err(&pdev->dev,
  172. "could not allocate memory for saving state\n");
  173. goto exit_destroy_power_state;
  174. }
  175. rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
  176. if (!rdebug.state_after_suspend) {
  177. dev_err(&pdev->dev,
  178. "could not allocate memory for saving state\n");
  179. goto exit_free;
  180. }
  181. dbx500_regulator_testcase(regulator_info, num_regulators);
  182. return 0;
  183. exit_free:
  184. kfree(rdebug.state_before_suspend);
  185. exit_destroy_power_state:
  186. debugfs_remove(rdebug.power_state_cnt_file);
  187. exit_destroy_status:
  188. debugfs_remove(rdebug.status_file);
  189. exit_destroy_dir:
  190. debugfs_remove(rdebug.dir);
  191. exit_no_debugfs:
  192. dev_err(&pdev->dev, "failed to create debugfs entries.\n");
  193. return -ENOMEM;
  194. }
  195. int __devexit ux500_regulator_debug_exit(void)
  196. {
  197. debugfs_remove_recursive(rdebug.dir);
  198. kfree(rdebug.state_after_suspend);
  199. kfree(rdebug.state_before_suspend);
  200. return 0;
  201. }
  202. #endif