clock.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Clock management for AT32AP CPUs
  3. *
  4. * Copyright (C) 2006 Atmel Corporation
  5. *
  6. * Based on arch/arm/mach-at91/clock.c
  7. * Copyright (C) 2005 David Brownell
  8. * Copyright (C) 2005 Ivan Kokshaysky
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/clk.h>
  15. #include <linux/err.h>
  16. #include <linux/device.h>
  17. #include <linux/string.h>
  18. #include "clock.h"
  19. static DEFINE_SPINLOCK(clk_lock);
  20. struct clk *clk_get(struct device *dev, const char *id)
  21. {
  22. int i;
  23. for (i = 0; i < at32_nr_clocks; i++) {
  24. struct clk *clk = at32_clock_list[i];
  25. if (clk->dev == dev && strcmp(id, clk->name) == 0)
  26. return clk;
  27. }
  28. return ERR_PTR(-ENOENT);
  29. }
  30. EXPORT_SYMBOL(clk_get);
  31. void clk_put(struct clk *clk)
  32. {
  33. /* clocks are static for now, we can't free them */
  34. }
  35. EXPORT_SYMBOL(clk_put);
  36. static void __clk_enable(struct clk *clk)
  37. {
  38. if (clk->parent)
  39. __clk_enable(clk->parent);
  40. if (clk->users++ == 0 && clk->mode)
  41. clk->mode(clk, 1);
  42. }
  43. int clk_enable(struct clk *clk)
  44. {
  45. unsigned long flags;
  46. spin_lock_irqsave(&clk_lock, flags);
  47. __clk_enable(clk);
  48. spin_unlock_irqrestore(&clk_lock, flags);
  49. return 0;
  50. }
  51. EXPORT_SYMBOL(clk_enable);
  52. static void __clk_disable(struct clk *clk)
  53. {
  54. if (clk->users == 0) {
  55. printk(KERN_ERR "%s: mismatched disable\n", clk->name);
  56. WARN_ON(1);
  57. return;
  58. }
  59. if (--clk->users == 0 && clk->mode)
  60. clk->mode(clk, 0);
  61. if (clk->parent)
  62. __clk_disable(clk->parent);
  63. }
  64. void clk_disable(struct clk *clk)
  65. {
  66. unsigned long flags;
  67. spin_lock_irqsave(&clk_lock, flags);
  68. __clk_disable(clk);
  69. spin_unlock_irqrestore(&clk_lock, flags);
  70. }
  71. EXPORT_SYMBOL(clk_disable);
  72. unsigned long clk_get_rate(struct clk *clk)
  73. {
  74. unsigned long flags;
  75. unsigned long rate;
  76. spin_lock_irqsave(&clk_lock, flags);
  77. rate = clk->get_rate(clk);
  78. spin_unlock_irqrestore(&clk_lock, flags);
  79. return rate;
  80. }
  81. EXPORT_SYMBOL(clk_get_rate);
  82. long clk_round_rate(struct clk *clk, unsigned long rate)
  83. {
  84. unsigned long flags, actual_rate;
  85. if (!clk->set_rate)
  86. return -ENOSYS;
  87. spin_lock_irqsave(&clk_lock, flags);
  88. actual_rate = clk->set_rate(clk, rate, 0);
  89. spin_unlock_irqrestore(&clk_lock, flags);
  90. return actual_rate;
  91. }
  92. EXPORT_SYMBOL(clk_round_rate);
  93. int clk_set_rate(struct clk *clk, unsigned long rate)
  94. {
  95. unsigned long flags;
  96. long ret;
  97. if (!clk->set_rate)
  98. return -ENOSYS;
  99. spin_lock_irqsave(&clk_lock, flags);
  100. ret = clk->set_rate(clk, rate, 1);
  101. spin_unlock_irqrestore(&clk_lock, flags);
  102. return (ret < 0) ? ret : 0;
  103. }
  104. EXPORT_SYMBOL(clk_set_rate);
  105. int clk_set_parent(struct clk *clk, struct clk *parent)
  106. {
  107. unsigned long flags;
  108. int ret;
  109. if (!clk->set_parent)
  110. return -ENOSYS;
  111. spin_lock_irqsave(&clk_lock, flags);
  112. ret = clk->set_parent(clk, parent);
  113. spin_unlock_irqrestore(&clk_lock, flags);
  114. return ret;
  115. }
  116. EXPORT_SYMBOL(clk_set_parent);
  117. struct clk *clk_get_parent(struct clk *clk)
  118. {
  119. return clk->parent;
  120. }
  121. EXPORT_SYMBOL(clk_get_parent);