aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hpet.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2005-12-06 17:31:30 -0500
committerLen Brown <len.brown@intel.com>2005-12-06 17:31:30 -0500
commit3d5271f9883cba7b54762bc4fe027d4172f06db7 (patch)
treeab8a881a14478598a0c8bda0d26c62cdccfffd6d /drivers/char/hpet.c
parent378b2556f4e09fa6f87ff0cb5c4395ff28257d02 (diff)
parent9115a6c787596e687df03010d97fccc5e0762506 (diff)
Pull release into acpica branch
Diffstat (limited to 'drivers/char/hpet.c')
-rw-r--r--drivers/char/hpet.c169
1 files changed, 113 insertions, 56 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a5c3f9c0c909..5172d4e1236c 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -49,7 +49,9 @@
49#define HPET_USER_FREQ (64) 49#define HPET_USER_FREQ (64)
50#define HPET_DRIFT (500) 50#define HPET_DRIFT (500)
51 51
52static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; 52#define HPET_RANGE_SIZE 1024 /* from HPET spec */
53
54static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
53 55
54/* A lock for concurrent access by app and isr hpet activity. */ 56/* A lock for concurrent access by app and isr hpet activity. */
55static DEFINE_SPINLOCK(hpet_lock); 57static DEFINE_SPINLOCK(hpet_lock);
@@ -78,7 +80,7 @@ struct hpets {
78 struct hpet __iomem *hp_hpet; 80 struct hpet __iomem *hp_hpet;
79 unsigned long hp_hpet_phys; 81 unsigned long hp_hpet_phys;
80 struct time_interpolator *hp_interpolator; 82 struct time_interpolator *hp_interpolator;
81 unsigned long hp_period; 83 unsigned long long hp_tick_freq;
82 unsigned long hp_delta; 84 unsigned long hp_delta;
83 unsigned int hp_ntimer; 85 unsigned int hp_ntimer;
84 unsigned int hp_which; 86 unsigned int hp_which;
@@ -90,6 +92,7 @@ static struct hpets *hpets;
90#define HPET_OPEN 0x0001 92#define HPET_OPEN 0x0001
91#define HPET_IE 0x0002 /* interrupt enabled */ 93#define HPET_IE 0x0002 /* interrupt enabled */
92#define HPET_PERIODIC 0x0004 94#define HPET_PERIODIC 0x0004
95#define HPET_SHARED_IRQ 0x0008
93 96
94#if BITS_PER_LONG == 64 97#if BITS_PER_LONG == 64
95#define write_counter(V, MC) writeq(V, MC) 98#define write_counter(V, MC) writeq(V, MC)
@@ -120,6 +123,11 @@ static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
120 unsigned long isr; 123 unsigned long isr;
121 124
122 devp = data; 125 devp = data;
126 isr = 1 << (devp - devp->hd_hpets->hp_dev);
127
128 if ((devp->hd_flags & HPET_SHARED_IRQ) &&
129 !(isr & readl(&devp->hd_hpet->hpet_isr)))
130 return IRQ_NONE;
123 131
124 spin_lock(&hpet_lock); 132 spin_lock(&hpet_lock);
125 devp->hd_irqdata++; 133 devp->hd_irqdata++;
@@ -137,8 +145,8 @@ static irqreturn_t hpet_interrupt(int irq, void *data, struct pt_regs *regs)
137 &devp->hd_timer->hpet_compare); 145 &devp->hd_timer->hpet_compare);
138 } 146 }
139 147
140 isr = (1 << (devp - devp->hd_hpets->hp_dev)); 148 if (devp->hd_flags & HPET_SHARED_IRQ)
141 writeq(isr, &devp->hd_hpet->hpet_isr); 149 writel(isr, &devp->hd_hpet->hpet_isr);
142 spin_unlock(&hpet_lock); 150 spin_unlock(&hpet_lock);
143 151
144 spin_lock(&hpet_task_lock); 152 spin_lock(&hpet_task_lock);
@@ -273,11 +281,11 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
273 281
274 vma->vm_flags |= VM_IO; 282 vma->vm_flags |= VM_IO;
275 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 283 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
276 addr = __pa(addr);
277 284
278 if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, 285 if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
279 PAGE_SIZE, vma->vm_page_prot)) { 286 PAGE_SIZE, vma->vm_page_prot)) {
280 printk(KERN_ERR "remap_pfn_range failed in hpet.c\n"); 287 printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
288 __FUNCTION__);
281 return -EAGAIN; 289 return -EAGAIN;
282 } 290 }
283 291
@@ -365,7 +373,9 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
365 hpet = devp->hd_hpet; 373 hpet = devp->hd_hpet;
366 hpetp = devp->hd_hpets; 374 hpetp = devp->hd_hpets;
367 375
368 v = readq(&timer->hpet_config); 376 if (!devp->hd_ireqfreq)
377 return -EIO;
378
369 spin_lock_irq(&hpet_lock); 379 spin_lock_irq(&hpet_lock);
370 380
371 if (devp->hd_flags & HPET_IE) { 381 if (devp->hd_flags & HPET_IE) {
@@ -374,16 +384,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
374 } 384 }
375 385
376 devp->hd_flags |= HPET_IE; 386 devp->hd_flags |= HPET_IE;
387
388 if (readl(&timer->hpet_config) & Tn_INT_TYPE_CNF_MASK)
389 devp->hd_flags |= HPET_SHARED_IRQ;
377 spin_unlock_irq(&hpet_lock); 390 spin_unlock_irq(&hpet_lock);
378 391
379 t = readq(&timer->hpet_config);
380 irq = devp->hd_hdwirq; 392 irq = devp->hd_hdwirq;
381 393
382 if (irq) { 394 if (irq) {
383 sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); 395 unsigned long irq_flags;
384 396
385 if (request_irq 397 sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
386 (irq, hpet_interrupt, SA_INTERRUPT, devp->hd_name, (void *)devp)) { 398 irq_flags = devp->hd_flags & HPET_SHARED_IRQ
399 ? SA_SHIRQ : SA_INTERRUPT;
400 if (request_irq(irq, hpet_interrupt, irq_flags,
401 devp->hd_name, (void *)devp)) {
387 printk(KERN_ERR "hpet: IRQ %d is not free\n", irq); 402 printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
388 irq = 0; 403 irq = 0;
389 } 404 }
@@ -417,20 +432,24 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
417 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); 432 write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
418 } 433 }
419 434
420 isr = (1 << (devp - hpets->hp_dev)); 435 if (devp->hd_flags & HPET_SHARED_IRQ) {
421 writeq(isr, &hpet->hpet_isr); 436 isr = 1 << (devp - devp->hd_hpets->hp_dev);
437 writel(isr, &hpet->hpet_isr);
438 }
422 writeq(g, &timer->hpet_config); 439 writeq(g, &timer->hpet_config);
423 local_irq_restore(flags); 440 local_irq_restore(flags);
424 441
425 return 0; 442 return 0;
426} 443}
427 444
428static inline unsigned long hpet_time_div(unsigned long dis) 445/* converts Hz to number of timer ticks */
446static inline unsigned long hpet_time_div(struct hpets *hpets,
447 unsigned long dis)
429{ 448{
430 unsigned long long m = 1000000000000000ULL; 449 unsigned long long m;
431 450
451 m = hpets->hp_tick_freq + (dis >> 1);
432 do_div(m, dis); 452 do_div(m, dis);
433
434 return (unsigned long)m; 453 return (unsigned long)m;
435} 454}
436 455
@@ -478,14 +497,21 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
478 { 497 {
479 struct hpet_info info; 498 struct hpet_info info;
480 499
481 info.hi_ireqfreq = hpet_time_div(hpetp->hp_period * 500 if (devp->hd_ireqfreq)
482 devp->hd_ireqfreq); 501 info.hi_ireqfreq =
502 hpet_time_div(hpetp, devp->hd_ireqfreq);
503 else
504 info.hi_ireqfreq = 0;
483 info.hi_flags = 505 info.hi_flags =
484 readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; 506 readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
485 info.hi_hpet = devp->hd_hpets->hp_which; 507 info.hi_hpet = hpetp->hp_which;
486 info.hi_timer = devp - devp->hd_hpets->hp_dev; 508 info.hi_timer = devp - hpetp->hp_dev;
487 if (copy_to_user((void __user *)arg, &info, sizeof(info))) 509 if (kernel)
488 err = -EFAULT; 510 memcpy((void *)arg, &info, sizeof(info));
511 else
512 if (copy_to_user((void __user *)arg, &info,
513 sizeof(info)))
514 err = -EFAULT;
489 break; 515 break;
490 } 516 }
491 case HPET_EPI: 517 case HPET_EPI:
@@ -517,12 +543,12 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
517 break; 543 break;
518 } 544 }
519 545
520 if (arg & (arg - 1)) { 546 if (!arg) {
521 err = -EINVAL; 547 err = -EINVAL;
522 break; 548 break;
523 } 549 }
524 550
525 devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg); 551 devp->hd_ireqfreq = hpet_time_div(hpetp, arg);
526 } 552 }
527 553
528 return err; 554 return err;
@@ -540,6 +566,17 @@ static struct file_operations hpet_fops = {
540 .mmap = hpet_mmap, 566 .mmap = hpet_mmap,
541}; 567};
542 568
569static int hpet_is_known(struct hpet_data *hdp)
570{
571 struct hpets *hpetp;
572
573 for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
574 if (hpetp->hp_hpet_phys == hdp->hd_phys_address)
575 return 1;
576
577 return 0;
578}
579
543EXPORT_SYMBOL(hpet_alloc); 580EXPORT_SYMBOL(hpet_alloc);
544EXPORT_SYMBOL(hpet_register); 581EXPORT_SYMBOL(hpet_register);
545EXPORT_SYMBOL(hpet_unregister); 582EXPORT_SYMBOL(hpet_unregister);
@@ -564,6 +601,8 @@ int hpet_register(struct hpet_task *tp, int periodic)
564 return -EINVAL; 601 return -EINVAL;
565 } 602 }
566 603
604 tp->ht_opaque = NULL;
605
567 spin_lock_irq(&hpet_task_lock); 606 spin_lock_irq(&hpet_task_lock);
568 spin_lock(&hpet_lock); 607 spin_lock(&hpet_lock);
569 608
@@ -703,15 +742,14 @@ static void hpet_register_interpolator(struct hpets *hpetp)
703#ifdef CONFIG_TIME_INTERPOLATION 742#ifdef CONFIG_TIME_INTERPOLATION
704 struct time_interpolator *ti; 743 struct time_interpolator *ti;
705 744
706 ti = kmalloc(sizeof(*ti), GFP_KERNEL); 745 ti = kzalloc(sizeof(*ti), GFP_KERNEL);
707 if (!ti) 746 if (!ti)
708 return; 747 return;
709 748
710 memset(ti, 0, sizeof(*ti));
711 ti->source = TIME_SOURCE_MMIO64; 749 ti->source = TIME_SOURCE_MMIO64;
712 ti->shift = 10; 750 ti->shift = 10;
713 ti->addr = &hpetp->hp_hpet->hpet_mc; 751 ti->addr = &hpetp->hp_hpet->hpet_mc;
714 ti->frequency = hpet_time_div(hpets->hp_period); 752 ti->frequency = hpetp->hp_tick_freq;
715 ti->drift = HPET_DRIFT; 753 ti->drift = HPET_DRIFT;
716 ti->mask = -1; 754 ti->mask = -1;
717 755
@@ -744,11 +782,11 @@ static unsigned long hpet_calibrate(struct hpets *hpetp)
744 if (!timer) 782 if (!timer)
745 return 0; 783 return 0;
746 784
747 hpet = hpets->hp_hpet; 785 hpet = hpetp->hp_hpet;
748 t = read_counter(&timer->hpet_compare); 786 t = read_counter(&timer->hpet_compare);
749 787
750 i = 0; 788 i = 0;
751 count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE); 789 count = hpet_time_div(hpetp, TICK_CALIBRATE);
752 790
753 local_irq_save(flags); 791 local_irq_save(flags);
754 792
@@ -772,28 +810,29 @@ int hpet_alloc(struct hpet_data *hdp)
772 struct hpets *hpetp; 810 struct hpets *hpetp;
773 size_t siz; 811 size_t siz;
774 struct hpet __iomem *hpet; 812 struct hpet __iomem *hpet;
775 static struct hpets *last = (struct hpets *)0; 813 static struct hpets *last = NULL;
776 unsigned long ns; 814 unsigned long period;
815 unsigned long long temp;
777 816
778 /* 817 /*
779 * hpet_alloc can be called by platform dependent code. 818 * hpet_alloc can be called by platform dependent code.
780 * if platform dependent code has allocated the hpet 819 * If platform dependent code has allocated the hpet that
781 * ACPI also reports hpet, then we catch it here. 820 * ACPI has also reported, then we catch it here.
782 */ 821 */
783 for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) 822 if (hpet_is_known(hdp)) {
784 if (hpetp->hp_hpet == hdp->hd_address) 823 printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
785 return 0; 824 __FUNCTION__);
825 return 0;
826 }
786 827
787 siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * 828 siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
788 sizeof(struct hpet_dev)); 829 sizeof(struct hpet_dev));
789 830
790 hpetp = kmalloc(siz, GFP_KERNEL); 831 hpetp = kzalloc(siz, GFP_KERNEL);
791 832
792 if (!hpetp) 833 if (!hpetp)
793 return -ENOMEM; 834 return -ENOMEM;
794 835
795 memset(hpetp, 0, siz);
796
797 hpetp->hp_which = hpet_nhpet++; 836 hpetp->hp_which = hpet_nhpet++;
798 hpetp->hp_hpet = hdp->hd_address; 837 hpetp->hp_hpet = hdp->hd_address;
799 hpetp->hp_hpet_phys = hdp->hd_phys_address; 838 hpetp->hp_hpet_phys = hdp->hd_phys_address;
@@ -823,21 +862,23 @@ int hpet_alloc(struct hpet_data *hdp)
823 862
824 last = hpetp; 863 last = hpetp;
825 864
826 hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> 865 period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
827 HPET_COUNTER_CLK_PERIOD_SHIFT; 866 HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */
867 temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */
868 temp += period >> 1; /* round */
869 do_div(temp, period);
870 hpetp->hp_tick_freq = temp; /* ticks per second */
828 871
829 printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s", 872 printk(KERN_INFO "hpet%d: at MMIO 0x%lx (virtual 0x%p), IRQ%s",
830 hpetp->hp_which, hdp->hd_phys_address, 873 hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address,
831 hpetp->hp_ntimer > 1 ? "s" : ""); 874 hpetp->hp_ntimer > 1 ? "s" : "");
832 for (i = 0; i < hpetp->hp_ntimer; i++) 875 for (i = 0; i < hpetp->hp_ntimer; i++)
833 printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); 876 printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
834 printk("\n"); 877 printk("\n");
835 878
836 ns = hpetp->hp_period; /* femptoseconds, 10^-15 */ 879 printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
837 ns /= 1000000; /* convert to nanoseconds, 10^-9 */ 880 hpetp->hp_which, hpetp->hp_ntimer,
838 printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n", 881 cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq);
839 hpetp->hp_which, ns, hpetp->hp_ntimer,
840 cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
841 882
842 mcfg = readq(&hpet->hpet_config); 883 mcfg = readq(&hpet->hpet_config);
843 if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { 884 if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
@@ -846,13 +887,10 @@ int hpet_alloc(struct hpet_data *hdp)
846 writeq(mcfg, &hpet->hpet_config); 887 writeq(mcfg, &hpet->hpet_config);
847 } 888 }
848 889
849 for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; 890 for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) {
850 i++, hpet_ntimer++, devp++) {
851 unsigned long v;
852 struct hpet_timer __iomem *timer; 891 struct hpet_timer __iomem *timer;
853 892
854 timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; 893 timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
855 v = readq(&timer->hpet_config);
856 894
857 devp->hd_hpets = hpetp; 895 devp->hd_hpets = hpetp;
858 devp->hd_hpet = hpet; 896 devp->hd_hpet = hpet;
@@ -881,7 +919,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
881 struct hpet_data *hdp; 919 struct hpet_data *hdp;
882 acpi_status status; 920 acpi_status status;
883 struct acpi_resource_address64 addr; 921 struct acpi_resource_address64 addr;
884 struct hpets *hpetp;
885 922
886 hdp = data; 923 hdp = data;
887 924
@@ -894,9 +931,29 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
894 hdp->hd_phys_address = addr.min_address_range; 931 hdp->hd_phys_address = addr.min_address_range;
895 hdp->hd_address = ioremap(addr.min_address_range, size); 932 hdp->hd_address = ioremap(addr.min_address_range, size);
896 933
897 for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) 934 if (hpet_is_known(hdp)) {
898 if (hpetp->hp_hpet == hdp->hd_address) 935 printk(KERN_DEBUG "%s: 0x%lx is busy\n",
899 return -EBUSY; 936 __FUNCTION__, hdp->hd_phys_address);
937 iounmap(hdp->hd_address);
938 return -EBUSY;
939 }
940 } else if (res->type == ACPI_RSTYPE_FIXED_MEM32) {
941 struct acpi_resource_fixed_mem32 *fixmem32;
942
943 fixmem32 = &res->data.fixed_memory32;
944 if (!fixmem32)
945 return -EINVAL;
946
947 hdp->hd_phys_address = fixmem32->range_base_address;
948 hdp->hd_address = ioremap(fixmem32->range_base_address,
949 HPET_RANGE_SIZE);
950
951 if (hpet_is_known(hdp)) {
952 printk(KERN_DEBUG "%s: 0x%lx is busy\n",
953 __FUNCTION__, hdp->hd_phys_address);
954 iounmap(hdp->hd_address);
955 return -EBUSY;
956 }
900 } else if (res->type == ACPI_RSTYPE_EXT_IRQ) { 957 } else if (res->type == ACPI_RSTYPE_EXT_IRQ) {
901 struct acpi_resource_ext_irq *irqp; 958 struct acpi_resource_ext_irq *irqp;
902 int i; 959 int i;