time-pistachio.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Pistachio clocksource based on general-purpose timers
  3. *
  4. * Copyright (C) 2015 Imagination Technologies
  5. *
  6. * This file is subject to the terms and conditions of the GNU General Public
  7. * License. See the file "COPYING" in the main directory of this archive
  8. * for more details.
  9. */
  10. #define pr_fmt(fmt) "%s: " fmt, __func__
  11. #include <linux/clk.h>
  12. #include <linux/clocksource.h>
  13. #include <linux/clockchips.h>
  14. #include <linux/delay.h>
  15. #include <linux/err.h>
  16. #include <linux/init.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/mfd/syscon.h>
  19. #include <linux/of.h>
  20. #include <linux/of_address.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/regmap.h>
  23. #include <linux/sched_clock.h>
  24. #include <linux/time.h>
  25. /* Top level reg */
  26. #define CR_TIMER_CTRL_CFG 0x00
  27. #define TIMER_ME_GLOBAL BIT(0)
  28. #define CR_TIMER_REV 0x10
  29. /* Timer specific registers */
  30. #define TIMER_CFG 0x20
  31. #define TIMER_ME_LOCAL BIT(0)
  32. #define TIMER_RELOAD_VALUE 0x24
  33. #define TIMER_CURRENT_VALUE 0x28
  34. #define TIMER_CURRENT_OVERFLOW_VALUE 0x2C
  35. #define TIMER_IRQ_STATUS 0x30
  36. #define TIMER_IRQ_CLEAR 0x34
  37. #define TIMER_IRQ_MASK 0x38
  38. #define PERIP_TIMER_CONTROL 0x90
  39. /* Timer specific configuration Values */
  40. #define RELOAD_VALUE 0xffffffff
  41. struct pistachio_clocksource {
  42. void __iomem *base;
  43. raw_spinlock_t lock;
  44. struct clocksource cs;
  45. };
  46. static struct pistachio_clocksource pcs_gpt;
  47. #define to_pistachio_clocksource(cs) \
  48. container_of(cs, struct pistachio_clocksource, cs)
  49. static inline u32 gpt_readl(void __iomem *base, u32 offset, u32 gpt_id)
  50. {
  51. return readl(base + 0x20 * gpt_id + offset);
  52. }
  53. static inline void gpt_writel(void __iomem *base, u32 value, u32 offset,
  54. u32 gpt_id)
  55. {
  56. writel(value, base + 0x20 * gpt_id + offset);
  57. }
  58. static cycle_t pistachio_clocksource_read_cycles(struct clocksource *cs)
  59. {
  60. struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
  61. u32 counter, overflw;
  62. unsigned long flags;
  63. /*
  64. * The counter value is only refreshed after the overflow value is read.
  65. * And they must be read in strict order, hence raw spin lock added.
  66. */
  67. raw_spin_lock_irqsave(&pcs->lock, flags);
  68. overflw = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0);
  69. counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0);
  70. raw_spin_unlock_irqrestore(&pcs->lock, flags);
  71. return ~(cycle_t)counter;
  72. }
  73. static u64 notrace pistachio_read_sched_clock(void)
  74. {
  75. return pistachio_clocksource_read_cycles(&pcs_gpt.cs);
  76. }
  77. static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx,
  78. int enable)
  79. {
  80. struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
  81. u32 val;
  82. val = gpt_readl(pcs->base, TIMER_CFG, timeridx);
  83. if (enable)
  84. val |= TIMER_ME_LOCAL;
  85. else
  86. val &= ~TIMER_ME_LOCAL;
  87. gpt_writel(pcs->base, val, TIMER_CFG, timeridx);
  88. }
  89. static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx)
  90. {
  91. struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
  92. /* Disable GPT local before loading reload value */
  93. pistachio_clksrc_set_mode(cs, timeridx, false);
  94. gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx);
  95. pistachio_clksrc_set_mode(cs, timeridx, true);
  96. }
  97. static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx)
  98. {
  99. /* Disable GPT local */
  100. pistachio_clksrc_set_mode(cs, timeridx, false);
  101. }
  102. static int pistachio_clocksource_enable(struct clocksource *cs)
  103. {
  104. pistachio_clksrc_enable(cs, 0);
  105. return 0;
  106. }
  107. static void pistachio_clocksource_disable(struct clocksource *cs)
  108. {
  109. pistachio_clksrc_disable(cs, 0);
  110. }
  111. /* Desirable clock source for pistachio platform */
  112. static struct pistachio_clocksource pcs_gpt = {
  113. .cs = {
  114. .name = "gptimer",
  115. .rating = 300,
  116. .enable = pistachio_clocksource_enable,
  117. .disable = pistachio_clocksource_disable,
  118. .read = pistachio_clocksource_read_cycles,
  119. .mask = CLOCKSOURCE_MASK(32),
  120. .flags = CLOCK_SOURCE_IS_CONTINUOUS |
  121. CLOCK_SOURCE_SUSPEND_NONSTOP,
  122. },
  123. };
  124. static void __init pistachio_clksrc_of_init(struct device_node *node)
  125. {
  126. struct clk *sys_clk, *fast_clk;
  127. struct regmap *periph_regs;
  128. unsigned long rate;
  129. int ret;
  130. pcs_gpt.base = of_iomap(node, 0);
  131. if (!pcs_gpt.base) {
  132. pr_err("cannot iomap\n");
  133. return;
  134. }
  135. periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph");
  136. if (IS_ERR(periph_regs)) {
  137. pr_err("cannot get peripheral regmap (%lu)\n",
  138. PTR_ERR(periph_regs));
  139. return;
  140. }
  141. /* Switch to using the fast counter clock */
  142. ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL,
  143. 0xf, 0x0);
  144. if (ret)
  145. return;
  146. sys_clk = of_clk_get_by_name(node, "sys");
  147. if (IS_ERR(sys_clk)) {
  148. pr_err("clock get failed (%lu)\n", PTR_ERR(sys_clk));
  149. return;
  150. }
  151. fast_clk = of_clk_get_by_name(node, "fast");
  152. if (IS_ERR(fast_clk)) {
  153. pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk));
  154. return;
  155. }
  156. ret = clk_prepare_enable(sys_clk);
  157. if (ret < 0) {
  158. pr_err("failed to enable clock (%d)\n", ret);
  159. return;
  160. }
  161. ret = clk_prepare_enable(fast_clk);
  162. if (ret < 0) {
  163. pr_err("failed to enable clock (%d)\n", ret);
  164. clk_disable_unprepare(sys_clk);
  165. return;
  166. }
  167. rate = clk_get_rate(fast_clk);
  168. /* Disable irq's for clocksource usage */
  169. gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 0);
  170. gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 1);
  171. gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 2);
  172. gpt_writel(&pcs_gpt.base, 0, TIMER_IRQ_MASK, 3);
  173. /* Enable timer block */
  174. writel(TIMER_ME_GLOBAL, pcs_gpt.base);
  175. raw_spin_lock_init(&pcs_gpt.lock);
  176. sched_clock_register(pistachio_read_sched_clock, 32, rate);
  177. clocksource_register_hz(&pcs_gpt.cs, rate);
  178. }
  179. CLOCKSOURCE_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
  180. pistachio_clksrc_of_init);