timer64.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * Copyright (C) 2010, 2011 Texas Instruments Incorporated
  3. * Contributed by: Mark Salter (msalter@redhat.com)
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/clockchips.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/io.h>
  12. #include <linux/of.h>
  13. #include <linux/of_irq.h>
  14. #include <linux/of_address.h>
  15. #include <asm/soc.h>
  16. #include <asm/dscr.h>
  17. #include <asm/timer64.h>
  18. struct timer_regs {
  19. u32 reserved0;
  20. u32 emumgt;
  21. u32 reserved1;
  22. u32 reserved2;
  23. u32 cntlo;
  24. u32 cnthi;
  25. u32 prdlo;
  26. u32 prdhi;
  27. u32 tcr;
  28. u32 tgcr;
  29. u32 wdtcr;
  30. };
  31. static struct timer_regs __iomem *timer;
  32. #define TCR_TSTATLO 0x001
  33. #define TCR_INVOUTPLO 0x002
  34. #define TCR_INVINPLO 0x004
  35. #define TCR_CPLO 0x008
  36. #define TCR_ENAMODELO_ONCE 0x040
  37. #define TCR_ENAMODELO_CONT 0x080
  38. #define TCR_ENAMODELO_MASK 0x0c0
  39. #define TCR_PWIDLO_MASK 0x030
  40. #define TCR_CLKSRCLO 0x100
  41. #define TCR_TIENLO 0x200
  42. #define TCR_TSTATHI (0x001 << 16)
  43. #define TCR_INVOUTPHI (0x002 << 16)
  44. #define TCR_CPHI (0x008 << 16)
  45. #define TCR_PWIDHI_MASK (0x030 << 16)
  46. #define TCR_ENAMODEHI_ONCE (0x040 << 16)
  47. #define TCR_ENAMODEHI_CONT (0x080 << 16)
  48. #define TCR_ENAMODEHI_MASK (0x0c0 << 16)
  49. #define TGCR_TIMLORS 0x001
  50. #define TGCR_TIMHIRS 0x002
  51. #define TGCR_TIMMODE_UD32 0x004
  52. #define TGCR_TIMMODE_WDT64 0x008
  53. #define TGCR_TIMMODE_CD32 0x00c
  54. #define TGCR_TIMMODE_MASK 0x00c
  55. #define TGCR_PSCHI_MASK (0x00f << 8)
  56. #define TGCR_TDDRHI_MASK (0x00f << 12)
  57. /*
  58. * Timer clocks are divided down from the CPU clock
  59. * The divisor is in the EMUMGTCLKSPD register
  60. */
  61. #define TIMER_DIVISOR \
  62. ((soc_readl(&timer->emumgt) & (0xf << 16)) >> 16)
  63. #define TIMER64_RATE (c6x_core_freq / TIMER_DIVISOR)
  64. #define TIMER64_MODE_DISABLED 0
  65. #define TIMER64_MODE_ONE_SHOT TCR_ENAMODELO_ONCE
  66. #define TIMER64_MODE_PERIODIC TCR_ENAMODELO_CONT
  67. static int timer64_mode;
  68. static int timer64_devstate_id = -1;
  69. static void timer64_config(unsigned long period)
  70. {
  71. u32 tcr = soc_readl(&timer->tcr) & ~TCR_ENAMODELO_MASK;
  72. soc_writel(tcr, &timer->tcr);
  73. soc_writel(period - 1, &timer->prdlo);
  74. soc_writel(0, &timer->cntlo);
  75. tcr |= timer64_mode;
  76. soc_writel(tcr, &timer->tcr);
  77. }
  78. static void timer64_enable(void)
  79. {
  80. u32 val;
  81. if (timer64_devstate_id >= 0)
  82. dscr_set_devstate(timer64_devstate_id, DSCR_DEVSTATE_ENABLED);
  83. /* disable timer, reset count */
  84. soc_writel(soc_readl(&timer->tcr) & ~TCR_ENAMODELO_MASK, &timer->tcr);
  85. soc_writel(0, &timer->prdlo);
  86. /* use internal clock and 1 cycle pulse width */
  87. val = soc_readl(&timer->tcr);
  88. soc_writel(val & ~(TCR_CLKSRCLO | TCR_PWIDLO_MASK), &timer->tcr);
  89. /* dual 32-bit unchained mode */
  90. val = soc_readl(&timer->tgcr) & ~TGCR_TIMMODE_MASK;
  91. soc_writel(val, &timer->tgcr);
  92. soc_writel(val | (TGCR_TIMLORS | TGCR_TIMMODE_UD32), &timer->tgcr);
  93. }
  94. static void timer64_disable(void)
  95. {
  96. /* disable timer, reset count */
  97. soc_writel(soc_readl(&timer->tcr) & ~TCR_ENAMODELO_MASK, &timer->tcr);
  98. soc_writel(0, &timer->prdlo);
  99. if (timer64_devstate_id >= 0)
  100. dscr_set_devstate(timer64_devstate_id, DSCR_DEVSTATE_DISABLED);
  101. }
  102. static int next_event(unsigned long delta,
  103. struct clock_event_device *evt)
  104. {
  105. timer64_config(delta);
  106. return 0;
  107. }
  108. static void set_clock_mode(enum clock_event_mode mode,
  109. struct clock_event_device *evt)
  110. {
  111. switch (mode) {
  112. case CLOCK_EVT_MODE_PERIODIC:
  113. timer64_enable();
  114. timer64_mode = TIMER64_MODE_PERIODIC;
  115. timer64_config(TIMER64_RATE / HZ);
  116. break;
  117. case CLOCK_EVT_MODE_ONESHOT:
  118. timer64_enable();
  119. timer64_mode = TIMER64_MODE_ONE_SHOT;
  120. break;
  121. case CLOCK_EVT_MODE_UNUSED:
  122. case CLOCK_EVT_MODE_SHUTDOWN:
  123. timer64_mode = TIMER64_MODE_DISABLED;
  124. timer64_disable();
  125. break;
  126. case CLOCK_EVT_MODE_RESUME:
  127. break;
  128. }
  129. }
  130. static struct clock_event_device t64_clockevent_device = {
  131. .name = "TIMER64_EVT32_TIMER",
  132. .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
  133. .rating = 200,
  134. .set_mode = set_clock_mode,
  135. .set_next_event = next_event,
  136. };
  137. static irqreturn_t timer_interrupt(int irq, void *dev_id)
  138. {
  139. struct clock_event_device *cd = &t64_clockevent_device;
  140. cd->event_handler(cd);
  141. return IRQ_HANDLED;
  142. }
  143. static struct irqaction timer_iact = {
  144. .name = "timer",
  145. .flags = IRQF_TIMER,
  146. .handler = timer_interrupt,
  147. .dev_id = &t64_clockevent_device,
  148. };
  149. void __init timer64_init(void)
  150. {
  151. struct clock_event_device *cd = &t64_clockevent_device;
  152. struct device_node *np, *first = NULL;
  153. u32 val;
  154. int err, found = 0;
  155. for_each_compatible_node(np, NULL, "ti,c64x+timer64") {
  156. err = of_property_read_u32(np, "ti,core-mask", &val);
  157. if (!err) {
  158. if (val & (1 << get_coreid())) {
  159. found = 1;
  160. break;
  161. }
  162. } else if (!first)
  163. first = np;
  164. }
  165. if (!found) {
  166. /* try first one with no core-mask */
  167. if (first)
  168. np = of_node_get(first);
  169. else {
  170. pr_debug("Cannot find ti,c64x+timer64 timer.\n");
  171. return;
  172. }
  173. }
  174. timer = of_iomap(np, 0);
  175. if (!timer) {
  176. pr_debug("%s: Cannot map timer registers.\n", np->full_name);
  177. goto out;
  178. }
  179. pr_debug("%s: Timer registers=%p.\n", np->full_name, timer);
  180. cd->irq = irq_of_parse_and_map(np, 0);
  181. if (cd->irq == NO_IRQ) {
  182. pr_debug("%s: Cannot find interrupt.\n", np->full_name);
  183. iounmap(timer);
  184. goto out;
  185. }
  186. /* If there is a device state control, save the ID. */
  187. err = of_property_read_u32(np, "ti,dscr-dev-enable", &val);
  188. if (!err) {
  189. timer64_devstate_id = val;
  190. /*
  191. * It is necessary to enable the timer block here because
  192. * the TIMER_DIVISOR macro needs to read a timer register
  193. * to get the divisor.
  194. */
  195. dscr_set_devstate(timer64_devstate_id, DSCR_DEVSTATE_ENABLED);
  196. }
  197. pr_debug("%s: Timer irq=%d.\n", np->full_name, cd->irq);
  198. clockevents_calc_mult_shift(cd, c6x_core_freq / TIMER_DIVISOR, 5);
  199. cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
  200. cd->min_delta_ns = clockevent_delta2ns(250, cd);
  201. cd->cpumask = cpumask_of(smp_processor_id());
  202. clockevents_register_device(cd);
  203. setup_irq(cd->irq, &timer_iact);
  204. out:
  205. of_node_put(np);
  206. return;
  207. }