timer-npcm7xx.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2014-2018 Nuvoton Technologies tomer.maimon@nuvoton.com
  4. * All rights reserved.
  5. *
  6. * Copyright 2017 Google, Inc.
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/sched.h>
  10. #include <linux/init.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/err.h>
  13. #include <linux/clk.h>
  14. #include <linux/io.h>
  15. #include <linux/clockchips.h>
  16. #include <linux/of_irq.h>
  17. #include <linux/of_address.h>
  18. #include "timer-of.h"
  19. /* Timers registers */
  20. #define NPCM7XX_REG_TCSR0 0x0 /* Timer 0 Control and Status Register */
  21. #define NPCM7XX_REG_TICR0 0x8 /* Timer 0 Initial Count Register */
  22. #define NPCM7XX_REG_TCSR1 0x4 /* Timer 1 Control and Status Register */
  23. #define NPCM7XX_REG_TICR1 0xc /* Timer 1 Initial Count Register */
  24. #define NPCM7XX_REG_TDR1 0x14 /* Timer 1 Data Register */
  25. #define NPCM7XX_REG_TISR 0x18 /* Timer Interrupt Status Register */
  26. /* Timers control */
  27. #define NPCM7XX_Tx_RESETINT 0x1f
  28. #define NPCM7XX_Tx_PERIOD BIT(27)
  29. #define NPCM7XX_Tx_INTEN BIT(29)
  30. #define NPCM7XX_Tx_COUNTEN BIT(30)
  31. #define NPCM7XX_Tx_ONESHOT 0x0
  32. #define NPCM7XX_Tx_OPER GENMASK(3, 27)
  33. #define NPCM7XX_Tx_MIN_PRESCALE 0x1
  34. #define NPCM7XX_Tx_TDR_MASK_BITS 24
  35. #define NPCM7XX_Tx_MAX_CNT 0xFFFFFF
  36. #define NPCM7XX_T0_CLR_INT 0x1
  37. #define NPCM7XX_Tx_CLR_CSR 0x0
  38. /* Timers operating mode */
  39. #define NPCM7XX_START_PERIODIC_Tx (NPCM7XX_Tx_PERIOD | NPCM7XX_Tx_COUNTEN | \
  40. NPCM7XX_Tx_INTEN | \
  41. NPCM7XX_Tx_MIN_PRESCALE)
  42. #define NPCM7XX_START_ONESHOT_Tx (NPCM7XX_Tx_ONESHOT | NPCM7XX_Tx_COUNTEN | \
  43. NPCM7XX_Tx_INTEN | \
  44. NPCM7XX_Tx_MIN_PRESCALE)
  45. #define NPCM7XX_START_Tx (NPCM7XX_Tx_COUNTEN | NPCM7XX_Tx_PERIOD | \
  46. NPCM7XX_Tx_MIN_PRESCALE)
  47. #define NPCM7XX_DEFAULT_CSR (NPCM7XX_Tx_CLR_CSR | NPCM7XX_Tx_MIN_PRESCALE)
  48. static int npcm7xx_timer_resume(struct clock_event_device *evt)
  49. {
  50. struct timer_of *to = to_timer_of(evt);
  51. u32 val;
  52. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  53. val |= NPCM7XX_Tx_COUNTEN;
  54. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  55. return 0;
  56. }
  57. static int npcm7xx_timer_shutdown(struct clock_event_device *evt)
  58. {
  59. struct timer_of *to = to_timer_of(evt);
  60. u32 val;
  61. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  62. val &= ~NPCM7XX_Tx_COUNTEN;
  63. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  64. return 0;
  65. }
  66. static int npcm7xx_timer_oneshot(struct clock_event_device *evt)
  67. {
  68. struct timer_of *to = to_timer_of(evt);
  69. u32 val;
  70. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  71. val &= ~NPCM7XX_Tx_OPER;
  72. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  73. val |= NPCM7XX_START_ONESHOT_Tx;
  74. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  75. return 0;
  76. }
  77. static int npcm7xx_timer_periodic(struct clock_event_device *evt)
  78. {
  79. struct timer_of *to = to_timer_of(evt);
  80. u32 val;
  81. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  82. val &= ~NPCM7XX_Tx_OPER;
  83. writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0);
  84. val |= NPCM7XX_START_PERIODIC_Tx;
  85. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  86. return 0;
  87. }
  88. static int npcm7xx_clockevent_set_next_event(unsigned long evt,
  89. struct clock_event_device *clk)
  90. {
  91. struct timer_of *to = to_timer_of(clk);
  92. u32 val;
  93. writel(evt, timer_of_base(to) + NPCM7XX_REG_TICR0);
  94. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  95. val |= NPCM7XX_START_Tx;
  96. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  97. return 0;
  98. }
  99. static irqreturn_t npcm7xx_timer0_interrupt(int irq, void *dev_id)
  100. {
  101. struct clock_event_device *evt = (struct clock_event_device *)dev_id;
  102. struct timer_of *to = to_timer_of(evt);
  103. writel(NPCM7XX_T0_CLR_INT, timer_of_base(to) + NPCM7XX_REG_TISR);
  104. evt->event_handler(evt);
  105. return IRQ_HANDLED;
  106. }
  107. static struct timer_of npcm7xx_to = {
  108. .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
  109. .clkevt = {
  110. .name = "npcm7xx-timer0",
  111. .features = CLOCK_EVT_FEAT_PERIODIC |
  112. CLOCK_EVT_FEAT_ONESHOT,
  113. .set_next_event = npcm7xx_clockevent_set_next_event,
  114. .set_state_shutdown = npcm7xx_timer_shutdown,
  115. .set_state_periodic = npcm7xx_timer_periodic,
  116. .set_state_oneshot = npcm7xx_timer_oneshot,
  117. .tick_resume = npcm7xx_timer_resume,
  118. .rating = 300,
  119. },
  120. .of_irq = {
  121. .handler = npcm7xx_timer0_interrupt,
  122. .flags = IRQF_TIMER | IRQF_IRQPOLL,
  123. },
  124. };
  125. static void __init npcm7xx_clockevents_init(void)
  126. {
  127. writel(NPCM7XX_DEFAULT_CSR,
  128. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR0);
  129. writel(NPCM7XX_Tx_RESETINT,
  130. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TISR);
  131. npcm7xx_to.clkevt.cpumask = cpumask_of(0);
  132. clockevents_config_and_register(&npcm7xx_to.clkevt,
  133. timer_of_rate(&npcm7xx_to),
  134. 0x1, NPCM7XX_Tx_MAX_CNT);
  135. }
  136. static void __init npcm7xx_clocksource_init(void)
  137. {
  138. u32 val;
  139. writel(NPCM7XX_DEFAULT_CSR,
  140. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
  141. writel(NPCM7XX_Tx_MAX_CNT,
  142. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TICR1);
  143. val = readl(timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
  144. val |= NPCM7XX_START_Tx;
  145. writel(val, timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
  146. clocksource_mmio_init(timer_of_base(&npcm7xx_to) +
  147. NPCM7XX_REG_TDR1,
  148. "npcm7xx-timer1", timer_of_rate(&npcm7xx_to),
  149. 200, (unsigned int)NPCM7XX_Tx_TDR_MASK_BITS,
  150. clocksource_mmio_readl_down);
  151. }
  152. static int __init npcm7xx_timer_init(struct device_node *np)
  153. {
  154. int ret;
  155. ret = timer_of_init(np, &npcm7xx_to);
  156. if (ret)
  157. return ret;
  158. /* Clock input is divided by PRESCALE + 1 before it is fed */
  159. /* to the counter */
  160. npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
  161. (NPCM7XX_Tx_MIN_PRESCALE + 1);
  162. npcm7xx_clocksource_init();
  163. npcm7xx_clockevents_init();
  164. pr_info("Enabling NPCM7xx clocksource timer base: %px, IRQ: %d ",
  165. timer_of_base(&npcm7xx_to), timer_of_irq(&npcm7xx_to));
  166. return 0;
  167. }
  168. TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init);