2 * J-Core SoC PIT/clocksource driver
4 * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
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
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>
22 #define PIT_IRQ_SHIFT 12
23 #define PIT_PRIO_SHIFT 20
24 #define PIT_ENABLE_SHIFT 26
25 #define PIT_PRIO_MASK 0xf
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
36 struct clock_event_device ced
;
38 unsigned long periodic_delta
;
42 static void __iomem
*jcore_pit_base
;
43 static struct jcore_pit __percpu
*jcore_pit_percpu
;
45 static notrace u64
jcore_sched_clock_read(void)
47 u32 seclo
, nsec
, seclo0
;
48 __iomem
void *base
= jcore_pit_base
;
50 seclo
= readl(base
+ REG_SECLO
);
53 nsec
= readl(base
+ REG_NSEC
);
54 seclo
= readl(base
+ REG_SECLO
);
55 } while (seclo0
!= seclo
);
57 return seclo
* NSEC_PER_SEC
+ nsec
;
60 static u64
jcore_clocksource_read(struct clocksource
*cs
)
62 return jcore_sched_clock_read();
65 static int jcore_pit_disable(struct jcore_pit
*pit
)
67 writel(0, pit
->base
+ REG_PITEN
);
71 static int jcore_pit_set(unsigned long delta
, struct jcore_pit
*pit
)
73 jcore_pit_disable(pit
);
74 writel(delta
, pit
->base
+ REG_THROT
);
75 writel(pit
->enable_val
, pit
->base
+ REG_PITEN
);
79 static int jcore_pit_set_state_shutdown(struct clock_event_device
*ced
)
81 struct jcore_pit
*pit
= container_of(ced
, struct jcore_pit
, ced
);
83 return jcore_pit_disable(pit
);
86 static int jcore_pit_set_state_oneshot(struct clock_event_device
*ced
)
88 struct jcore_pit
*pit
= container_of(ced
, struct jcore_pit
, ced
);
90 return jcore_pit_disable(pit
);
93 static int jcore_pit_set_state_periodic(struct clock_event_device
*ced
)
95 struct jcore_pit
*pit
= container_of(ced
, struct jcore_pit
, ced
);
97 return jcore_pit_set(pit
->periodic_delta
, pit
);
100 static int jcore_pit_set_next_event(unsigned long delta
,
101 struct clock_event_device
*ced
)
103 struct jcore_pit
*pit
= container_of(ced
, struct jcore_pit
, ced
);
105 return jcore_pit_set(delta
, pit
);
108 static int jcore_pit_local_init(unsigned cpu
)
110 struct jcore_pit
*pit
= this_cpu_ptr(jcore_pit_percpu
);
111 unsigned buspd
, freq
;
113 pr_info("Local J-Core PIT init on cpu %u\n", cpu
);
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
);
119 clockevents_config_and_register(&pit
->ced
, freq
, 1, ULONG_MAX
);
124 static irqreturn_t
jcore_timer_interrupt(int irq
, void *dev_id
)
126 struct jcore_pit
*pit
= this_cpu_ptr(dev_id
);
128 if (clockevent_state_oneshot(&pit
->ced
))
129 jcore_pit_disable(pit
);
131 pit
->ced
.event_handler(&pit
->ced
);
136 static int __init
jcore_pit_init(struct device_node
*node
)
139 unsigned pit_irq
, cpu
;
141 u32 irqprio
, enable_val
;
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");
149 pit_irq
= irq_of_parse_and_map(node
, 0);
151 pr_err("Error: J-Core PIT has no IRQ\n");
155 pr_info("Initializing J-Core PIT at %p IRQ %d\n",
156 jcore_pit_base
, pit_irq
);
158 err
= clocksource_mmio_init(jcore_pit_base
, "jcore_pit_cs",
159 NSEC_PER_SEC
, 400, 32,
160 jcore_clocksource_read
);
162 pr_err("Error registering clocksource device: %d\n", err
);
166 sched_clock_register(jcore_sched_clock_read
, 32, NSEC_PER_SEC
);
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");
174 err
= request_irq(pit_irq
, jcore_timer_interrupt
,
175 IRQF_TIMER
| IRQF_PERCPU
,
176 "jcore_pit", jcore_pit_percpu
);
178 pr_err("pit irq request failed: %d\n", err
);
179 free_percpu(jcore_pit_percpu
);
184 * The J-Core PIT is not hard-wired to a particular IRQ, but
185 * integrated with the interrupt controller such that the IRQ it
186 * generates is programmable, as follows:
188 * The bit layout of the PIT enable register is:
190 * .....e..ppppiiiiiiii............
192 * where the .'s indicate unrelated/unused bits, e is enable,
193 * p is priority, and i is hard irq number.
195 * For the PIT included in AIC1 (obsolete but still in use),
196 * any hard irq (trap number) can be programmed via the 8
197 * iiiiiiii bits, and a priority (0-15) is programmable
198 * separately in the pppp bits.
200 * For the PIT included in AIC2 (current), the programming
201 * interface is equivalent modulo interrupt mapping. This is
202 * why a different compatible tag was not used. However only
203 * traps 64-127 (the ones actually intended to be used for
204 * interrupts, rather than syscalls/exceptions/etc.) can be
205 * programmed (the high 2 bits of i are ignored) and the
206 * priority pppp is <<2'd and or'd onto the irq number. This
207 * choice seems to have been made on the hardware engineering
208 * side under an assumption that preserving old AIC1 priority
209 * mappings was important. Future models will likely ignore
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
);
218 for_each_present_cpu(cpu
) {
219 struct jcore_pit
*pit
= per_cpu_ptr(jcore_pit_percpu
, cpu
);
221 pit
->base
= of_iomap(node
, cpu
);
223 pr_err("Unable to map PIT for cpu %u\n", cpu
);
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
;
239 pit
->enable_val
= enable_val
;
242 cpuhp_setup_state(CPUHP_AP_JCORE_TIMER_STARTING
,
243 "clockevents/jcore:starting",
244 jcore_pit_local_init
, NULL
);
249 CLOCKSOURCE_OF_DECLARE(jcore_pit
, "jcore,pit", jcore_pit_init
);