time-pistachio.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 u64 notrace
  59. pistachio_clocksource_read_cycles(struct clocksource *cs)
  60. {
  61. struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
  62. u32 counter, overflw;
  63. unsigned long flags;
  64. /*
  65. * The counter value is only refreshed after the overflow value is read.
  66. * And they must be read in strict order, hence raw spin lock added.
  67. */
  68. raw_spin_lock_irqsave(&pcs->lock, flags);
  69. overflw = gpt_readl(pcs->base, TIMER_CURRENT_OVERFLOW_VALUE, 0);
  70. counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0);
  71. raw_spin_unlock_irqrestore(&pcs->lock, flags);
  72. return (u64)~counter;
  73. }
  74. static u64 notrace pistachio_read_sched_clock(void)
  75. {
  76. return pistachio_clocksource_read_cycles(&pcs_gpt.cs);
  77. }
  78. static void pistachio_clksrc_set_mode(struct clocksource *cs, int timeridx,
  79. int enable)
  80. {
  81. struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
  82. u32 val;
  83. val = gpt_readl(pcs->base, TIMER_CFG, timeridx);
  84. if (enable)
  85. val |= TIMER_ME_LOCAL;
  86. else
  87. val &= ~TIMER_ME_LOCAL;
  88. gpt_writel(pcs->base, val, TIMER_CFG, timeridx);
  89. }
  90. static void pistachio_clksrc_enable(struct clocksource *cs, int timeridx)
  91. {
  92. struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
  93. /* Disable GPT local before loading reload value */
  94. pistachio_clksrc_set_mode(cs, timeridx, false);
  95. gpt_writel(pcs->base, RELOAD_VALUE, TIMER_RELOAD_VALUE, timeridx);
  96. pistachio_clksrc_set_mode(cs, timeridx, true);
  97. }
  98. static void pistachio_clksrc_disable(struct clocksource *cs, int timeridx)
  99. {
  100. /* Disable GPT local */
  101. pistachio_clksrc_set_mode(cs, timeridx, false);
  102. }
  103. static int pistachio_clocksource_enable(struct clocksource *cs)
  104. {
  105. pistachio_clksrc_enable(cs, 0);
  106. return 0;
  107. }
  108. static void pistachio_clocksource_disable(struct clocksource *cs)
  109. {
  110. pistachio_clksrc_disable(cs, 0);
  111. }
  112. /* Desirable clock source for pistachio platform */
  113. static struct pistachio_clocksource pcs_gpt = {
  114. .cs = {
  115. .name = "gptimer",
  116. .rating = 300,
  117. .enable = pistachio_clocksource_enable,
  118. .disable = pistachio_clocksource_disable,
  119. .read = pistachio_clocksource_read_cycles,
  120. .mask = CLOCKSOURCE_MASK(32),
  121. .flags = CLOCK_SOURCE_IS_CONTINUOUS |
  122. CLOCK_SOURCE_SUSPEND_NONSTOP,
  123. },
  124. };
  125. static int __init pistachio_clksrc_of_init(struct device_node *node)
  126. {
  127. struct clk *sys_clk, *fast_clk;
  128. struct regmap *periph_regs;
  129. unsigned long rate;
  130. int ret;
  131. pcs_gpt.base = of_iomap(node, 0);
  132. if (!pcs_gpt.base) {
  133. pr_err("cannot iomap\n");
  134. return -ENXIO;
  135. }
  136. periph_regs = syscon_regmap_lookup_by_phandle(node, "img,cr-periph");
  137. if (IS_ERR(periph_regs)) {
  138. pr_err("cannot get peripheral regmap (%ld)\n",
  139. PTR_ERR(periph_regs));
  140. return PTR_ERR(periph_regs);
  141. }
  142. /* Switch to using the fast counter clock */
  143. ret = regmap_update_bits(periph_regs, PERIP_TIMER_CONTROL,
  144. 0xf, 0x0);
  145. if (ret)
  146. return ret;
  147. sys_clk = of_clk_get_by_name(node, "sys");
  148. if (IS_ERR(sys_clk)) {
  149. pr_err("clock get failed (%ld)\n", PTR_ERR(sys_clk));
  150. return PTR_ERR(sys_clk);
  151. }
  152. fast_clk = of_clk_get_by_name(node, "fast");
  153. if (IS_ERR(fast_clk)) {
  154. pr_err("clock get failed (%lu)\n", PTR_ERR(fast_clk));
  155. return PTR_ERR(fast_clk);
  156. }
  157. ret = clk_prepare_enable(sys_clk);
  158. if (ret < 0) {
  159. pr_err("failed to enable clock (%d)\n", ret);
  160. return ret;
  161. }
  162. ret = clk_prepare_enable(fast_clk);
  163. if (ret < 0) {
  164. pr_err("failed to enable clock (%d)\n", ret);
  165. clk_disable_unprepare(sys_clk);
  166. return ret;
  167. }
  168. rate = clk_get_rate(fast_clk);
  169. /* Disable irq's for clocksource usage */
  170. gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 0);
  171. gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 1);
  172. gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 2);
  173. gpt_writel(pcs_gpt.base, 0, TIMER_IRQ_MASK, 3);
  174. /* Enable timer block */
  175. writel(TIMER_ME_GLOBAL, pcs_gpt.base);
  176. raw_spin_lock_init(&pcs_gpt.lock);
  177. sched_clock_register(pistachio_read_sched_clock, 32, rate);
  178. return clocksource_register_hz(&pcs_gpt.cs, rate);
  179. }
  180. TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
  181. pistachio_clksrc_of_init);