timer-ti-32k.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /**
  3. * timer-ti-32k.c - OMAP2 32k Timer Support
  4. *
  5. * Copyright (C) 2009 Nokia Corporation
  6. *
  7. * Update to use new clocksource/clockevent layers
  8. * Author: Kevin Hilman, MontaVista Software, Inc. <[email protected]>
  9. * Copyright (C) 2007 MontaVista Software, Inc.
  10. *
  11. * Original driver:
  12. * Copyright (C) 2005 Nokia Corporation
  13. * Author: Paul Mundt <[email protected]>
  14. * Juha Yrjölä <[email protected]>
  15. * OMAP Dual-mode timer framework support by Timo Teras
  16. *
  17. * Some parts based off of TI's 24xx code:
  18. *
  19. * Copyright (C) 2004-2009 Texas Instruments, Inc.
  20. *
  21. * Roughly modelled after the OMAP1 MPU timer code.
  22. * Added OMAP4 support - Santosh Shilimkar <[email protected]>
  23. *
  24. * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com
  25. */
  26. #include <linux/clk.h>
  27. #include <linux/init.h>
  28. #include <linux/time.h>
  29. #include <linux/sched_clock.h>
  30. #include <linux/clocksource.h>
  31. #include <linux/of.h>
  32. #include <linux/of_address.h>
  33. /*
  34. * 32KHz clocksource ... always available, on pretty most chips except
  35. * OMAP 730 and 1510. Other timers could be used as clocksources, with
  36. * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
  37. * but systems won't necessarily want to spend resources that way.
  38. */
  39. #define OMAP2_32KSYNCNT_REV_OFF 0x0
  40. #define OMAP2_32KSYNCNT_REV_SCHEME (0x3 << 30)
  41. #define OMAP2_32KSYNCNT_CR_OFF_LOW 0x10
  42. #define OMAP2_32KSYNCNT_CR_OFF_HIGH 0x30
  43. struct ti_32k {
  44. void __iomem *base;
  45. void __iomem *counter;
  46. struct clocksource cs;
  47. };
  48. static inline struct ti_32k *to_ti_32k(struct clocksource *cs)
  49. {
  50. return container_of(cs, struct ti_32k, cs);
  51. }
  52. static u64 notrace ti_32k_read_cycles(struct clocksource *cs)
  53. {
  54. struct ti_32k *ti = to_ti_32k(cs);
  55. return (u64)readl_relaxed(ti->counter);
  56. }
  57. static struct ti_32k ti_32k_timer = {
  58. .cs = {
  59. .name = "32k_counter",
  60. .rating = 250,
  61. .read = ti_32k_read_cycles,
  62. .mask = CLOCKSOURCE_MASK(32),
  63. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  64. },
  65. };
  66. static u64 notrace omap_32k_read_sched_clock(void)
  67. {
  68. return ti_32k_read_cycles(&ti_32k_timer.cs);
  69. }
  70. static void __init ti_32k_timer_enable_clock(struct device_node *np,
  71. const char *name)
  72. {
  73. struct clk *clock;
  74. int error;
  75. clock = of_clk_get_by_name(np->parent, name);
  76. if (IS_ERR(clock)) {
  77. /* Only some SoCs have a separate interface clock */
  78. if (PTR_ERR(clock) == -EINVAL && !strncmp("ick", name, 3))
  79. return;
  80. pr_warn("%s: could not get clock %s %li\n",
  81. __func__, name, PTR_ERR(clock));
  82. return;
  83. }
  84. error = clk_prepare_enable(clock);
  85. if (error) {
  86. pr_warn("%s: could not enable %s: %i\n",
  87. __func__, name, error);
  88. return;
  89. }
  90. }
  91. static void __init ti_32k_timer_module_init(struct device_node *np,
  92. void __iomem *base)
  93. {
  94. void __iomem *sysc = base + 4;
  95. if (!of_device_is_compatible(np->parent, "ti,sysc"))
  96. return;
  97. ti_32k_timer_enable_clock(np, "fck");
  98. ti_32k_timer_enable_clock(np, "ick");
  99. /*
  100. * Force idle module as wkup domain is active with MPU.
  101. * No need to tag the module disabled for ti-sysc probe.
  102. */
  103. writel_relaxed(0, sysc);
  104. }
  105. static int __init ti_32k_timer_init(struct device_node *np)
  106. {
  107. int ret;
  108. ti_32k_timer.base = of_iomap(np, 0);
  109. if (!ti_32k_timer.base) {
  110. pr_err("Can't ioremap 32k timer base\n");
  111. return -ENXIO;
  112. }
  113. if (!of_machine_is_compatible("ti,am43"))
  114. ti_32k_timer.cs.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
  115. ti_32k_timer.counter = ti_32k_timer.base;
  116. ti_32k_timer_module_init(np, ti_32k_timer.base);
  117. /*
  118. * 32k sync Counter IP register offsets vary between the highlander
  119. * version and the legacy ones.
  120. *
  121. * The 'SCHEME' bits(30-31) of the revision register is used to identify
  122. * the version.
  123. */
  124. if (readl_relaxed(ti_32k_timer.base + OMAP2_32KSYNCNT_REV_OFF) &
  125. OMAP2_32KSYNCNT_REV_SCHEME)
  126. ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_HIGH;
  127. else
  128. ti_32k_timer.counter += OMAP2_32KSYNCNT_CR_OFF_LOW;
  129. pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
  130. ret = clocksource_register_hz(&ti_32k_timer.cs, 32768);
  131. if (ret) {
  132. pr_err("32k_counter: can't register clocksource\n");
  133. return ret;
  134. }
  135. sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
  136. return 0;
  137. }
  138. TIMER_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",
  139. ti_32k_timer_init);