clock.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Clock management for AT32AP CPUs
  3. *
  4. * Copyright (C) 2006 Atmel Corporation
  5. *
  6. * Based on arch/arm/mach-at91rm9200/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 spinlock_t clk_lock = SPIN_LOCK_UNLOCKED;
  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. BUG_ON(clk->users == 0);
  55. if (--clk->users == 0 && clk->mode)
  56. clk->mode(clk, 0);
  57. if (clk->parent)
  58. __clk_disable(clk->parent);
  59. }
  60. void clk_disable(struct clk *clk)
  61. {
  62. unsigned long flags;
  63. spin_lock_irqsave(&clk_lock, flags);
  64. __clk_disable(clk);
  65. spin_unlock_irqrestore(&clk_lock, flags);
  66. }
  67. EXPORT_SYMBOL(clk_disable);
  68. unsigned long clk_get_rate(struct clk *clk)
  69. {
  70. unsigned long flags;
  71. unsigned long rate;
  72. spin_lock_irqsave(&clk_lock, flags);
  73. rate = clk->get_rate(clk);
  74. spin_unlock_irqrestore(&clk_lock, flags);
  75. return rate;
  76. }
  77. EXPORT_SYMBOL(clk_get_rate);
  78. long clk_round_rate(struct clk *clk, unsigned long rate)
  79. {
  80. unsigned long flags, actual_rate;
  81. if (!clk->set_rate)
  82. return -ENOSYS;
  83. spin_lock_irqsave(&clk_lock, flags);
  84. actual_rate = clk->set_rate(clk, rate, 0);
  85. spin_unlock_irqrestore(&clk_lock, flags);
  86. return actual_rate;
  87. }
  88. EXPORT_SYMBOL(clk_round_rate);
  89. int clk_set_rate(struct clk *clk, unsigned long rate)
  90. {
  91. unsigned long flags;
  92. long ret;
  93. if (!clk->set_rate)
  94. return -ENOSYS;
  95. spin_lock_irqsave(&clk_lock, flags);
  96. ret = clk->set_rate(clk, rate, 1);
  97. spin_unlock_irqrestore(&clk_lock, flags);
  98. return (ret < 0) ? ret : 0;
  99. }
  100. EXPORT_SYMBOL(clk_set_rate);
  101. int clk_set_parent(struct clk *clk, struct clk *parent)
  102. {
  103. unsigned long flags;
  104. int ret;
  105. if (!clk->set_parent)
  106. return -ENOSYS;
  107. spin_lock_irqsave(&clk_lock, flags);
  108. ret = clk->set_parent(clk, parent);
  109. spin_unlock_irqrestore(&clk_lock, flags);
  110. return ret;
  111. }
  112. EXPORT_SYMBOL(clk_set_parent);
  113. struct clk *clk_get_parent(struct clk *clk)
  114. {
  115. return clk->parent;
  116. }
  117. EXPORT_SYMBOL(clk_get_parent);