clock.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * arch/arm/mach-ns9xxx/clock.c
  3. *
  4. * Copyright (C) 2007 by Digi International Inc.
  5. * All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License version 2 as published by
  9. * the Free Software Foundation.
  10. */
  11. #include <linux/err.h>
  12. #include <linux/module.h>
  13. #include <linux/list.h>
  14. #include <linux/clk.h>
  15. #include <linux/string.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/semaphore.h>
  18. #include "clock.h"
  19. static LIST_HEAD(clocks);
  20. static DEFINE_SPINLOCK(clk_lock);
  21. struct clk *clk_get(struct device *dev, const char *id)
  22. {
  23. struct clk *p, *ret = NULL, *retgen = NULL;
  24. unsigned long flags;
  25. int idno;
  26. if (dev == NULL || dev->bus != &platform_bus_type)
  27. idno = -1;
  28. else
  29. idno = to_platform_device(dev)->id;
  30. spin_lock_irqsave(&clk_lock, flags);
  31. list_for_each_entry(p, &clocks, node) {
  32. if (strcmp(id, p->name) == 0) {
  33. if (p->id == idno) {
  34. if (!try_module_get(p->owner))
  35. continue;
  36. ret = p;
  37. break;
  38. } else if (p->id == -1)
  39. /* remember match with id == -1 in case there is
  40. * no clock for idno */
  41. retgen = p;
  42. }
  43. }
  44. if (!ret && retgen && try_module_get(retgen->owner))
  45. ret = retgen;
  46. if (ret)
  47. ++ret->refcount;
  48. spin_unlock_irqrestore(&clk_lock, flags);
  49. return ret ? ret : ERR_PTR(-ENOENT);
  50. }
  51. EXPORT_SYMBOL(clk_get);
  52. void clk_put(struct clk *clk)
  53. {
  54. module_put(clk->owner);
  55. --clk->refcount;
  56. }
  57. EXPORT_SYMBOL(clk_put);
  58. static int clk_enable_unlocked(struct clk *clk)
  59. {
  60. int ret = 0;
  61. if (clk->parent) {
  62. ret = clk_enable_unlocked(clk->parent);
  63. if (ret)
  64. return ret;
  65. }
  66. if (clk->usage++ == 0 && clk->endisable)
  67. ret = clk->endisable(clk, 1);
  68. return ret;
  69. }
  70. int clk_enable(struct clk *clk)
  71. {
  72. int ret;
  73. unsigned long flags;
  74. spin_lock_irqsave(&clk_lock, flags);
  75. ret = clk_enable_unlocked(clk);
  76. spin_unlock_irqrestore(&clk_lock, flags);
  77. return ret;
  78. }
  79. EXPORT_SYMBOL(clk_enable);
  80. static void clk_disable_unlocked(struct clk *clk)
  81. {
  82. if (--clk->usage == 0 && clk->endisable)
  83. clk->endisable(clk, 0);
  84. if (clk->parent)
  85. clk_disable_unlocked(clk->parent);
  86. }
  87. void clk_disable(struct clk *clk)
  88. {
  89. unsigned long flags;
  90. spin_lock_irqsave(&clk_lock, flags);
  91. clk_disable_unlocked(clk);
  92. spin_unlock_irqrestore(&clk_lock, flags);
  93. }
  94. EXPORT_SYMBOL(clk_disable);
  95. unsigned long clk_get_rate(struct clk *clk)
  96. {
  97. if (clk->get_rate)
  98. return clk->get_rate(clk);
  99. if (clk->rate)
  100. return clk->rate;
  101. if (clk->parent)
  102. return clk_get_rate(clk->parent);
  103. return 0;
  104. }
  105. EXPORT_SYMBOL(clk_get_rate);
  106. int clk_register(struct clk *clk)
  107. {
  108. unsigned long flags;
  109. spin_lock_irqsave(&clk_lock, flags);
  110. list_add(&clk->node, &clocks);
  111. if (clk->parent)
  112. ++clk->parent->refcount;
  113. spin_unlock_irqrestore(&clk_lock, flags);
  114. return 0;
  115. }
  116. int clk_unregister(struct clk *clk)
  117. {
  118. int ret = 0;
  119. unsigned long flags;
  120. spin_lock_irqsave(&clk_lock, flags);
  121. if (clk->usage || clk->refcount)
  122. ret = -EBUSY;
  123. else
  124. list_del(&clk->node);
  125. if (clk->parent)
  126. --clk->parent->refcount;
  127. spin_unlock_irqrestore(&clk_lock, flags);
  128. return ret;
  129. }
  130. #if defined CONFIG_DEBUG_FS
  131. #include <linux/debugfs.h>
  132. #include <linux/seq_file.h>
  133. static int clk_debugfs_show(struct seq_file *s, void *null)
  134. {
  135. unsigned long flags;
  136. struct clk *p;
  137. spin_lock_irqsave(&clk_lock, flags);
  138. list_for_each_entry(p, &clocks, node)
  139. seq_printf(s, "%s.%d: usage=%lu refcount=%lu rate=%lu\n",
  140. p->name, p->id, p->usage, p->refcount,
  141. p->usage ? clk_get_rate(p) : 0);
  142. spin_unlock_irqrestore(&clk_lock, flags);
  143. return 0;
  144. }
  145. static int clk_debugfs_open(struct inode *inode, struct file *file)
  146. {
  147. return single_open(file, clk_debugfs_show, NULL);
  148. }
  149. static const struct file_operations clk_debugfs_operations = {
  150. .open = clk_debugfs_open,
  151. .read = seq_read,
  152. .llseek = seq_lseek,
  153. .release = single_release,
  154. };
  155. static int __init clk_debugfs_init(void)
  156. {
  157. struct dentry *dentry;
  158. dentry = debugfs_create_file("clk", S_IFREG | S_IRUGO, NULL, NULL,
  159. &clk_debugfs_operations);
  160. return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
  161. }
  162. subsys_initcall(clk_debugfs_init);
  163. #endif /* if defined CONFIG_DEBUG_FS */