aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hpet.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-30 08:40:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-30 08:40:09 -0500
commitdd430ca20c40ecccd6954a7efd13d4398f507728 (patch)
treeb65089436d17b2bcc6054ede2e335a821b50007f /drivers/char/hpet.c
parent60e233172eabdd1f831bd48631b9626ce2279d9b (diff)
parentafadcd788f37bfa62d92662e54a720c26c91becf (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86
* git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86: (890 commits) x86: fix nodemap_size according to nodeid bits x86: fix overlap between pagetable with bss section x86: add PCI IDs to k8topology_64.c x86: fix early_ioremap pagetable ops x86: use the same pgd_list for PAE and 64-bit x86: defer cr3 reload when doing pud_clear() x86: early boot debugging via FireWire (ohci1394_dma=early) x86: don't special-case pmd allocations as much x86: shrink some ifdefs in fault.c x86: ignore spurious faults x86: remove nx_enabled from fault.c x86: unify fault_32|64.c x86: unify fault_32|64.c with ifdefs x86: unify fault_32|64.c by ifdef'd function bodies x86: arch/x86/mm/init_32.c printk fixes x86: arch/x86/mm/init_32.c cleanup x86: arch/x86/mm/init_64.c printk fixes x86: unify ioremap x86: fixes some bugs about EFI memory map handling x86: use reboot_type on EFI 32 ...
Diffstat (limited to 'drivers/char/hpet.c')
-rw-r--r--drivers/char/hpet.c126
1 files changed, 44 insertions, 82 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 4c16778e3f84..465ad35ed38f 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -600,63 +600,6 @@ static int hpet_is_known(struct hpet_data *hdp)
600 return 0; 600 return 0;
601} 601}
602 602
603EXPORT_SYMBOL(hpet_alloc);
604EXPORT_SYMBOL(hpet_register);
605EXPORT_SYMBOL(hpet_unregister);
606EXPORT_SYMBOL(hpet_control);
607
608int hpet_register(struct hpet_task *tp, int periodic)
609{
610 unsigned int i;
611 u64 mask;
612 struct hpet_timer __iomem *timer;
613 struct hpet_dev *devp;
614 struct hpets *hpetp;
615
616 switch (periodic) {
617 case 1:
618 mask = Tn_PER_INT_CAP_MASK;
619 break;
620 case 0:
621 mask = 0;
622 break;
623 default:
624 return -EINVAL;
625 }
626
627 tp->ht_opaque = NULL;
628
629 spin_lock_irq(&hpet_task_lock);
630 spin_lock(&hpet_lock);
631
632 for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
633 for (timer = hpetp->hp_hpet->hpet_timers, i = 0;
634 i < hpetp->hp_ntimer; i++, timer++) {
635 if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK)
636 != mask)
637 continue;
638
639 devp = &hpetp->hp_dev[i];
640
641 if (devp->hd_flags & HPET_OPEN || devp->hd_task) {
642 devp = NULL;
643 continue;
644 }
645
646 tp->ht_opaque = devp;
647 devp->hd_task = tp;
648 break;
649 }
650
651 spin_unlock(&hpet_lock);
652 spin_unlock_irq(&hpet_task_lock);
653
654 if (tp->ht_opaque)
655 return 0;
656 else
657 return -EBUSY;
658}
659
660static inline int hpet_tpcheck(struct hpet_task *tp) 603static inline int hpet_tpcheck(struct hpet_task *tp)
661{ 604{
662 struct hpet_dev *devp; 605 struct hpet_dev *devp;
@@ -706,24 +649,6 @@ int hpet_unregister(struct hpet_task *tp)
706 return 0; 649 return 0;
707} 650}
708 651
709int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
710{
711 struct hpet_dev *devp;
712 int err;
713
714 if ((err = hpet_tpcheck(tp)))
715 return err;
716
717 spin_lock_irq(&hpet_lock);
718 devp = tp->ht_opaque;
719 if (devp->hd_task != tp) {
720 spin_unlock_irq(&hpet_lock);
721 return -ENXIO;
722 }
723 spin_unlock_irq(&hpet_lock);
724 return hpet_ioctl_common(devp, cmd, arg, 1);
725}
726
727static ctl_table hpet_table[] = { 652static ctl_table hpet_table[] = {
728 { 653 {
729 .ctl_name = CTL_UNNUMBERED, 654 .ctl_name = CTL_UNNUMBERED,
@@ -806,14 +731,14 @@ static unsigned long hpet_calibrate(struct hpets *hpetp)
806 731
807int hpet_alloc(struct hpet_data *hdp) 732int hpet_alloc(struct hpet_data *hdp)
808{ 733{
809 u64 cap, mcfg; 734 u64 cap, mcfg, hpet_config;
810 struct hpet_dev *devp; 735 struct hpet_dev *devp;
811 u32 i, ntimer; 736 u32 i, ntimer, irq;
812 struct hpets *hpetp; 737 struct hpets *hpetp;
813 size_t siz; 738 size_t siz;
814 struct hpet __iomem *hpet; 739 struct hpet __iomem *hpet;
815 static struct hpets *last = NULL; 740 static struct hpets *last = NULL;
816 unsigned long period; 741 unsigned long period, irq_bitmap;
817 unsigned long long temp; 742 unsigned long long temp;
818 743
819 /* 744 /*
@@ -840,11 +765,47 @@ int hpet_alloc(struct hpet_data *hdp)
840 hpetp->hp_hpet_phys = hdp->hd_phys_address; 765 hpetp->hp_hpet_phys = hdp->hd_phys_address;
841 766
842 hpetp->hp_ntimer = hdp->hd_nirqs; 767 hpetp->hp_ntimer = hdp->hd_nirqs;
768 hpet = hpetp->hp_hpet;
843 769
844 for (i = 0; i < hdp->hd_nirqs; i++) 770 /* Assign IRQs statically for legacy devices */
845 hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i]; 771 hpetp->hp_dev[0].hd_hdwirq = hdp->hd_irq[0];
772 hpetp->hp_dev[1].hd_hdwirq = hdp->hd_irq[1];
846 773
847 hpet = hpetp->hp_hpet; 774 /* Assign IRQs dynamically for the others */
775 for (i = 2, devp = &hpetp->hp_dev[2]; i < hdp->hd_nirqs; i++, devp++) {
776 struct hpet_timer __iomem *timer;
777
778 timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
779
780 /* Check if there's already an IRQ assigned to the timer */
781 if (hdp->hd_irq[i]) {
782 hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
783 continue;
784 }
785
786 hpet_config = readq(&timer->hpet_config);
787 irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK)
788 >> Tn_INT_ROUTE_CAP_SHIFT;
789 if (!irq_bitmap)
790 irq = 0; /* No valid IRQ Assignable */
791 else {
792 irq = find_first_bit(&irq_bitmap, 32);
793 do {
794 hpet_config |= irq << Tn_INT_ROUTE_CNF_SHIFT;
795 writeq(hpet_config, &timer->hpet_config);
796
797 /*
798 * Verify whether we have written a valid
799 * IRQ number by reading it back again
800 */
801 hpet_config = readq(&timer->hpet_config);
802 if (irq == (hpet_config & Tn_INT_ROUTE_CNF_MASK)
803 >> Tn_INT_ROUTE_CNF_SHIFT)
804 break; /* Success */
805 } while ((irq = (find_next_bit(&irq_bitmap, 32, irq))));
806 }
807 hpetp->hp_dev[i].hd_hdwirq = irq;
808 }
848 809
849 cap = readq(&hpet->hpet_cap); 810 cap = readq(&hpet->hpet_cap);
850 811
@@ -875,7 +836,8 @@ int hpet_alloc(struct hpet_data *hdp)
875 hpetp->hp_which, hdp->hd_phys_address, 836 hpetp->hp_which, hdp->hd_phys_address,
876 hpetp->hp_ntimer > 1 ? "s" : ""); 837 hpetp->hp_ntimer > 1 ? "s" : "");
877 for (i = 0; i < hpetp->hp_ntimer; i++) 838 for (i = 0; i < hpetp->hp_ntimer; i++)
878 printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); 839 printk("%s %d", i > 0 ? "," : "",
840 hpetp->hp_dev[i].hd_hdwirq);
879 printk("\n"); 841 printk("\n");
880 842
881 printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", 843 printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",