timer-of.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (c) 2017, Linaro Ltd. All rights reserved.
  3. *
  4. * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms and conditions of the GNU General Public License,
  8. * version 2, as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <linux/clk.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/of.h>
  21. #include <linux/of_address.h>
  22. #include <linux/of_irq.h>
  23. #include <linux/slab.h>
  24. #include "timer-of.h"
  25. /**
  26. * timer_of_irq_exit - Release the interrupt
  27. * @of_irq: an of_timer_irq structure pointer
  28. *
  29. * Free the irq resource
  30. */
  31. static __init void timer_of_irq_exit(struct of_timer_irq *of_irq)
  32. {
  33. struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);
  34. struct clock_event_device *clkevt = &to->clkevt;
  35. of_irq->percpu ? free_percpu_irq(of_irq->irq, clkevt) :
  36. free_irq(of_irq->irq, clkevt);
  37. }
  38. /**
  39. * timer_of_irq_init - Request the interrupt
  40. * @np: a device tree node pointer
  41. * @of_irq: an of_timer_irq structure pointer
  42. *
  43. * Get the interrupt number from the DT from its definition and
  44. * request it. The interrupt is gotten by falling back the following way:
  45. *
  46. * - Get interrupt number by name
  47. * - Get interrupt number by index
  48. *
  49. * When the interrupt is per CPU, 'request_percpu_irq()' is called,
  50. * otherwise 'request_irq()' is used.
  51. *
  52. * Returns 0 on success, < 0 otherwise
  53. */
  54. static __init int timer_of_irq_init(struct device_node *np,
  55. struct of_timer_irq *of_irq)
  56. {
  57. int ret;
  58. struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);
  59. struct clock_event_device *clkevt = &to->clkevt;
  60. if (of_irq->name) {
  61. of_irq->irq = ret = of_irq_get_byname(np, of_irq->name);
  62. if (ret < 0) {
  63. pr_err("Failed to get interrupt %s for %s\n",
  64. of_irq->name, np->full_name);
  65. return ret;
  66. }
  67. } else {
  68. of_irq->irq = irq_of_parse_and_map(np, of_irq->index);
  69. }
  70. if (!of_irq->irq) {
  71. pr_err("Failed to map interrupt for %pOF\n", np);
  72. return -EINVAL;
  73. }
  74. ret = of_irq->percpu ?
  75. request_percpu_irq(of_irq->irq, of_irq->handler,
  76. np->full_name, clkevt) :
  77. request_irq(of_irq->irq, of_irq->handler,
  78. of_irq->flags ? of_irq->flags : IRQF_TIMER,
  79. np->full_name, clkevt);
  80. if (ret) {
  81. pr_err("Failed to request irq %d for %pOF\n", of_irq->irq, np);
  82. return ret;
  83. }
  84. clkevt->irq = of_irq->irq;
  85. return 0;
  86. }
  87. /**
  88. * timer_of_clk_exit - Release the clock resources
  89. * @of_clk: a of_timer_clk structure pointer
  90. *
  91. * Disables and releases the refcount on the clk
  92. */
  93. static __init void timer_of_clk_exit(struct of_timer_clk *of_clk)
  94. {
  95. of_clk->rate = 0;
  96. clk_disable_unprepare(of_clk->clk);
  97. clk_put(of_clk->clk);
  98. }
  99. /**
  100. * timer_of_clk_init - Initialize the clock resources
  101. * @np: a device tree node pointer
  102. * @of_clk: a of_timer_clk structure pointer
  103. *
  104. * Get the clock by name or by index, enable it and get the rate
  105. *
  106. * Returns 0 on success, < 0 otherwise
  107. */
  108. static __init int timer_of_clk_init(struct device_node *np,
  109. struct of_timer_clk *of_clk)
  110. {
  111. int ret;
  112. of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) :
  113. of_clk_get(np, of_clk->index);
  114. if (IS_ERR(of_clk->clk)) {
  115. pr_err("Failed to get clock for %pOF\n", np);
  116. return PTR_ERR(of_clk->clk);
  117. }
  118. ret = clk_prepare_enable(of_clk->clk);
  119. if (ret) {
  120. pr_err("Failed for enable clock for %pOF\n", np);
  121. goto out_clk_put;
  122. }
  123. of_clk->rate = clk_get_rate(of_clk->clk);
  124. if (!of_clk->rate) {
  125. ret = -EINVAL;
  126. pr_err("Failed to get clock rate for %pOF\n", np);
  127. goto out_clk_disable;
  128. }
  129. of_clk->period = DIV_ROUND_UP(of_clk->rate, HZ);
  130. out:
  131. return ret;
  132. out_clk_disable:
  133. clk_disable_unprepare(of_clk->clk);
  134. out_clk_put:
  135. clk_put(of_clk->clk);
  136. goto out;
  137. }
  138. static __init void timer_of_base_exit(struct of_timer_base *of_base)
  139. {
  140. iounmap(of_base->base);
  141. }
  142. static __init int timer_of_base_init(struct device_node *np,
  143. struct of_timer_base *of_base)
  144. {
  145. of_base->base = of_base->name ?
  146. of_io_request_and_map(np, of_base->index, of_base->name) :
  147. of_iomap(np, of_base->index);
  148. if (IS_ERR(of_base->base)) {
  149. pr_err("Failed to iomap (%s)\n", of_base->name);
  150. return PTR_ERR(of_base->base);
  151. }
  152. return 0;
  153. }
  154. int __init timer_of_init(struct device_node *np, struct timer_of *to)
  155. {
  156. int ret = -EINVAL;
  157. int flags = 0;
  158. if (to->flags & TIMER_OF_BASE) {
  159. ret = timer_of_base_init(np, &to->of_base);
  160. if (ret)
  161. goto out_fail;
  162. flags |= TIMER_OF_BASE;
  163. }
  164. if (to->flags & TIMER_OF_CLOCK) {
  165. ret = timer_of_clk_init(np, &to->of_clk);
  166. if (ret)
  167. goto out_fail;
  168. flags |= TIMER_OF_CLOCK;
  169. }
  170. if (to->flags & TIMER_OF_IRQ) {
  171. ret = timer_of_irq_init(np, &to->of_irq);
  172. if (ret)
  173. goto out_fail;
  174. flags |= TIMER_OF_IRQ;
  175. }
  176. if (!to->clkevt.name)
  177. to->clkevt.name = np->full_name;
  178. to->np = np;
  179. return ret;
  180. out_fail:
  181. if (flags & TIMER_OF_IRQ)
  182. timer_of_irq_exit(&to->of_irq);
  183. if (flags & TIMER_OF_CLOCK)
  184. timer_of_clk_exit(&to->of_clk);
  185. if (flags & TIMER_OF_BASE)
  186. timer_of_base_exit(&to->of_base);
  187. return ret;
  188. }
  189. /**
  190. * timer_of_cleanup - release timer_of ressources
  191. * @to: timer_of structure
  192. *
  193. * Release the ressources that has been used in timer_of_init().
  194. * This function should be called in init error cases
  195. */
  196. void __init timer_of_cleanup(struct timer_of *to)
  197. {
  198. if (to->flags & TIMER_OF_IRQ)
  199. timer_of_irq_exit(&to->of_irq);
  200. if (to->flags & TIMER_OF_CLOCK)
  201. timer_of_clk_exit(&to->of_clk);
  202. if (to->flags & TIMER_OF_BASE)
  203. timer_of_base_exit(&to->of_base);
  204. }