h8300_timer8.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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 (p->ced.mode == CLOCK_EVT_MODE_ONESHOT)
  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 void timer8_clock_event_mode(enum clock_event_mode mode,
  138. struct clock_event_device *ced)
  139. {
  140. struct timer8_priv *p = ced_to_priv(ced);
  141. switch (mode) {
  142. case CLOCK_EVT_MODE_PERIODIC:
  143. dev_info(&p->pdev->dev, "used for periodic clock events\n");
  144. timer8_stop(p);
  145. timer8_clock_event_start(p, PERIODIC);
  146. break;
  147. case CLOCK_EVT_MODE_ONESHOT:
  148. dev_info(&p->pdev->dev, "used for oneshot clock events\n");
  149. timer8_stop(p);
  150. timer8_clock_event_start(p, ONESHOT);
  151. break;
  152. case CLOCK_EVT_MODE_SHUTDOWN:
  153. case CLOCK_EVT_MODE_UNUSED:
  154. timer8_stop(p);
  155. break;
  156. default:
  157. break;
  158. }
  159. }
  160. static int timer8_clock_event_next(unsigned long delta,
  161. struct clock_event_device *ced)
  162. {
  163. struct timer8_priv *p = ced_to_priv(ced);
  164. BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
  165. timer8_set_next(p, delta - 1);
  166. return 0;
  167. }
  168. static int timer8_setup(struct timer8_priv *p,
  169. struct platform_device *pdev)
  170. {
  171. struct resource *res;
  172. int irq;
  173. int ret;
  174. memset(p, 0, sizeof(*p));
  175. p->pdev = pdev;
  176. res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
  177. if (!res) {
  178. dev_err(&p->pdev->dev, "failed to get I/O memory\n");
  179. return -ENXIO;
  180. }
  181. irq = platform_get_irq(p->pdev, 0);
  182. if (irq < 0) {
  183. dev_err(&p->pdev->dev, "failed to get irq\n");
  184. return -ENXIO;
  185. }
  186. p->mapbase = res->start;
  187. p->irqaction.name = dev_name(&p->pdev->dev);
  188. p->irqaction.handler = timer8_interrupt;
  189. p->irqaction.dev_id = p;
  190. p->irqaction.flags = IRQF_TIMER;
  191. p->pclk = clk_get(&p->pdev->dev, "fck");
  192. if (IS_ERR(p->pclk)) {
  193. dev_err(&p->pdev->dev, "can't get clk\n");
  194. return PTR_ERR(p->pclk);
  195. }
  196. p->ced.name = pdev->name;
  197. p->ced.features = CLOCK_EVT_FEAT_PERIODIC |
  198. CLOCK_EVT_FEAT_ONESHOT;
  199. p->ced.rating = 200;
  200. p->ced.cpumask = cpumask_of(0);
  201. p->ced.set_next_event = timer8_clock_event_next;
  202. p->ced.set_mode = timer8_clock_event_mode;
  203. ret = setup_irq(irq, &p->irqaction);
  204. if (ret < 0) {
  205. dev_err(&p->pdev->dev,
  206. "failed to request irq %d\n", irq);
  207. return ret;
  208. }
  209. clockevents_register_device(&p->ced);
  210. platform_set_drvdata(pdev, p);
  211. return 0;
  212. }
  213. static int timer8_probe(struct platform_device *pdev)
  214. {
  215. struct timer8_priv *p = platform_get_drvdata(pdev);
  216. if (p) {
  217. dev_info(&pdev->dev, "kept as earlytimer\n");
  218. return 0;
  219. }
  220. p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
  221. if (!p)
  222. return -ENOMEM;
  223. return timer8_setup(p, pdev);
  224. }
  225. static int timer8_remove(struct platform_device *pdev)
  226. {
  227. return -EBUSY;
  228. }
  229. static const struct of_device_id timer8_of_table[] __maybe_unused = {
  230. { .compatible = "renesas,8bit-timer" },
  231. { }
  232. };
  233. MODULE_DEVICE_TABLE(of, timer8_of_table);
  234. static struct platform_driver timer8_driver = {
  235. .probe = timer8_probe,
  236. .remove = timer8_remove,
  237. .driver = {
  238. .name = "h8300-8timer",
  239. .of_match_table = of_match_ptr(timer8_of_table),
  240. }
  241. };
  242. static int __init timer8_init(void)
  243. {
  244. return platform_driver_register(&timer8_driver);
  245. }
  246. static void __exit timer8_exit(void)
  247. {
  248. platform_driver_unregister(&timer8_driver);
  249. }
  250. subsys_initcall(timer8_init);
  251. module_exit(timer8_exit);
  252. MODULE_AUTHOR("Yoshinori Sato");
  253. MODULE_DESCRIPTION("H8/300 8bit Timer Driver");
  254. MODULE_LICENSE("GPL v2");