86
86
.mask = CLOCKSOURCE_MASK(64),
87
.mult = 0, /* to be calculated */
89
87
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
91
89
static struct clocksource *hpet_clocksource;
165
163
* This has the effect of treating non-periodic like periodic.
167
165
if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) {
166
unsigned long m, t, mc, base, k;
167
struct hpet __iomem *hpet = devp->hd_hpet;
168
struct hpets *hpetp = devp->hd_hpets;
170
170
t = devp->hd_ireqfreq;
171
171
m = read_counter(&devp->hd_timer->hpet_compare);
172
write_counter(t + m, &devp->hd_timer->hpet_compare);
172
mc = read_counter(&hpet->hpet_mc);
173
/* The time for the next interrupt would logically be t + m,
174
* however, if we are very unlucky and the interrupt is delayed
175
* for longer than t then we will completely miss the next
176
* interrupt if we set t + m and an application will hang.
177
* Therefore we need to make a more complex computation assuming
178
* that there exists a k for which the following is true:
179
* k * t + base < mc + delta
180
* (k + 1) * t + base > mc + delta
181
* where t is the interval in hpet ticks for the given freq,
182
* base is the theoretical start value 0 < base < t,
183
* mc is the main counter value at the time of the interrupt,
184
* delta is the time it takes to write the a value to the
186
* k may then be computed as (mc - base + delta) / t .
189
k = (mc - base + hpetp->hp_delta) / t;
190
write_counter(t * (k + 1) + base,
191
&devp->hd_timer->hpet_compare);
175
194
if (devp->hd_flags & HPET_SHARED_IRQ)
934
953
if (!hpet_clocksource) {
935
954
hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
936
955
CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr);
937
clocksource_hpet.mult = clocksource_hz2mult(hpetp->hp_tick_freq,
938
clocksource_hpet.shift);
939
clocksource_register(&clocksource_hpet);
956
clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
940
957
hpetp->hp_clocksource = &clocksource_hpet;
941
958
hpet_clocksource = &clocksource_hpet;