h8300_timer8.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * linux/arch/h8300/kernel/cpu/timer/timer8.c
  3. *
  4. * Yoshinori Sato <ysato@users.sourcefoge.jp>
  5. *
  6. * 8bit Timer driver
  7. *
  8. */
  9. #include <linux/errno.h>
  10. #include <linux/sched.h>
  11. #include <linux/kernel.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/init.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/slab.h>
  16. #include <linux/clockchips.h>
  17. #include <linux/module.h>
  18. #include <linux/clk.h>
  19. #include <linux/io.h>
  20. #include <linux/of.h>
  21. #include <asm/irq.h>
  22. #define _8TCR 0
  23. #define _8TCSR 2
  24. #define TCORA 4
  25. #define TCORB 6
  26. #define _8TCNT 8
  27. #define FLAG_REPROGRAM (1 << 0)
  28. #define FLAG_SKIPEVENT (1 << 1)
  29. #define FLAG_IRQCONTEXT (1 << 2)
  30. #define FLAG_STARTED (1 << 3)
  31. #define ONESHOT 0
  32. #define PERIODIC 1
  33. #define RELATIVE 0
  34. #define ABSOLUTE 1
  35. struct timer8_priv {
  36. struct platform_device *pdev;
  37. struct clock_event_device ced;
  38. struct irqaction irqaction;
  39. unsigned long mapbase;
  40. raw_spinlock_t lock;
  41. unsigned long flags;
  42. unsigned int rate;
  43. unsigned int tcora;
  44. struct clk *pclk;
  45. };
  46. static unsigned long timer8_get_counter(struct timer8_priv *p)
  47. {
  48. unsigned long v1, v2, v3;
  49. int o1, o2;
  50. o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20;
  51. /* Make sure the timer value is stable. Stolen from acpi_pm.c */
  52. do {
  53. o2 = o1;
  54. v1 = ctrl_inw(p->mapbase + _8TCNT);
  55. v2 = ctrl_inw(p->mapbase + _8TCNT);
  56. v3 = ctrl_inw(p->mapbase + _8TCNT);
  57. o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20;
  58. } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
  59. || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
  60. v2 |= o1 << 10;
  61. return v2;
  62. }
  63. static irqreturn_t timer8_interrupt(int irq, void *dev_id)
  64. {
  65. struct timer8_priv *p = dev_id;
  66. ctrl_outb(ctrl_inb(p->mapbase + _8TCSR) & ~0x40,
  67. p->mapbase + _8TCSR);
  68. p->flags |= FLAG_IRQCONTEXT;
  69. ctrl_outw(p->tcora, p->mapbase + TCORA);
  70. if (!(p->flags & FLAG_SKIPEVENT)) {
  71. if (clockevent_state_oneshot(&p->ced))
  72. ctrl_outw(0x0000, p->mapbase + _8TCR);
  73. p->ced.event_handler(&p->ced);
  74. }
  75. p->flags &= ~(FLAG_SKIPEVENT | FLAG_IRQCONTEXT);
  76. return IRQ_HANDLED;
  77. }
  78. static void timer8_set_next(struct timer8_priv *p, unsigned long delta)
  79. {
  80. unsigned long flags;
  81. unsigned long now;
  82. raw_spin_lock_irqsave(&p->lock, flags);
  83. if (delta >= 0x10000)
  84. dev_warn(&p->pdev->dev, "delta out of range\n");
  85. now = timer8_get_counter(p);
  86. p->tcora = delta;
  87. ctrl_outb(ctrl_inb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR);
  88. if (delta > now)
  89. ctrl_outw(delta, p->mapbase + TCORA);
  90. else
  91. ctrl_outw(now + 1, p->mapbase + TCORA);
  92. raw_spin_unlock_irqrestore(&p->lock, flags);
  93. }
  94. static int timer8_enable(struct timer8_priv *p)
  95. {
  96. p->rate = clk_get_rate(p->pclk) / 64;
  97. ctrl_outw(0xffff, p->mapbase + TCORA);
  98. ctrl_outw(0x0000, p->mapbase + _8TCNT);
  99. ctrl_outw(0x0c02, p->mapbase + _8TCR);
  100. return 0;
  101. }
  102. static int timer8_start(struct timer8_priv *p)
  103. {
  104. int ret = 0;
  105. unsigned long flags;
  106. raw_spin_lock_irqsave(&p->lock, flags);
  107. if (!(p->flags & FLAG_STARTED))
  108. ret = timer8_enable(p);
  109. if (ret)
  110. goto out;
  111. p->flags |= FLAG_STARTED;
  112. out:
  113. raw_spin_unlock_irqrestore(&p->lock, flags);
  114. return ret;
  115. }
  116. static void timer8_stop(struct timer8_priv *p)
  117. {
  118. unsigned long flags;
  119. raw_spin_lock_irqsave(&p->lock, flags);
  120. ctrl_outw(0x0000, p->mapbase + _8TCR);
  121. raw_spin_unlock_irqrestore(&p->lock, flags);
  122. }
  123. static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced)
  124. {
  125. return container_of(ced, struct timer8_priv, ced);
  126. }
  127. static void timer8_clock_event_start(struct timer8_priv *p, int periodic)
  128. {
  129. struct clock_event_device *ced = &p->ced;
  130. timer8_start(p);
  131. ced->shift = 32;
  132. ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
  133. ced->max_delta_ns = clockevent_delta2ns(0xffff, ced);
  134. ced->min_delta_ns = clockevent_delta2ns(0x0001, ced);
  135. timer8_set_next(p, periodic?(p->rate + HZ/2) / HZ:0x10000);
  136. }
  137. static int timer8_clock_event_shutdown(struct clock_event_device *ced)
  138. {
  139. timer8_stop(ced_to_priv(ced));
  140. return 0;
  141. }
  142. static int timer8_clock_event_periodic(struct clock_event_device *ced)
  143. {
  144. struct timer8_priv *p = ced_to_priv(ced);
  145. dev_info(&p->pdev->dev, "used for periodic clock events\n");
  146. timer8_stop(p);
  147. timer8_clock_event_start(p, PERIODIC);
  148. return 0;
  149. }
  150. static int timer8_clock_event_oneshot(struct clock_event_device *ced)
  151. {
  152. struct timer8_priv *p = ced_to_priv(ced);
  153. dev_info(&p->pdev->dev, "used for oneshot clock events\n");
  154. timer8_stop(p);
  155. timer8_clock_event_start(p, ONESHOT);
  156. return 0;
  157. }
  158. static int timer8_clock_event_next(unsigned long delta,
  159. struct clock_event_device *ced)
  160. {
  161. struct timer8_priv *p = ced_to_priv(ced);
  162. BUG_ON(!clockevent_state_oneshot(ced));
  163. timer8_set_next(p, delta - 1);
  164. return 0;
  165. }
  166. static int timer8_setup(struct timer8_priv *p,
  167. struct platform_device *pdev)
  168. {
  169. struct resource *res;
  170. int irq;
  171. int ret;
  172. p->pdev = pdev;
  173. res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
  174. if (!res) {
  175. dev_err(&p->pdev->dev, "failed to get I/O memory\n");
  176. return -ENXIO;
  177. }
  178. irq = platform_get_irq(p->pdev, 0);
  179. if (irq < 0) {
  180. dev_err(&p->pdev->dev, "failed to get irq\n");
  181. return -ENXIO;
  182. }
  183. p->mapbase = res->start;
  184. p->irqaction.name = dev_name(&p->pdev->dev);
  185. p->irqaction.handler = timer8_interrupt;
  186. p->irqaction.dev_id = p;
  187. p->irqaction.flags = IRQF_TIMER;
  188. p->pclk = clk_get(&p->pdev->dev, "fck");
  189. if (IS_ERR(p->pclk)) {
  190. dev_err(&p->pdev->dev, "can't get clk\n");
  191. return PTR_ERR(p->pclk);
  192. }
  193. p->ced.name = pdev->name;
  194. p->ced.features = CLOCK_EVT_FEAT_PERIODIC |
  195. CLOCK_EVT_FEAT_ONESHOT;
  196. p->ced.rating = 200;
  197. p->ced.cpumask = cpumask_of(0);
  198. p->ced.set_next_event = timer8_clock_event_next;
  199. p->ced.set_state_shutdown = timer8_clock_event_shutdown;
  200. p->ced.set_state_periodic = timer8_clock_event_periodic;
  201. p->ced.set_state_oneshot = timer8_clock_event_oneshot;
  202. ret = setup_irq(irq, &p->irqaction);
  203. if (ret < 0) {
  204. dev_err(&p->pdev->dev,
  205. "failed to request irq %d\n", irq);
  206. return ret;
  207. }
  208. clockevents_register_device(&p->ced);
  209. platform_set_drvdata(pdev, p);
  210. return 0;
  211. }
  212. static int timer8_probe(struct platform_device *pdev)
  213. {
  214. struct timer8_priv *p = platform_get_drvdata(pdev);
  215. if (p) {
  216. dev_info(&pdev->dev, "kept as earlytimer\n");
  217. return 0;
  218. }
  219. p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
  220. if (!p)
  221. return -ENOMEM;
  222. return timer8_setup(p, pdev);
  223. }
  224. static int timer8_remove(struct platform_device *pdev)
  225. {
  226. return -EBUSY;
  227. }
  228. static const struct of_device_id timer8_of_table[] __maybe_unused = {
  229. { .compatible = "renesas,8bit-timer" },
  230. { }
  231. };
  232. MODULE_DEVICE_TABLE(of, timer8_of_table);
  233. static struct platform_driver timer8_driver = {
  234. .probe = timer8_probe,
  235. .remove = timer8_remove,
  236. .driver = {
  237. .name = "h8300-8timer",
  238. .of_match_table = of_match_ptr(timer8_of_table),
  239. }
  240. };
  241. static int __init timer8_init(void)
  242. {
  243. return platform_driver_register(&timer8_driver);
  244. }
  245. static void __exit timer8_exit(void)
  246. {
  247. platform_driver_unregister(&timer8_driver);
  248. }
  249. subsys_initcall(timer8_init);
  250. module_exit(timer8_exit);
  251. MODULE_AUTHOR("Yoshinori Sato");
  252. MODULE_DESCRIPTION("H8/300 8bit Timer Driver");
  253. MODULE_LICENSE("GPL v2");