This source file includes following definitions.
- jcore_sched_clock_read
- jcore_clocksource_read
- jcore_pit_disable
- jcore_pit_set
- jcore_pit_set_state_shutdown
- jcore_pit_set_state_oneshot
- jcore_pit_set_state_periodic
- jcore_pit_set_next_event
- jcore_pit_local_init
- jcore_timer_interrupt
- jcore_pit_init
1
2
3
4
5
6
7
8
9
10
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <linux/interrupt.h>
14 #include <linux/clockchips.h>
15 #include <linux/clocksource.h>
16 #include <linux/sched_clock.h>
17 #include <linux/cpu.h>
18 #include <linux/cpuhotplug.h>
19 #include <linux/of_address.h>
20 #include <linux/of_irq.h>
21
22 #define PIT_IRQ_SHIFT 12
23 #define PIT_PRIO_SHIFT 20
24 #define PIT_ENABLE_SHIFT 26
25 #define PIT_PRIO_MASK 0xf
26
27 #define REG_PITEN 0x00
28 #define REG_THROT 0x10
29 #define REG_COUNT 0x14
30 #define REG_BUSPD 0x18
31 #define REG_SECHI 0x20
32 #define REG_SECLO 0x24
33 #define REG_NSEC 0x28
34
35 struct jcore_pit {
36 struct clock_event_device ced;
37 void __iomem *base;
38 unsigned long periodic_delta;
39 u32 enable_val;
40 };
41
42 static void __iomem *jcore_pit_base;
43 static struct jcore_pit __percpu *jcore_pit_percpu;
44
45 static notrace u64 jcore_sched_clock_read(void)
46 {
47 u32 seclo, nsec, seclo0;
48 __iomem void *base = jcore_pit_base;
49
50 seclo = readl(base + REG_SECLO);
51 do {
52 seclo0 = seclo;
53 nsec = readl(base + REG_NSEC);
54 seclo = readl(base + REG_SECLO);
55 } while (seclo0 != seclo);
56
57 return seclo * NSEC_PER_SEC + nsec;
58 }
59
60 static u64 jcore_clocksource_read(struct clocksource *cs)
61 {
62 return jcore_sched_clock_read();
63 }
64
65 static int jcore_pit_disable(struct jcore_pit *pit)
66 {
67 writel(0, pit->base + REG_PITEN);
68 return 0;
69 }
70
71 static int jcore_pit_set(unsigned long delta, struct jcore_pit *pit)
72 {
73 jcore_pit_disable(pit);
74 writel(delta, pit->base + REG_THROT);
75 writel(pit->enable_val, pit->base + REG_PITEN);
76 return 0;
77 }
78
79 static int jcore_pit_set_state_shutdown(struct clock_event_device *ced)
80 {
81 struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
82
83 return jcore_pit_disable(pit);
84 }
85
86 static int jcore_pit_set_state_oneshot(struct clock_event_device *ced)
87 {
88 struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
89
90 return jcore_pit_disable(pit);
91 }
92
93 static int jcore_pit_set_state_periodic(struct clock_event_device *ced)
94 {
95 struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
96
97 return jcore_pit_set(pit->periodic_delta, pit);
98 }
99
100 static int jcore_pit_set_next_event(unsigned long delta,
101 struct clock_event_device *ced)
102 {
103 struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
104
105 return jcore_pit_set(delta, pit);
106 }
107
108 static int jcore_pit_local_init(unsigned cpu)
109 {
110 struct jcore_pit *pit = this_cpu_ptr(jcore_pit_percpu);
111 unsigned buspd, freq;
112
113 pr_info("Local J-Core PIT init on cpu %u\n", cpu);
114
115 buspd = readl(pit->base + REG_BUSPD);
116 freq = DIV_ROUND_CLOSEST(NSEC_PER_SEC, buspd);
117 pit->periodic_delta = DIV_ROUND_CLOSEST(NSEC_PER_SEC, HZ * buspd);
118
119 clockevents_config_and_register(&pit->ced, freq, 1, ULONG_MAX);
120
121 return 0;
122 }
123
124 static irqreturn_t jcore_timer_interrupt(int irq, void *dev_id)
125 {
126 struct jcore_pit *pit = this_cpu_ptr(dev_id);
127
128 if (clockevent_state_oneshot(&pit->ced))
129 jcore_pit_disable(pit);
130
131 pit->ced.event_handler(&pit->ced);
132
133 return IRQ_HANDLED;
134 }
135
136 static int __init jcore_pit_init(struct device_node *node)
137 {
138 int err;
139 unsigned pit_irq, cpu;
140 unsigned long hwirq;
141 u32 irqprio, enable_val;
142
143 jcore_pit_base = of_iomap(node, 0);
144 if (!jcore_pit_base) {
145 pr_err("Error: Cannot map base address for J-Core PIT\n");
146 return -ENXIO;
147 }
148
149 pit_irq = irq_of_parse_and_map(node, 0);
150 if (!pit_irq) {
151 pr_err("Error: J-Core PIT has no IRQ\n");
152 return -ENXIO;
153 }
154
155 pr_info("Initializing J-Core PIT at %p IRQ %d\n",
156 jcore_pit_base, pit_irq);
157
158 err = clocksource_mmio_init(jcore_pit_base, "jcore_pit_cs",
159 NSEC_PER_SEC, 400, 32,
160 jcore_clocksource_read);
161 if (err) {
162 pr_err("Error registering clocksource device: %d\n", err);
163 return err;
164 }
165
166 sched_clock_register(jcore_sched_clock_read, 32, NSEC_PER_SEC);
167
168 jcore_pit_percpu = alloc_percpu(struct jcore_pit);
169 if (!jcore_pit_percpu) {
170 pr_err("Failed to allocate memory for clock event device\n");
171 return -ENOMEM;
172 }
173
174 err = request_irq(pit_irq, jcore_timer_interrupt,
175 IRQF_TIMER | IRQF_PERCPU,
176 "jcore_pit", jcore_pit_percpu);
177 if (err) {
178 pr_err("pit irq request failed: %d\n", err);
179 free_percpu(jcore_pit_percpu);
180 return err;
181 }
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 hwirq = irq_get_irq_data(pit_irq)->hwirq;
213 irqprio = (hwirq >> 2) & PIT_PRIO_MASK;
214 enable_val = (1U << PIT_ENABLE_SHIFT)
215 | (hwirq << PIT_IRQ_SHIFT)
216 | (irqprio << PIT_PRIO_SHIFT);
217
218 for_each_present_cpu(cpu) {
219 struct jcore_pit *pit = per_cpu_ptr(jcore_pit_percpu, cpu);
220
221 pit->base = of_iomap(node, cpu);
222 if (!pit->base) {
223 pr_err("Unable to map PIT for cpu %u\n", cpu);
224 continue;
225 }
226
227 pit->ced.name = "jcore_pit";
228 pit->ced.features = CLOCK_EVT_FEAT_PERIODIC
229 | CLOCK_EVT_FEAT_ONESHOT
230 | CLOCK_EVT_FEAT_PERCPU;
231 pit->ced.cpumask = cpumask_of(cpu);
232 pit->ced.rating = 400;
233 pit->ced.irq = pit_irq;
234 pit->ced.set_state_shutdown = jcore_pit_set_state_shutdown;
235 pit->ced.set_state_periodic = jcore_pit_set_state_periodic;
236 pit->ced.set_state_oneshot = jcore_pit_set_state_oneshot;
237 pit->ced.set_next_event = jcore_pit_set_next_event;
238
239 pit->enable_val = enable_val;
240 }
241
242 cpuhp_setup_state(CPUHP_AP_JCORE_TIMER_STARTING,
243 "clockevents/jcore:starting",
244 jcore_pit_local_init, NULL);
245
246 return 0;
247 }
248
249 TIMER_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init);