timer-npcm7xx.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2014-2018 Nuvoton Technologies [email protected]
  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(28, 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 |= NPCM7XX_START_ONESHOT_Tx;
  73. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  74. return 0;
  75. }
  76. static int npcm7xx_timer_periodic(struct clock_event_device *evt)
  77. {
  78. struct timer_of *to = to_timer_of(evt);
  79. u32 val;
  80. writel(timer_of_period(to), timer_of_base(to) + NPCM7XX_REG_TICR0);
  81. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  82. val &= ~NPCM7XX_Tx_OPER;
  83. val |= NPCM7XX_START_PERIODIC_Tx;
  84. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  85. return 0;
  86. }
  87. static int npcm7xx_clockevent_set_next_event(unsigned long evt,
  88. struct clock_event_device *clk)
  89. {
  90. struct timer_of *to = to_timer_of(clk);
  91. u32 val;
  92. writel(evt, timer_of_base(to) + NPCM7XX_REG_TICR0);
  93. val = readl(timer_of_base(to) + NPCM7XX_REG_TCSR0);
  94. val |= NPCM7XX_START_Tx;
  95. writel(val, timer_of_base(to) + NPCM7XX_REG_TCSR0);
  96. return 0;
  97. }
  98. static irqreturn_t npcm7xx_timer0_interrupt(int irq, void *dev_id)
  99. {
  100. struct clock_event_device *evt = (struct clock_event_device *)dev_id;
  101. struct timer_of *to = to_timer_of(evt);
  102. writel(NPCM7XX_T0_CLR_INT, timer_of_base(to) + NPCM7XX_REG_TISR);
  103. evt->event_handler(evt);
  104. return IRQ_HANDLED;
  105. }
  106. static struct timer_of npcm7xx_to = {
  107. .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
  108. .clkevt = {
  109. .name = "npcm7xx-timer0",
  110. .features = CLOCK_EVT_FEAT_PERIODIC |
  111. CLOCK_EVT_FEAT_ONESHOT,
  112. .set_next_event = npcm7xx_clockevent_set_next_event,
  113. .set_state_shutdown = npcm7xx_timer_shutdown,
  114. .set_state_periodic = npcm7xx_timer_periodic,
  115. .set_state_oneshot = npcm7xx_timer_oneshot,
  116. .tick_resume = npcm7xx_timer_resume,
  117. .rating = 300,
  118. },
  119. .of_irq = {
  120. .handler = npcm7xx_timer0_interrupt,
  121. .flags = IRQF_TIMER | IRQF_IRQPOLL,
  122. },
  123. };
  124. static void __init npcm7xx_clockevents_init(void)
  125. {
  126. writel(NPCM7XX_DEFAULT_CSR,
  127. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR0);
  128. writel(NPCM7XX_Tx_RESETINT,
  129. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TISR);
  130. npcm7xx_to.clkevt.cpumask = cpumask_of(0);
  131. clockevents_config_and_register(&npcm7xx_to.clkevt,
  132. timer_of_rate(&npcm7xx_to),
  133. 0x1, NPCM7XX_Tx_MAX_CNT);
  134. }
  135. static void __init npcm7xx_clocksource_init(void)
  136. {
  137. u32 val;
  138. writel(NPCM7XX_DEFAULT_CSR,
  139. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
  140. writel(NPCM7XX_Tx_MAX_CNT,
  141. timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TICR1);
  142. val = readl(timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
  143. val |= NPCM7XX_START_Tx;
  144. writel(val, timer_of_base(&npcm7xx_to) + NPCM7XX_REG_TCSR1);
  145. clocksource_mmio_init(timer_of_base(&npcm7xx_to) +
  146. NPCM7XX_REG_TDR1,
  147. "npcm7xx-timer1", timer_of_rate(&npcm7xx_to),
  148. 200, (unsigned int)NPCM7XX_Tx_TDR_MASK_BITS,
  149. clocksource_mmio_readl_down);
  150. }
  151. static int __init npcm7xx_timer_init(struct device_node *np)
  152. {
  153. int ret;
  154. ret = timer_of_init(np, &npcm7xx_to);
  155. if (ret)
  156. return ret;
  157. /* Clock input is divided by PRESCALE + 1 before it is fed */
  158. /* to the counter */
  159. npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
  160. (NPCM7XX_Tx_MIN_PRESCALE + 1);
  161. npcm7xx_clocksource_init();
  162. npcm7xx_clockevents_init();
  163. pr_info("Enabling NPCM7xx clocksource timer base: %px, IRQ: %d ",
  164. timer_of_base(&npcm7xx_to), timer_of_irq(&npcm7xx_to));
  165. return 0;
  166. }
  167. TIMER_OF_DECLARE(wpcm450, "nuvoton,wpcm450-timer", npcm7xx_timer_init);
  168. TIMER_OF_DECLARE(npcm7xx, "nuvoton,npcm750-timer", npcm7xx_timer_init);