diff options
Diffstat (limited to 'drivers/char/hpet.c')
| -rw-r--r-- | drivers/char/hpet.c | 168 |
1 files changed, 113 insertions, 55 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index c055bb630ffc..3808d9572619 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 | ||
| 52 | static u32 hpet_ntimer, hpet_nhpet, hpet_max_freq = HPET_USER_FREQ; | 52 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ |
| 53 | |||
| 54 | static 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. */ |
| 55 | static DEFINE_SPINLOCK(hpet_lock); | 57 | static 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); |
| @@ -276,7 +284,8 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 276 | 284 | ||
| 277 | 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, |
| 278 | PAGE_SIZE, vma->vm_page_prot)) { | 286 | PAGE_SIZE, vma->vm_page_prot)) { |
| 279 | printk(KERN_ERR "remap_pfn_range failed in hpet.c\n"); | 287 | printk(KERN_ERR "%s: io_remap_pfn_range failed\n", |
| 288 | __FUNCTION__); | ||
| 280 | return -EAGAIN; | 289 | return -EAGAIN; |
| 281 | } | 290 | } |
| 282 | 291 | ||
| @@ -364,7 +373,9 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
| 364 | hpet = devp->hd_hpet; | 373 | hpet = devp->hd_hpet; |
| 365 | hpetp = devp->hd_hpets; | 374 | hpetp = devp->hd_hpets; |
| 366 | 375 | ||
| 367 | v = readq(&timer->hpet_config); | 376 | if (!devp->hd_ireqfreq) |
| 377 | return -EIO; | ||
| 378 | |||
| 368 | spin_lock_irq(&hpet_lock); | 379 | spin_lock_irq(&hpet_lock); |
| 369 | 380 | ||
| 370 | if (devp->hd_flags & HPET_IE) { | 381 | if (devp->hd_flags & HPET_IE) { |
| @@ -373,16 +384,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
| 373 | } | 384 | } |
| 374 | 385 | ||
| 375 | 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; | ||
| 376 | spin_unlock_irq(&hpet_lock); | 390 | spin_unlock_irq(&hpet_lock); |
| 377 | 391 | ||
| 378 | t = readq(&timer->hpet_config); | ||
| 379 | irq = devp->hd_hdwirq; | 392 | irq = devp->hd_hdwirq; |
| 380 | 393 | ||
| 381 | if (irq) { | 394 | if (irq) { |
| 382 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); | 395 | unsigned long irq_flags; |
| 383 | 396 | ||
| 384 | if (request_irq | 397 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); |
| 385 | (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)) { | ||
| 386 | printk(KERN_ERR "hpet: IRQ %d is not free\n", irq); | 402 | printk(KERN_ERR "hpet: IRQ %d is not free\n", irq); |
| 387 | irq = 0; | 403 | irq = 0; |
| 388 | } | 404 | } |
| @@ -416,20 +432,24 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
| 416 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); | 432 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); |
| 417 | } | 433 | } |
| 418 | 434 | ||
| 419 | isr = (1 << (devp - hpets->hp_dev)); | 435 | if (devp->hd_flags & HPET_SHARED_IRQ) { |
| 420 | writeq(isr, &hpet->hpet_isr); | 436 | isr = 1 << (devp - devp->hd_hpets->hp_dev); |
| 437 | writel(isr, &hpet->hpet_isr); | ||
| 438 | } | ||
| 421 | writeq(g, &timer->hpet_config); | 439 | writeq(g, &timer->hpet_config); |
| 422 | local_irq_restore(flags); | 440 | local_irq_restore(flags); |
| 423 | 441 | ||
| 424 | return 0; | 442 | return 0; |
| 425 | } | 443 | } |
| 426 | 444 | ||
| 427 | static inline unsigned long hpet_time_div(unsigned long dis) | 445 | /* converts Hz to number of timer ticks */ |
| 446 | static inline unsigned long hpet_time_div(struct hpets *hpets, | ||
| 447 | unsigned long dis) | ||
| 428 | { | 448 | { |
| 429 | unsigned long long m = 1000000000000000ULL; | 449 | unsigned long long m; |
| 430 | 450 | ||
| 451 | m = hpets->hp_tick_freq + (dis >> 1); | ||
| 431 | do_div(m, dis); | 452 | do_div(m, dis); |
| 432 | |||
| 433 | return (unsigned long)m; | 453 | return (unsigned long)m; |
| 434 | } | 454 | } |
| 435 | 455 | ||
| @@ -477,14 +497,21 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | |||
| 477 | { | 497 | { |
| 478 | struct hpet_info info; | 498 | struct hpet_info info; |
| 479 | 499 | ||
| 480 | info.hi_ireqfreq = hpet_time_div(hpetp->hp_period * | 500 | if (devp->hd_ireqfreq) |
| 481 | devp->hd_ireqfreq); | 501 | info.hi_ireqfreq = |
| 502 | hpet_time_div(hpetp, devp->hd_ireqfreq); | ||
| 503 | else | ||
| 504 | info.hi_ireqfreq = 0; | ||
| 482 | info.hi_flags = | 505 | info.hi_flags = |
| 483 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; | 506 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; |
| 484 | info.hi_hpet = devp->hd_hpets->hp_which; | 507 | info.hi_hpet = hpetp->hp_which; |
| 485 | info.hi_timer = devp - devp->hd_hpets->hp_dev; | 508 | info.hi_timer = devp - hpetp->hp_dev; |
| 486 | if (copy_to_user((void __user *)arg, &info, sizeof(info))) | 509 | if (kernel) |
| 487 | 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; | ||
| 488 | break; | 515 | break; |
| 489 | } | 516 | } |
| 490 | case HPET_EPI: | 517 | case HPET_EPI: |
| @@ -516,12 +543,12 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | |||
| 516 | break; | 543 | break; |
| 517 | } | 544 | } |
| 518 | 545 | ||
| 519 | if (arg & (arg - 1)) { | 546 | if (!arg) { |
| 520 | err = -EINVAL; | 547 | err = -EINVAL; |
| 521 | break; | 548 | break; |
| 522 | } | 549 | } |
| 523 | 550 | ||
| 524 | devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg); | 551 | devp->hd_ireqfreq = hpet_time_div(hpetp, arg); |
| 525 | } | 552 | } |
| 526 | 553 | ||
| 527 | return err; | 554 | return err; |
| @@ -539,6 +566,17 @@ static struct file_operations hpet_fops = { | |||
| 539 | .mmap = hpet_mmap, | 566 | .mmap = hpet_mmap, |
| 540 | }; | 567 | }; |
| 541 | 568 | ||
| 569 | static 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 | |||
| 542 | EXPORT_SYMBOL(hpet_alloc); | 580 | EXPORT_SYMBOL(hpet_alloc); |
| 543 | EXPORT_SYMBOL(hpet_register); | 581 | EXPORT_SYMBOL(hpet_register); |
| 544 | EXPORT_SYMBOL(hpet_unregister); | 582 | EXPORT_SYMBOL(hpet_unregister); |
| @@ -563,6 +601,8 @@ int hpet_register(struct hpet_task *tp, int periodic) | |||
| 563 | return -EINVAL; | 601 | return -EINVAL; |
| 564 | } | 602 | } |
| 565 | 603 | ||
| 604 | tp->ht_opaque = NULL; | ||
| 605 | |||
| 566 | spin_lock_irq(&hpet_task_lock); | 606 | spin_lock_irq(&hpet_task_lock); |
| 567 | spin_lock(&hpet_lock); | 607 | spin_lock(&hpet_lock); |
| 568 | 608 | ||
| @@ -702,15 +742,14 @@ static void hpet_register_interpolator(struct hpets *hpetp) | |||
| 702 | #ifdef CONFIG_TIME_INTERPOLATION | 742 | #ifdef CONFIG_TIME_INTERPOLATION |
| 703 | struct time_interpolator *ti; | 743 | struct time_interpolator *ti; |
| 704 | 744 | ||
| 705 | ti = kmalloc(sizeof(*ti), GFP_KERNEL); | 745 | ti = kzalloc(sizeof(*ti), GFP_KERNEL); |
| 706 | if (!ti) | 746 | if (!ti) |
| 707 | return; | 747 | return; |
| 708 | 748 | ||
| 709 | memset(ti, 0, sizeof(*ti)); | ||
| 710 | ti->source = TIME_SOURCE_MMIO64; | 749 | ti->source = TIME_SOURCE_MMIO64; |
| 711 | ti->shift = 10; | 750 | ti->shift = 10; |
| 712 | ti->addr = &hpetp->hp_hpet->hpet_mc; | 751 | ti->addr = &hpetp->hp_hpet->hpet_mc; |
| 713 | ti->frequency = hpet_time_div(hpets->hp_period); | 752 | ti->frequency = hpetp->hp_tick_freq; |
| 714 | ti->drift = HPET_DRIFT; | 753 | ti->drift = HPET_DRIFT; |
| 715 | ti->mask = -1; | 754 | ti->mask = -1; |
| 716 | 755 | ||
| @@ -743,11 +782,11 @@ static unsigned long hpet_calibrate(struct hpets *hpetp) | |||
| 743 | if (!timer) | 782 | if (!timer) |
| 744 | return 0; | 783 | return 0; |
| 745 | 784 | ||
| 746 | hpet = hpets->hp_hpet; | 785 | hpet = hpetp->hp_hpet; |
| 747 | t = read_counter(&timer->hpet_compare); | 786 | t = read_counter(&timer->hpet_compare); |
| 748 | 787 | ||
| 749 | i = 0; | 788 | i = 0; |
| 750 | count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE); | 789 | count = hpet_time_div(hpetp, TICK_CALIBRATE); |
| 751 | 790 | ||
| 752 | local_irq_save(flags); | 791 | local_irq_save(flags); |
| 753 | 792 | ||
| @@ -771,28 +810,29 @@ int hpet_alloc(struct hpet_data *hdp) | |||
| 771 | struct hpets *hpetp; | 810 | struct hpets *hpetp; |
| 772 | size_t siz; | 811 | size_t siz; |
| 773 | struct hpet __iomem *hpet; | 812 | struct hpet __iomem *hpet; |
| 774 | static struct hpets *last = (struct hpets *)0; | 813 | static struct hpets *last = NULL; |
| 775 | unsigned long ns; | 814 | unsigned long period; |
| 815 | unsigned long long temp; | ||
| 776 | 816 | ||
| 777 | /* | 817 | /* |
| 778 | * hpet_alloc can be called by platform dependent code. | 818 | * hpet_alloc can be called by platform dependent code. |
| 779 | * if platform dependent code has allocated the hpet | 819 | * If platform dependent code has allocated the hpet that |
| 780 | * ACPI also reports hpet, then we catch it here. | 820 | * ACPI has also reported, then we catch it here. |
| 781 | */ | 821 | */ |
| 782 | for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) | 822 | if (hpet_is_known(hdp)) { |
| 783 | if (hpetp->hp_hpet == hdp->hd_address) | 823 | printk(KERN_DEBUG "%s: duplicate HPET ignored\n", |
| 784 | return 0; | 824 | __FUNCTION__); |
| 825 | return 0; | ||
| 826 | } | ||
| 785 | 827 | ||
| 786 | siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * | 828 | siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) * |
| 787 | sizeof(struct hpet_dev)); | 829 | sizeof(struct hpet_dev)); |
| 788 | 830 | ||
| 789 | hpetp = kmalloc(siz, GFP_KERNEL); | 831 | hpetp = kzalloc(siz, GFP_KERNEL); |
| 790 | 832 | ||
| 791 | if (!hpetp) | 833 | if (!hpetp) |
| 792 | return -ENOMEM; | 834 | return -ENOMEM; |
| 793 | 835 | ||
| 794 | memset(hpetp, 0, siz); | ||
| 795 | |||
| 796 | hpetp->hp_which = hpet_nhpet++; | 836 | hpetp->hp_which = hpet_nhpet++; |
| 797 | hpetp->hp_hpet = hdp->hd_address; | 837 | hpetp->hp_hpet = hdp->hd_address; |
| 798 | hpetp->hp_hpet_phys = hdp->hd_phys_address; | 838 | hpetp->hp_hpet_phys = hdp->hd_phys_address; |
| @@ -822,21 +862,23 @@ int hpet_alloc(struct hpet_data *hdp) | |||
| 822 | 862 | ||
| 823 | last = hpetp; | 863 | last = hpetp; |
| 824 | 864 | ||
| 825 | hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> | 865 | period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> |
| 826 | 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 */ | ||
| 827 | 871 | ||
| 828 | 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", |
| 829 | hpetp->hp_which, hdp->hd_phys_address, | 873 | hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address, |
| 830 | hpetp->hp_ntimer > 1 ? "s" : ""); | 874 | hpetp->hp_ntimer > 1 ? "s" : ""); |
| 831 | for (i = 0; i < hpetp->hp_ntimer; i++) | 875 | for (i = 0; i < hpetp->hp_ntimer; i++) |
| 832 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); | 876 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); |
| 833 | printk("\n"); | 877 | printk("\n"); |
| 834 | 878 | ||
| 835 | ns = hpetp->hp_period; /* femptoseconds, 10^-15 */ | 879 | printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", |
| 836 | ns /= 1000000; /* convert to nanoseconds, 10^-9 */ | 880 | hpetp->hp_which, hpetp->hp_ntimer, |
| 837 | printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n", | 881 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq); |
| 838 | hpetp->hp_which, ns, hpetp->hp_ntimer, | ||
| 839 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32); | ||
| 840 | 882 | ||
| 841 | mcfg = readq(&hpet->hpet_config); | 883 | mcfg = readq(&hpet->hpet_config); |
| 842 | if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { | 884 | if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { |
| @@ -845,13 +887,10 @@ int hpet_alloc(struct hpet_data *hdp) | |||
| 845 | writeq(mcfg, &hpet->hpet_config); | 887 | writeq(mcfg, &hpet->hpet_config); |
| 846 | } | 888 | } |
| 847 | 889 | ||
| 848 | 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++) { |
| 849 | i++, hpet_ntimer++, devp++) { | ||
| 850 | unsigned long v; | ||
| 851 | struct hpet_timer __iomem *timer; | 891 | struct hpet_timer __iomem *timer; |
| 852 | 892 | ||
| 853 | timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; | 893 | timer = &hpet->hpet_timers[devp - hpetp->hp_dev]; |
| 854 | v = readq(&timer->hpet_config); | ||
| 855 | 894 | ||
| 856 | devp->hd_hpets = hpetp; | 895 | devp->hd_hpets = hpetp; |
| 857 | devp->hd_hpet = hpet; | 896 | devp->hd_hpet = hpet; |
| @@ -880,7 +919,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
| 880 | struct hpet_data *hdp; | 919 | struct hpet_data *hdp; |
| 881 | acpi_status status; | 920 | acpi_status status; |
| 882 | struct acpi_resource_address64 addr; | 921 | struct acpi_resource_address64 addr; |
| 883 | struct hpets *hpetp; | ||
| 884 | 922 | ||
| 885 | hdp = data; | 923 | hdp = data; |
| 886 | 924 | ||
| @@ -893,9 +931,29 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
| 893 | hdp->hd_phys_address = addr.min_address_range; | 931 | hdp->hd_phys_address = addr.min_address_range; |
| 894 | hdp->hd_address = ioremap(addr.min_address_range, size); | 932 | hdp->hd_address = ioremap(addr.min_address_range, size); |
| 895 | 933 | ||
| 896 | for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) | 934 | if (hpet_is_known(hdp)) { |
| 897 | if (hpetp->hp_hpet == hdp->hd_address) | 935 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", |
| 898 | return -EBUSY; | 936 | __FUNCTION__, hdp->hd_phys_address); |
| 937 | iounmap(hdp->hd_address); | ||
| 938 | return -EBUSY; | ||
| 939 | } | ||
| 940 | } else if (res->id == 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 | } | ||
| 899 | } else if (res->id == ACPI_RSTYPE_EXT_IRQ) { | 957 | } else if (res->id == ACPI_RSTYPE_EXT_IRQ) { |
| 900 | struct acpi_resource_ext_irq *irqp; | 958 | struct acpi_resource_ext_irq *irqp; |
| 901 | int i; | 959 | int i; |
