1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/clk.h>
18#include <linux/err.h>
19#include <linux/io.h>
20#include <linux/clocksource.h>
21#include <linux/sched_clock.h>
22
23#include <asm/mach/time.h>
24
25#include <plat/counter-32k.h>
26
27
28#define OMAP2_32KSYNCNT_REV_OFF 0x0
29#define OMAP2_32KSYNCNT_REV_SCHEME (0x3 << 30)
30#define OMAP2_32KSYNCNT_CR_OFF_LOW 0x10
31#define OMAP2_32KSYNCNT_CR_OFF_HIGH 0x30
32
33
34
35
36
37
38
39static void __iomem *sync32k_cnt_reg;
40
41static u64 notrace omap_32k_read_sched_clock(void)
42{
43 return sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0;
44}
45
46
47
48
49
50
51
52
53static struct timespec64 persistent_ts;
54static cycles_t cycles;
55static unsigned int persistent_mult, persistent_shift;
56
57static void omap_read_persistent_clock64(struct timespec64 *ts)
58{
59 unsigned long long nsecs;
60 cycles_t last_cycles;
61
62 last_cycles = cycles;
63 cycles = sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0;
64
65 nsecs = clocksource_cyc2ns(cycles - last_cycles,
66 persistent_mult, persistent_shift);
67
68 timespec64_add_ns(&persistent_ts, nsecs);
69
70 *ts = persistent_ts;
71}
72
73
74
75
76
77
78
79
80
81
82int __init omap_init_clocksource_32k(void __iomem *vbase)
83{
84 int ret;
85
86
87
88
89
90
91
92 if (readl_relaxed(vbase + OMAP2_32KSYNCNT_REV_OFF) &
93 OMAP2_32KSYNCNT_REV_SCHEME)
94 sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_HIGH;
95 else
96 sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_LOW;
97
98
99
100
101
102 clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
103 32768, NSEC_PER_SEC, 120000);
104
105 ret = clocksource_mmio_init(sync32k_cnt_reg, "32k_counter", 32768,
106 250, 32, clocksource_mmio_readl_up);
107 if (ret) {
108 pr_err("32k_counter: can't register clocksource\n");
109 return ret;
110 }
111
112 sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
113 register_persistent_clock(NULL, omap_read_persistent_clock64);
114 pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
115
116 return 0;
117}
118