This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / char / hpet.c
1 /*
2  * Intel & MS High Precision Event Timer Implementation.
3  * Contributors:
4  *      Venki Pallipadi
5  *      Bob Picco
6  */
7
8 #include <linux/config.h>
9 #include <linux/interrupt.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <linux/miscdevice.h>
14 #include <linux/major.h>
15 #include <linux/ioport.h>
16 #include <linux/fcntl.h>
17 #include <linux/init.h>
18 #include <linux/poll.h>
19 #include <linux/proc_fs.h>
20 #include <linux/spinlock.h>
21 #include <linux/sysctl.h>
22 #include <linux/wait.h>
23 #include <linux/bcd.h>
24 #include <linux/seq_file.h>
25
26 #include <asm/current.h>
27 #include <asm/uaccess.h>
28 #include <asm/system.h>
29 #include <asm/io.h>
30 #include <asm/irq.h>
31 #include <asm/bitops.h>
32 #include <asm/div64.h>
33
34 #include <linux/acpi.h>
35 #include <acpi/acpi_bus.h>
36 #include <linux/hpet.h>
37
38 /*
39  * The High Precision Event Timer driver.
40  * This driver is closely modelled after the rtc.c driver.
41  * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm
42  */
43 #define HPET_USER_FREQ  (64)
44 #define HPET_DRIFT      (500)
45
46 static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
47
48 /* A lock for concurrent access by app and isr hpet activity. */
49 static spinlock_t hpet_lock = SPIN_LOCK_UNLOCKED;
50 /* A lock for concurrent intermodule access to hpet and isr hpet activity. */
51 static spinlock_t hpet_task_lock = SPIN_LOCK_UNLOCKED;
52
53 #define HPET_DEV_NAME   (7)
54
55 struct hpet_dev {
56         struct hpets *hd_hpets;
57         struct hpet *hd_hpet;
58         struct hpet_timer *hd_timer;
59         unsigned long hd_ireqfreq;
60         unsigned long hd_irqdata;
61         wait_queue_head_t hd_waitqueue;
62         struct fasync_struct *hd_async_queue;
63         struct hpet_task *hd_task;
64         unsigned int hd_flags;
65         unsigned int hd_irq;
66         unsigned int hd_hdwirq;
67         char hd_name[HPET_DEV_NAME];
68 };
69
70 struct hpets {
71         struct hpets *hp_next;
72         struct hpet *hp_hpet;
73         unsigned long hp_period;
74         unsigned long hp_delta;
75         unsigned int hp_ntimer;
76         unsigned int hp_which;
77         struct hpet_dev hp_dev[1];
78 };
79
80 static struct hpets *hpets;
81
82 #define HPET_OPEN               0x0001
83 #define HPET_IE                 0x0002  /* interrupt enabled */
84 #define HPET_PERIODIC           0x0004
85
86 #if BITS_PER_LONG == 64
87 #define write_counter(V, MC)    writeq(V, MC)
88 #define read_counter(MC)        readq(MC)
89 #else
90 #define write_counter(V, MC)    writel(V, MC)
91 #define read_counter(MC)        readl(MC)
92 #endif
93
94 #ifndef readq
95 static unsigned long long __inline readq(void *addr)
96 {
97         return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
98 }
99 #endif
100
101 #ifndef writeq
102 static void __inline writeq(unsigned long long v, void *addr)
103 {
104         writel(v & 0xffffffff, addr);
105         writel(v >> 32, addr + 4);
106 }
107 #endif
108
109 static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
110 {
111         struct hpet_dev *devp;
112         unsigned long isr;
113
114         devp = data;
115
116         spin_lock(&hpet_lock);
117         devp->hd_irqdata++;
118
119         /*
120          * For non-periodic timers, increment the accumulator.
121          * This has the effect of treating non-periodic like periodic.
122          */
123         if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) {
124                 unsigned long m, t;
125
126                 t = devp->hd_ireqfreq;
127                 m = read_counter(&devp->hd_hpet->hpet_mc);
128                 write_counter(t + m + devp->hd_hpets->hp_delta,
129                               &devp->hd_timer->hpet_compare);
130         }
131
132         isr = (1 << (devp - devp->hd_hpets->hp_dev));
133         writeq(isr, &devp->hd_hpet->hpet_isr);
134         spin_unlock(&hpet_lock);
135
136         spin_lock(&hpet_task_lock);
137         if (devp->hd_task)
138                 devp->hd_task->ht_func(devp->hd_task->ht_data);
139         spin_unlock(&hpet_task_lock);
140
141         wake_up_interruptible(&devp->hd_waitqueue);
142
143         kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
144
145         return IRQ_HANDLED;
146 }
147
148 static int hpet_open(struct inode *inode, struct file *file)
149 {
150         struct hpet_dev *devp;
151         struct hpets *hpetp;
152         int i;
153
154         if (file->f_mode & FMODE_WRITE)
155                 return -EINVAL;
156
157         spin_lock_irq(&hpet_lock);
158
159         for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
160                 for (i = 0; i < hpetp->hp_ntimer; i++)
161                         if (hpetp->hp_dev[i].hd_flags & HPET_OPEN
162                             || hpetp->hp_dev[i].hd_task)
163                                 continue;
164                         else {
165                                 devp = &hpetp->hp_dev[i];
166                                 break;
167                         }
168
169         if (!devp) {
170                 spin_unlock_irq(&hpet_lock);
171                 return -EBUSY;
172         }
173
174         file->private_data = devp;
175         devp->hd_irqdata = 0;
176         devp->hd_flags |= HPET_OPEN;
177         spin_unlock_irq(&hpet_lock);
178
179         return 0;
180 }
181
182 static ssize_t
183 hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
184 {
185         DECLARE_WAITQUEUE(wait, current);
186         unsigned long data;
187         ssize_t retval;
188         struct hpet_dev *devp;
189
190         devp = file->private_data;
191         if (!devp->hd_ireqfreq)
192                 return -EIO;
193
194         if (count < sizeof(unsigned long))
195                 return -EINVAL;
196
197         add_wait_queue(&devp->hd_waitqueue, &wait);
198
199         for ( ; ; ) {
200                 set_current_state(TASK_INTERRUPTIBLE);
201
202                 spin_lock_irq(&hpet_lock);
203                 data = devp->hd_irqdata;
204                 devp->hd_irqdata = 0;
205                 spin_unlock_irq(&hpet_lock);
206
207                 if (data)
208                         break;
209                 else if (file->f_flags & O_NONBLOCK) {
210                         retval = -EAGAIN;
211                         goto out;
212                 } else if (signal_pending(current)) {
213                         retval = -ERESTARTSYS;
214                         goto out;
215                 }
216                 schedule();
217         }
218
219         retval = put_user(data, (unsigned long __user *)buf);
220         if (!retval)
221                 retval = sizeof(unsigned long);
222 out:
223         __set_current_state(TASK_RUNNING);
224         remove_wait_queue(&devp->hd_waitqueue, &wait);
225
226         return retval;
227 }
228
229 static unsigned int hpet_poll(struct file *file, poll_table * wait)
230 {
231         unsigned long v;
232         struct hpet_dev *devp;
233
234         devp = file->private_data;
235
236         if (!devp->hd_ireqfreq)
237                 return 0;
238
239         poll_wait(file, &devp->hd_waitqueue, wait);
240
241         spin_lock_irq(&hpet_lock);
242         v = devp->hd_irqdata;
243         spin_unlock_irq(&hpet_lock);
244
245         if (v != 0)
246                 return POLLIN | POLLRDNORM;
247
248         return 0;
249 }
250
251 static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
252 {
253 #ifdef  CONFIG_HPET_NOMMAP
254         return -ENOSYS;
255 #else
256         struct hpet_dev *devp;
257         unsigned long addr;
258
259         if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
260                 return -EINVAL;
261
262         devp = file->private_data;
263         addr = (unsigned long)devp->hd_hpet;
264
265         if (addr & (PAGE_SIZE - 1))
266                 return -ENOSYS;
267
268         vma->vm_flags |= VM_IO;
269         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
270         addr = __pa(addr);
271
272         if (remap_page_range
273             (vma, vma->vm_start, addr, PAGE_SIZE, vma->vm_page_prot)) {
274                 printk(KERN_ERR "remap_page_range failed in hpet.c\n");
275                 return -EAGAIN;
276         }
277
278         return 0;
279 #endif
280 }
281
282 static int hpet_fasync(int fd, struct file *file, int on)
283 {
284         struct hpet_dev *devp;
285
286         devp = file->private_data;
287
288         if (fasync_helper(fd, file, on, &devp->hd_async_queue) >= 0)
289                 return 0;
290         else
291                 return -EIO;
292 }
293
294 static int hpet_release(struct inode *inode, struct file *file)
295 {
296         struct hpet_dev *devp;
297         struct hpet_timer *timer;
298         int irq = 0;
299
300         devp = file->private_data;
301         timer = devp->hd_timer;
302
303         spin_lock_irq(&hpet_lock);
304
305         writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
306                &timer->hpet_config);
307
308         irq = devp->hd_irq;
309         devp->hd_irq = 0;
310
311         devp->hd_ireqfreq = 0;
312
313         if (devp->hd_flags & HPET_PERIODIC
314             && readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) {
315                 unsigned long v;
316
317                 v = readq(&timer->hpet_config);
318                 v ^= Tn_TYPE_CNF_MASK;
319                 writeq(v, &timer->hpet_config);
320         }
321
322         devp->hd_flags &= ~(HPET_OPEN | HPET_IE | HPET_PERIODIC);
323         spin_unlock_irq(&hpet_lock);
324
325         if (irq)
326                 free_irq(irq, devp);
327
328         if (file->f_flags & FASYNC)
329                 hpet_fasync(-1, file, 0);
330
331         file->private_data = NULL;
332         return 0;
333 }
334
335 static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int);
336
337 static int
338 hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
339            unsigned long arg)
340 {
341         struct hpet_dev *devp;
342
343         devp = file->private_data;
344         return hpet_ioctl_common(devp, cmd, arg, 0);
345 }
346
347 static int hpet_ioctl_ieon(struct hpet_dev *devp)
348 {
349         struct hpet_timer *timer;
350         struct hpet *hpet;
351         struct hpets *hpetp;
352         int irq;
353         unsigned long g, v, t, m;
354         unsigned long flags, isr;
355
356         timer = devp->hd_timer;
357         hpet = devp->hd_hpet;
358         hpetp = devp->hd_hpets;
359
360         v = readq(&timer->hpet_config);
361         spin_lock_irq(&hpet_lock);
362
363         if (devp->hd_flags & HPET_IE) {
364                 spin_unlock_irq(&hpet_lock);
365                 return -EBUSY;
366         }
367
368         devp->hd_flags |= HPET_IE;
369         spin_unlock_irq(&hpet_lock);
370
371         t = readq(&timer->hpet_config);
372         irq = devp->hd_hdwirq;
373
374         if (irq) {
375                 sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
376
377                 if (request_irq
378                     (irq, hpet_interrupt, SA_INTERRUPT, devp->hd_name, (void *)devp)) {
379                         printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
380                         irq = 0;
381                 }
382         }
383
384         if (irq == 0) {
385                 spin_lock_irq(&hpet_lock);
386                 devp->hd_flags ^= HPET_IE;
387                 spin_unlock_irq(&hpet_lock);
388                 return -EIO;
389         }
390
391         devp->hd_irq = irq;
392         t = devp->hd_ireqfreq;
393         v = readq(&timer->hpet_config);
394         g = v | Tn_INT_ENB_CNF_MASK;
395
396         if (devp->hd_flags & HPET_PERIODIC) {
397                 write_counter(t, &timer->hpet_compare);
398                 g |= Tn_TYPE_CNF_MASK;
399                 v |= Tn_TYPE_CNF_MASK;
400                 writeq(v, &timer->hpet_config);
401                 v |= Tn_VAL_SET_CNF_MASK;
402                 writeq(v, &timer->hpet_config);
403                 local_irq_save(flags);
404                 m = read_counter(&hpet->hpet_mc);
405                 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
406         } else {
407                 local_irq_save(flags);
408                 m = read_counter(&hpet->hpet_mc);
409                 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
410         }
411
412         isr = (1 << (devp - hpets->hp_dev));
413         writeq(isr, &hpet->hpet_isr);
414         writeq(g, &timer->hpet_config);
415         local_irq_restore(flags);
416
417         return 0;
418 }
419
420 static inline unsigned long hpet_time_div(unsigned long dis)
421 {
422         unsigned long long m = 1000000000000000ULL;
423
424         do_div(m, dis);
425
426         return (unsigned long)m;
427 }
428
429 static int
430 hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
431 {
432         struct hpet_timer *timer;
433         struct hpet *hpet;
434         struct hpets *hpetp;
435         int err;
436         unsigned long v;
437
438         switch (cmd) {
439         case HPET_IE_OFF:
440         case HPET_INFO:
441         case HPET_EPI:
442         case HPET_DPI:
443         case HPET_IRQFREQ:
444                 timer = devp->hd_timer;
445                 hpet = devp->hd_hpet;
446                 hpetp = devp->hd_hpets;
447                 break;
448         case HPET_IE_ON:
449                 return hpet_ioctl_ieon(devp);
450         default:
451                 return -EINVAL;
452         }
453
454         err = 0;
455
456         switch (cmd) {
457         case HPET_IE_OFF:
458                 if ((devp->hd_flags & HPET_IE) == 0)
459                         break;
460                 v = readq(&timer->hpet_config);
461                 v &= ~Tn_INT_ENB_CNF_MASK;
462                 writeq(v, &timer->hpet_config);
463                 if (devp->hd_irq) {
464                         free_irq(devp->hd_irq, devp);
465                         devp->hd_irq = 0;
466                 }
467                 devp->hd_flags ^= HPET_IE;
468                 break;
469         case HPET_INFO:
470                 {
471                         struct hpet_info info;
472
473                         info.hi_ireqfreq = hpet_time_div(hpetp->hp_period *
474                                                          devp->hd_ireqfreq);
475                         info.hi_flags =
476                             readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
477                         info.hi_hpet = devp->hd_hpets->hp_which;
478                         info.hi_timer = devp - devp->hd_hpets->hp_dev;
479                         if (copy_to_user((void __user *)arg, &info, sizeof(info)))
480                                 err = -EFAULT;
481                         break;
482                 }
483         case HPET_EPI:
484                 v = readq(&timer->hpet_config);
485                 if ((v & Tn_PER_INT_CAP_MASK) == 0) {
486                         err = -ENXIO;
487                         break;
488                 }
489                 devp->hd_flags |= HPET_PERIODIC;
490                 break;
491         case HPET_DPI:
492                 v = readq(&timer->hpet_config);
493                 if ((v & Tn_PER_INT_CAP_MASK) == 0) {
494                         err = -ENXIO;
495                         break;
496                 }
497                 if (devp->hd_flags & HPET_PERIODIC &&
498                     readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) {
499                         v = readq(&timer->hpet_config);
500                         v ^= Tn_TYPE_CNF_MASK;
501                         writeq(v, &timer->hpet_config);
502                 }
503                 devp->hd_flags &= ~HPET_PERIODIC;
504                 break;
505         case HPET_IRQFREQ:
506                 if (!kernel && (arg > hpet_max_freq) &&
507                     !capable(CAP_SYS_RESOURCE)) {
508                         err = -EACCES;
509                         break;
510                 }
511
512                 if (arg & (arg - 1)) {
513                         err = -EINVAL;
514                         break;
515                 }
516
517                 devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg);
518         }
519
520         return err;
521 }
522
523 static struct file_operations hpet_fops = {
524         .owner = THIS_MODULE,
525         .llseek = no_llseek,
526         .read = hpet_read,
527         .poll = hpet_poll,
528         .ioctl = hpet_ioctl,
529         .open = hpet_open,
530         .release = hpet_release,
531         .fasync = hpet_fasync,
532         .mmap = hpet_mmap,
533 };
534
535 EXPORT_SYMBOL(hpet_alloc);
536 EXPORT_SYMBOL(hpet_register);
537 EXPORT_SYMBOL(hpet_unregister);
538 EXPORT_SYMBOL(hpet_control);
539
540 int hpet_register(struct hpet_task *tp, int periodic)
541 {
542         unsigned int i;
543         u64 mask;
544         struct hpet_timer *timer;
545         struct hpet_dev *devp;
546         struct hpets *hpetp;
547
548         switch (periodic) {
549         case 1:
550                 mask = Tn_PER_INT_CAP_MASK;
551                 break;
552         case 0:
553                 mask = 0;
554                 break;
555         default:
556                 return -EINVAL;
557         }
558
559         spin_lock_irq(&hpet_task_lock);
560         spin_lock(&hpet_lock);
561
562         for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
563                 for (timer = hpetp->hp_hpet->hpet_timers, i = 0;
564                      i < hpetp->hp_ntimer; i++, timer++) {
565                         if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK)
566                             != mask)
567                                 continue;
568
569                         devp = &hpetp->hp_dev[i];
570
571                         if (devp->hd_flags & HPET_OPEN || devp->hd_task) {
572                                 devp = NULL;
573                                 continue;
574                         }
575
576                         tp->ht_opaque = devp;
577                         devp->hd_task = tp;
578                         break;
579                 }
580
581         spin_unlock(&hpet_lock);
582         spin_unlock_irq(&hpet_task_lock);
583
584         if (tp->ht_opaque)
585                 return 0;
586         else
587                 return -EBUSY;
588 }
589
590 static inline int hpet_tpcheck(struct hpet_task *tp)
591 {
592         struct hpet_dev *devp;
593         struct hpets *hpetp;
594
595         devp = tp->ht_opaque;
596
597         if (!devp)
598                 return -ENXIO;
599
600         for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
601                 if (devp >= hpetp->hp_dev
602                     && devp < (hpetp->hp_dev + hpetp->hp_ntimer)
603                     && devp->hd_hpet == hpetp->hp_hpet)
604                         return 0;
605
606         return -ENXIO;
607 }
608
609 int hpet_unregister(struct hpet_task *tp)
610 {
611         struct hpet_dev *devp;
612         struct hpet_timer *timer;
613         int err;
614
615         if ((err = hpet_tpcheck(tp)))
616                 return err;
617
618         spin_lock_irq(&hpet_task_lock);
619         spin_lock(&hpet_lock);
620
621         devp = tp->ht_opaque;
622         if (devp->hd_task != tp) {
623                 spin_unlock(&hpet_lock);
624                 spin_unlock_irq(&hpet_task_lock);
625                 return -ENXIO;
626         }
627
628         timer = devp->hd_timer;
629         writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
630                &timer->hpet_config);
631         devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
632         devp->hd_task = NULL;
633         spin_unlock(&hpet_lock);
634         spin_unlock_irq(&hpet_task_lock);
635
636         return 0;
637 }
638
639 int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
640 {
641         struct hpet_dev *devp;
642         int err;
643
644         if ((err = hpet_tpcheck(tp)))
645                 return err;
646
647         spin_lock_irq(&hpet_lock);
648         devp = tp->ht_opaque;
649         if (devp->hd_task != tp) {
650                 spin_unlock_irq(&hpet_lock);
651                 return -ENXIO;
652         }
653         spin_unlock_irq(&hpet_lock);
654         return hpet_ioctl_common(devp, cmd, arg, 1);
655 }
656
657 #ifdef  CONFIG_TIME_INTERPOLATION
658
659 static unsigned long hpet_offset, last_wall_hpet;
660 static long hpet_nsecs_per_cycle, hpet_cycles_per_sec;
661
662 static unsigned long hpet_getoffset(void)
663 {
664         return hpet_offset + (read_counter(&hpets->hp_hpet->hpet_mc) -
665                               last_wall_hpet) * hpet_nsecs_per_cycle;
666 }
667
668 static void hpet_update(long delta)
669 {
670         unsigned long mc;
671         unsigned long offset;
672
673         mc = read_counter(&hpets->hp_hpet->hpet_mc);
674         offset = hpet_offset + (mc - last_wall_hpet) * hpet_nsecs_per_cycle;
675
676         if (delta < 0 || (unsigned long)delta < offset)
677                 hpet_offset = offset - delta;
678         else
679                 hpet_offset = 0;
680         last_wall_hpet = mc;
681 }
682
683 static void hpet_reset(void)
684 {
685         hpet_offset = 0;
686         last_wall_hpet = read_counter(&hpets->hp_hpet->hpet_mc);
687 }
688
689 static struct time_interpolator hpet_interpolator = {
690         .get_offset = hpet_getoffset,
691         .update = hpet_update,
692         .reset = hpet_reset
693 };
694
695 #endif
696
697 static ctl_table hpet_table[] = {
698         {
699          .ctl_name = 1,
700          .procname = "max-user-freq",
701          .data = &hpet_max_freq,
702          .maxlen = sizeof(int),
703          .mode = 0644,
704          .proc_handler = &proc_dointvec,
705          },
706         {.ctl_name = 0}
707 };
708
709 static ctl_table hpet_root[] = {
710         {
711          .ctl_name = 1,
712          .procname = "hpet",
713          .maxlen = 0,
714          .mode = 0555,
715          .child = hpet_table,
716          },
717         {.ctl_name = 0}
718 };
719
720 static ctl_table dev_root[] = {
721         {
722          .ctl_name = CTL_DEV,
723          .procname = "dev",
724          .maxlen = 0,
725          .mode = 0555,
726          .child = hpet_root,
727          },
728         {.ctl_name = 0}
729 };
730
731 static struct ctl_table_header *sysctl_header;
732
733 /*
734  * Adjustment for when arming the timer with
735  * initial conditions.  That is, main counter
736  * ticks expired before interrupts are enabled.
737  */
738 #define TICK_CALIBRATE  (1000UL)
739
740 static unsigned long __init hpet_calibrate(struct hpets *hpetp)
741 {
742         struct hpet_timer *timer = NULL;
743         unsigned long t, m, count, i, flags, start;
744         struct hpet_dev *devp;
745         int j;
746         struct hpet *hpet;
747
748         for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++)
749                 if ((devp->hd_flags & HPET_OPEN) == 0) {
750                         timer = devp->hd_timer;
751                         break;
752                 }
753
754         if (!timer)
755                 return 0;
756
757         hpet = hpets->hp_hpet;
758         t = read_counter(&timer->hpet_compare);
759
760         i = 0;
761         count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE);
762
763         local_irq_save(flags);
764
765         start = read_counter(&hpet->hpet_mc);
766
767         do {
768                 m = read_counter(&hpet->hpet_mc);
769                 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
770         } while (i++, (m - start) < count);
771
772         local_irq_restore(flags);
773
774         return (m - start) / i;
775 }
776
777 int __init hpet_alloc(struct hpet_data *hdp)
778 {
779         u64 cap, mcfg;
780         struct hpet_dev *devp;
781         u32 i, ntimer;
782         struct hpets *hpetp;
783         size_t siz;
784         struct hpet *hpet;
785         static struct hpets *last __initdata = (struct hpets *)0;
786
787         /*
788          * hpet_alloc can be called by platform dependent code.
789          * if platform dependent code has allocated the hpet
790          * ACPI also reports hpet, then we catch it here.
791          */
792         for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
793                 if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
794                         return 0;
795
796         siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
797                                       sizeof(struct hpet_dev));
798
799         hpetp = kmalloc(siz, GFP_KERNEL);
800
801         if (!hpetp)
802                 return -ENOMEM;
803
804         memset(hpetp, 0, siz);
805
806         hpetp->hp_which = hpet_nhpet++;
807         hpetp->hp_hpet = (struct hpet *)hdp->hd_address;
808
809         hpetp->hp_ntimer = hdp->hd_nirqs;
810
811         for (i = 0; i < hdp->hd_nirqs; i++)
812                 hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
813
814         hpet = hpetp->hp_hpet;
815
816         cap = readq(&hpet->hpet_cap);
817
818         ntimer = ((cap & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT) + 1;
819
820         if (hpetp->hp_ntimer != ntimer) {
821                 printk(KERN_WARNING "hpet: number irqs doesn't agree"
822                        " with number of timers\n");
823                 kfree(hpetp);
824                 return -ENODEV;
825         }
826
827         if (last)
828                 last->hp_next = hpetp;
829         else
830                 hpets = hpetp;
831
832         last = hpetp;
833
834         hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
835             HPET_COUNTER_CLK_PERIOD_SHIFT;
836
837         mcfg = readq(&hpet->hpet_config);
838         if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
839                 write_counter(0L, &hpet->hpet_mc);
840                 mcfg |= HPET_ENABLE_CNF_MASK;
841                 writeq(mcfg, &hpet->hpet_config);
842         }
843
844         for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer;
845              i++, hpet_ntimer++, devp++) {
846                 unsigned long v;
847                 struct hpet_timer *timer;
848
849                 timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
850                 v = readq(&timer->hpet_config);
851
852                 devp->hd_hpets = hpetp;
853                 devp->hd_hpet = hpet;
854                 devp->hd_timer = timer;
855
856                 /*
857                  * If the timer was reserved by platform code,
858                  * then make timer unavailable for opens.
859                  */
860                 if (hdp->hd_state & (1 << i)) {
861                         devp->hd_flags = HPET_OPEN;
862                         continue;
863                 }
864
865                 init_waitqueue_head(&devp->hd_waitqueue);
866         }
867
868         hpetp->hp_delta = hpet_calibrate(hpetp);
869
870         return 0;
871 }
872
873 static acpi_status __init hpet_resources(struct acpi_resource *res, void *data)
874 {
875         struct hpet_data *hdp;
876         acpi_status status;
877         struct acpi_resource_address64 addr;
878         struct hpets *hpetp;
879
880         hdp = data;
881
882         status = acpi_resource_to_address64(res, &addr);
883
884         if (ACPI_SUCCESS(status)) {
885                 unsigned long size;
886
887                 size = addr.max_address_range - addr.min_address_range + 1;
888                 hdp->hd_address =
889                     (unsigned long)ioremap(addr.min_address_range, size);
890
891                 for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
892                         if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
893                                 return -EBUSY;
894         } else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
895                 struct acpi_resource_ext_irq *irqp;
896                 int i;
897
898                 irqp = &res->data.extended_irq;
899
900                 if (irqp->number_of_interrupts > 0) {
901                         hdp->hd_nirqs = irqp->number_of_interrupts;
902
903                         for (i = 0; i < hdp->hd_nirqs; i++)
904 #ifdef  CONFIG_IA64
905                                 hdp->hd_irq[i] =
906                                     acpi_register_gsi(irqp->interrupts[i],
907                                                       irqp->edge_level,
908                                                       irqp->active_high_low);
909 #else
910                                 hdp->hd_irq[i] = irqp->interrupts[i];
911 #endif
912                 }
913         }
914
915         return AE_OK;
916 }
917
918 static int __init hpet_acpi_add(struct acpi_device *device)
919 {
920         acpi_status result;
921         struct hpet_data data;
922
923         memset(&data, 0, sizeof(data));
924
925         result =
926             acpi_walk_resources(device->handle, METHOD_NAME__CRS,
927                                 hpet_resources, &data);
928
929         if (ACPI_FAILURE(result))
930                 return -ENODEV;
931
932         if (!data.hd_address || !data.hd_nirqs) {
933                 printk("%s: no address or irqs in _CRS\n", __FUNCTION__);
934                 return -ENODEV;
935         }
936
937         return hpet_alloc(&data);
938 }
939
940 static int __init hpet_acpi_remove(struct acpi_device *device, int type)
941 {
942         return 0;
943 }
944
945 static struct acpi_driver hpet_acpi_driver __initdata = {
946         .name = "hpet",
947         .class = "",
948         .ids = "PNP0103",
949         .ops = {
950                 .add = hpet_acpi_add,
951                 .remove = hpet_acpi_remove,
952                 },
953 };
954
955 static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops };
956
957 static int __init hpet_init(void)
958 {
959         (void)acpi_bus_register_driver(&hpet_acpi_driver);
960
961         if (hpets) {
962                 if (misc_register(&hpet_misc))
963                         return -ENODEV;
964
965                 sysctl_header = register_sysctl_table(dev_root, 0);
966
967 #ifdef  CONFIG_TIME_INTERPOLATION
968                 {
969                         struct hpet *hpet;
970
971                         hpet = hpets->hp_hpet;
972                         hpet_cycles_per_sec = hpet_time_div(hpets->hp_period);
973                         hpet_interpolator.frequency = hpet_cycles_per_sec;
974                         hpet_interpolator.drift = hpet_cycles_per_sec *
975                             HPET_DRIFT / 1000000;
976                         hpet_nsecs_per_cycle = 1000000000 / hpet_cycles_per_sec;
977                         register_time_interpolator(&hpet_interpolator);
978                 }
979 #endif
980                 return 0;
981         } else
982                 return -ENODEV;
983 }
984
985 static void __exit hpet_exit(void)
986 {
987         acpi_bus_unregister_driver(&hpet_acpi_driver);
988
989         if (hpets)
990                 unregister_sysctl_table(sysctl_header);
991
992         return;
993 }
994
995 module_init(hpet_init);
996 module_exit(hpet_exit);
997 MODULE_AUTHOR("Bob Picco <Robert.Picco@hp.com>");
998 MODULE_LICENSE("GPL");