1 #include <linux/clocksource.h> 2 #include <linux/clockchips.h> 3 #include <linux/delay.h> 4 #include <linux/errno.h> 5 #include <linux/hpet.h> 6 #include <linux/init.h> 7 #include <linux/sysdev.h> 8 #include <linux/pm.h> 9 10 #include <asm/fixmap.h> 11 #include <asm/hpet.h> 12 #include <asm/i8253.h> 13 #include <asm/io.h> 14 15 #define HPET_MASK CLOCKSOURCE_MASK(32) 16 #define HPET_SHIFT 22 17 18 /* FSEC = 10^-15 19 NSEC = 10^-9 */ 20 #define FSEC_PER_NSEC 1000000L 21 22 /* 23 * HPET address is set in acpi/boot.c, when an ACPI entry exists 24 */ 25 unsigned long hpet_address; 26 static void __iomem *hpet_virt_address; 27 28 unsigned long hpet_readl(unsigned long a) 29 { 30 return readl(hpet_virt_address + a); 31 } 32 33 static inline void hpet_writel(unsigned long d, unsigned long a) 34 { 35 writel(d, hpet_virt_address + a); 36 } 37 38 #ifdef CONFIG_X86_64 39 #include <asm/pgtable.h> 40 #endif 41 42 static inline void hpet_set_mapping(void) 43 { 44 hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); 45 #ifdef CONFIG_X86_64 46 __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE); 47 #endif 48 } 49 50 static inline void hpet_clear_mapping(void) 51 { 52 iounmap(hpet_virt_address); 53 hpet_virt_address = NULL; 54 } 55 56 /* 57 * HPET command line enable / disable 58 */ 59 static int boot_hpet_disable; 60 int hpet_force_user; 61 62 static int __init hpet_setup(char* str) 63 { 64 if (str) { 65 if (!strncmp("disable", str, 7)) 66 boot_hpet_disable = 1; 67 if (!strncmp("force", str, 5)) 68 hpet_force_user = 1; 69 } 70 return 1; 71 } 72 __setup("hpet=", hpet_setup); 73 74 static int __init disable_hpet(char *str) 75 { 76 boot_hpet_disable = 1; 77 return 1; 78 } 79 __setup("nohpet", disable_hpet); 80 81 static inline int is_hpet_capable(void) 82 { 83 return (!boot_hpet_disable && hpet_address); 84 } 85 86 /* 87 * HPET timer interrupt enable / disable 88 */ 89 static int hpet_legacy_int_enabled; 90 91 /** 92 * is_hpet_enabled - check whether the hpet timer interrupt is enabled 93 */ 94 int is_hpet_enabled(void) 95 { 96 return is_hpet_capable() && hpet_legacy_int_enabled; 97 } 98 EXPORT_SYMBOL_GPL(is_hpet_enabled); 99 100 /* 101 * When the hpet driver (/dev/hpet) is enabled, we need to reserve 102 * timer 0 and timer 1 in case of RTC emulation. 103 */ 104 #ifdef CONFIG_HPET 105 static void hpet_reserve_platform_timers(unsigned long id) 106 { 107 struct hpet __iomem *hpet = hpet_virt_address; 108 struct hpet_timer __iomem *timer = &hpet->hpet_timers[2]; 109 unsigned int nrtimers, i; 110 struct hpet_data hd; 111 112 nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1; 113 114 memset(&hd, 0, sizeof (hd)); 115 hd.hd_phys_address = hpet_address; 116 hd.hd_address = hpet; 117 hd.hd_nirqs = nrtimers; 118 hpet_reserve_timer(&hd, 0); 119 120 #ifdef CONFIG_HPET_EMULATE_RTC 121 hpet_reserve_timer(&hd, 1); 122 #endif 123 124 /* 125 * NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254 126 * is wrong for i8259!) not the output IRQ. Many BIOS writers 127 * don't bother configuring *any* comparator interrupts. 128 */ 129 hd.hd_irq[0] = HPET_LEGACY_8254; 130 hd.hd_irq[1] = HPET_LEGACY_RTC; 131 132 for (i = 2; i < nrtimers; timer++, i++) { 133 hd.hd_irq[i] = (readl(&timer->hpet_config) & Tn_INT_ROUTE_CNF_MASK) >> 134 Tn_INT_ROUTE_CNF_SHIFT; 135 } 136 137 hpet_alloc(&hd); 138 139 } 140 #else 141 static void hpet_reserve_platform_timers(unsigned long id) { } 142 #endif 143 144 /* 145 * Common hpet info 146 */ 147 static unsigned long hpet_period; 148 149 static void hpet_legacy_set_mode(enum clock_event_mode mode, 150 struct clock_event_device *evt); 151 static int hpet_legacy_next_event(unsigned long delta, 152 struct clock_event_device *evt); 153 154 /* 155 * The hpet clock event device 156 */ 157 static struct clock_event_device hpet_clockevent = { 158 .name = "hpet", 159 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 160 .set_mode = hpet_legacy_set_mode, 161 .set_next_event = hpet_legacy_next_event, 162 .shift = 32, 163 .irq = 0, 164 .rating = 50, 165 }; 166 167 static void hpet_start_counter(void) 168 { 169 unsigned long cfg = hpet_readl(HPET_CFG); 170 171 cfg &= ~HPET_CFG_ENABLE; 172 hpet_writel(cfg, HPET_CFG); 173 hpet_writel(0, HPET_COUNTER); 174 hpet_writel(0, HPET_COUNTER + 4); 175 cfg |= HPET_CFG_ENABLE; 176 hpet_writel(cfg, HPET_CFG); 177 } 178 179 static void hpet_resume_device(void) 180 { 181 force_hpet_resume(); 182 } 183 184 static void hpet_restart_counter(void) 185 { 186 hpet_resume_device(); 187 hpet_start_counter(); 188 } 189 190 static void hpet_enable_legacy_int(void) 191 { 192 unsigned long cfg = hpet_readl(HPET_CFG); 193 194 cfg |= HPET_CFG_LEGACY; 195 hpet_writel(cfg, HPET_CFG); 196 hpet_legacy_int_enabled = 1; 197 } 198 199 static void hpet_legacy_clockevent_register(void) 200 { 201 /* Start HPET legacy interrupts */ 202 hpet_enable_legacy_int(); 203 204 /* 205 * The mult factor is defined as (include/linux/clockchips.h) 206 * mult/2^shift = cyc/ns (in contrast to ns/cyc in clocksource.h) 207 * hpet_period is in units of femtoseconds (per cycle), so 208 * mult/2^shift = cyc/ns = 10^6/hpet_period 209 * mult = (10^6 * 2^shift)/hpet_period 210 * mult = (FSEC_PER_NSEC << hpet_clockevent.shift)/hpet_period 211 */ 212 hpet_clockevent.mult = div_sc((unsigned long) FSEC_PER_NSEC, 213 hpet_period, hpet_clockevent.shift); 214 /* Calculate the min / max delta */ 215 hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, 216 &hpet_clockevent); 217 /* 5 usec minimum reprogramming delta. */ 218 hpet_clockevent.min_delta_ns = 5000; 219 220 /* 221 * Start hpet with the boot cpu mask and make it 222 * global after the IO_APIC has been initialized. 223 */ 224 hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id()); 225 clockevents_register_device(&hpet_clockevent); 226 global_clock_event = &hpet_clockevent; 227 printk(KERN_DEBUG "hpet clockevent registered\n"); 228 } 229 230 static void hpet_legacy_set_mode(enum clock_event_mode mode, 231 struct clock_event_device *evt) 232 { 233 unsigned long cfg, cmp, now; 234 uint64_t delta; 235 236 switch(mode) { 237 case CLOCK_EVT_MODE_PERIODIC: 238 delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * hpet_clockevent.mult; 239 delta >>= hpet_clockevent.shift; 240 now = hpet_readl(HPET_COUNTER); 241 cmp = now + (unsigned long) delta; 242 cfg = hpet_readl(HPET_T0_CFG); 243 cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | 244 HPET_TN_SETVAL | HPET_TN_32BIT; 245 hpet_writel(cfg, HPET_T0_CFG); 246 /* 247 * The first write after writing TN_SETVAL to the 248 * config register sets the counter value, the second 249 * write sets the period. 250 */ 251 hpet_writel(cmp, HPET_T0_CMP); 252 udelay(1); 253 hpet_writel((unsigned long) delta, HPET_T0_CMP); 254 break; 255 256 case CLOCK_EVT_MODE_ONESHOT: 257 cfg = hpet_readl(HPET_T0_CFG); 258 cfg &= ~HPET_TN_PERIODIC; 259 cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; 260 hpet_writel(cfg, HPET_T0_CFG); 261 break; 262 263 case CLOCK_EVT_MODE_UNUSED: 264 case CLOCK_EVT_MODE_SHUTDOWN: 265 cfg = hpet_readl(HPET_T0_CFG); 266 cfg &= ~HPET_TN_ENABLE; 267 hpet_writel(cfg, HPET_T0_CFG); 268 break; 269 270 case CLOCK_EVT_MODE_RESUME: 271 hpet_enable_legacy_int(); 272 break; 273 } 274 } 275 276 static int hpet_legacy_next_event(unsigned long delta, 277 struct clock_event_device *evt) 278 { 279 u32 cnt; 280 281 cnt = hpet_readl(HPET_COUNTER); 282 cnt += (u32) delta; 283 hpet_writel(cnt, HPET_T0_CMP); 284 285 /* 286 * We need to read back the CMP register to make sure that 287 * what we wrote hit the chip before we compare it to the 288 * counter. 289 */ 290 WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt); 291 292 return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0; 293 } 294 295 /* 296 * Clock source related code 297 */ 298 static cycle_t read_hpet(void) 299 { 300 return (cycle_t)hpet_readl(HPET_COUNTER); 301 } 302 303 #ifdef CONFIG_X86_64 304 static cycle_t __vsyscall_fn vread_hpet(void) 305 { 306 return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0); 307 } 308 #endif 309 310 static struct clocksource clocksource_hpet = { 311 .name = "hpet", 312 .rating = 250, 313 .read = read_hpet, 314 .mask = HPET_MASK, 315 .shift = HPET_SHIFT, 316 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 317 .resume = hpet_restart_counter, 318 #ifdef CONFIG_X86_64 319 .vread = vread_hpet, 320 #endif 321 }; 322 323 static int hpet_clocksource_register(void) 324 { 325 u64 start, now; 326 cycle_t t1; 327 328 /* Start the counter */ 329 hpet_start_counter(); 330 331 /* Verify whether hpet counter works */ 332 t1 = read_hpet(); 333 rdtscll(start); 334 335 /* 336 * We don't know the TSC frequency yet, but waiting for 337 * 200000 TSC cycles is safe: 338 * 4 GHz == 50us 339 * 1 GHz == 200us 340 */ 341 do { 342 rep_nop(); 343 rdtscll(now); 344 } while ((now - start) < 200000UL); 345 346 if (t1 == read_hpet()) { 347 printk(KERN_WARNING 348 "HPET counter not counting. HPET disabled\n"); 349 return -ENODEV; 350 } 351 352 /* 353 * The definition of mult is (include/linux/clocksource.h) 354 * mult/2^shift = ns/cyc and hpet_period is in units of fsec/cyc 355 * so we first need to convert hpet_period to ns/cyc units: 356 * mult/2^shift = ns/cyc = hpet_period/10^6 357 * mult = (hpet_period * 2^shift)/10^6 358 * mult = (hpet_period << shift)/FSEC_PER_NSEC 359 */ 360 clocksource_hpet.mult = div_sc(hpet_period, FSEC_PER_NSEC, HPET_SHIFT); 361 362 clocksource_register(&clocksource_hpet); 363 364 return 0; 365 } 366 367 /** 368 * hpet_enable - Try to setup the HPET timer. Returns 1 on success. 369 */ 370 int __init hpet_enable(void) 371 { 372 unsigned long id; 373 int i; 374 375 if (!is_hpet_capable()) 376 return 0; 377 378 hpet_set_mapping(); 379 380 /* 381 * Read the period and check for a sane value: 382 */ 383 hpet_period = hpet_readl(HPET_PERIOD); 384 385 /* 386 * AMD SB700 based systems with spread spectrum enabled use a 387 * SMM based HPET emulation to provide proper frequency 388 * setting. The SMM code is initialized with the first HPET 389 * register access and takes some time to complete. During 390 * this time the config register reads 0xffffffff. We check 391 * for max. 1000 loops whether the config register reads a non 392 * 0xffffffff value to make sure that HPET is up and running 393 * before we go further. A counting loop is safe, as the HPET 394 * access takes thousands of CPU cycles. On non SB700 based 395 * machines this check is only done once and has no side 396 * effects. 397 */ 398 for (i = 0; hpet_readl(HPET_CFG) == 0xFFFFFFFF; i++) { 399 if (i == 1000) { 400 printk(KERN_WARNING 401 "HPET config register value = 0xFFFFFFFF. " 402 "Disabling HPET\n"); 403 goto out_nohpet; 404 } 405 } 406 407 if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) 408 goto out_nohpet; 409 410 /* 411 * Read the HPET ID register to retrieve the IRQ routing 412 * information and the number of channels 413 */ 414 id = hpet_readl(HPET_ID); 415 416 #ifdef CONFIG_HPET_EMULATE_RTC 417 /* 418 * The legacy routing mode needs at least two channels, tick timer 419 * and the rtc emulation channel. 420 */ 421 if (!(id & HPET_ID_NUMBER)) 422 goto out_nohpet; 423 #endif 424 425 if (hpet_clocksource_register()) 426 goto out_nohpet; 427 428 if (id & HPET_ID_LEGSUP) { 429 hpet_legacy_clockevent_register(); 430 return 1; 431 } 432 return 0; 433 434 out_nohpet: 435 hpet_clear_mapping(); 436 boot_hpet_disable = 1; 437 return 0; 438 } 439 440 /* 441 * Needs to be late, as the reserve_timer code calls kalloc ! 442 * 443 * Not a problem on i386 as hpet_enable is called from late_time_init, 444 * but on x86_64 it is necessary ! 445 */ 446 static __init int hpet_late_init(void) 447 { 448 if (boot_hpet_disable) 449 return -ENODEV; 450 451 if (!hpet_address) { 452 if (!force_hpet_address) 453 return -ENODEV; 454 455 hpet_address = force_hpet_address; 456 hpet_enable(); 457 if (!hpet_virt_address) 458 return -ENODEV; 459 } 460 461 hpet_reserve_platform_timers(hpet_readl(HPET_ID)); 462 463 return 0; 464 } 465 fs_initcall(hpet_late_init); 466 467 void hpet_disable(void) 468 { 469 if (is_hpet_capable()) { 470 unsigned long cfg = hpet_readl(HPET_CFG); 471 472 if (hpet_legacy_int_enabled) { 473 cfg &= ~HPET_CFG_LEGACY; 474 hpet_legacy_int_enabled = 0; 475 } 476 cfg &= ~HPET_CFG_ENABLE; 477 hpet_writel(cfg, HPET_CFG); 478 } 479 } 480 481 #ifdef CONFIG_HPET_EMULATE_RTC 482 483 /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET 484 * is enabled, we support RTC interrupt functionality in software. 485 * RTC has 3 kinds of interrupts: 486 * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock 487 * is updated 488 * 2) Alarm Interrupt - generate an interrupt at a specific time of day 489 * 3) Periodic Interrupt - generate periodic interrupt, with frequencies 490 * 2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2) 491 * (1) and (2) above are implemented using polling at a frequency of 492 * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt 493 * overhead. (DEFAULT_RTC_INT_FREQ) 494 * For (3), we use interrupts at 64Hz or user specified periodic 495 * frequency, whichever is higher. 496 */ 497 #include <linux/mc146818rtc.h> 498 #include <linux/rtc.h> 499 #include <asm/rtc.h> 500 501 #define DEFAULT_RTC_INT_FREQ 64 502 #define DEFAULT_RTC_SHIFT 6 503 #define RTC_NUM_INTS 1 504 505 static unsigned long hpet_rtc_flags; 506 static int hpet_prev_update_sec; 507 static struct rtc_time hpet_alarm_time; 508 static unsigned long hpet_pie_count; 509 static unsigned long hpet_t1_cmp; 510 static unsigned long hpet_default_delta; 511 static unsigned long hpet_pie_delta; 512 static unsigned long hpet_pie_limit; 513 514 static rtc_irq_handler irq_handler; 515 516 /* 517 * Registers a IRQ handler. 518 */ 519 int hpet_register_irq_handler(rtc_irq_handler handler) 520 { 521 if (!is_hpet_enabled()) 522 return -ENODEV; 523 if (irq_handler) 524 return -EBUSY; 525 526 irq_handler = handler; 527 528 return 0; 529 } 530 EXPORT_SYMBOL_GPL(hpet_register_irq_handler); 531 532 /* 533 * Deregisters the IRQ handler registered with hpet_register_irq_handler() 534 * and does cleanup. 535 */ 536 void hpet_unregister_irq_handler(rtc_irq_handler handler) 537 { 538 if (!is_hpet_enabled()) 539 return; 540 541 irq_handler = NULL; 542 hpet_rtc_flags = 0; 543 } 544 EXPORT_SYMBOL_GPL(hpet_unregister_irq_handler); 545 546 /* 547 * Timer 1 for RTC emulation. We use one shot mode, as periodic mode 548 * is not supported by all HPET implementations for timer 1. 549 * 550 * hpet_rtc_timer_init() is called when the rtc is initialized. 551 */ 552 int hpet_rtc_timer_init(void) 553 { 554 unsigned long cfg, cnt, delta, flags; 555 556 if (!is_hpet_enabled()) 557 return 0; 558 559 if (!hpet_default_delta) { 560 uint64_t clc; 561 562 clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC; 563 clc >>= hpet_clockevent.shift + DEFAULT_RTC_SHIFT; 564 hpet_default_delta = (unsigned long) clc; 565 } 566 567 if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit) 568 delta = hpet_default_delta; 569 else 570 delta = hpet_pie_delta; 571 572 local_irq_save(flags); 573 574 cnt = delta + hpet_readl(HPET_COUNTER); 575 hpet_writel(cnt, HPET_T1_CMP); 576 hpet_t1_cmp = cnt; 577 578 cfg = hpet_readl(HPET_T1_CFG); 579 cfg &= ~HPET_TN_PERIODIC; 580 cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; 581 hpet_writel(cfg, HPET_T1_CFG); 582 583 local_irq_restore(flags); 584 585 return 1; 586 } 587 EXPORT_SYMBOL_GPL(hpet_rtc_timer_init); 588 589 /* 590 * The functions below are called from rtc driver. 591 * Return 0 if HPET is not being used. 592 * Otherwise do the necessary changes and return 1. 593 */ 594 int hpet_mask_rtc_irq_bit(unsigned long bit_mask) 595 { 596 if (!is_hpet_enabled()) 597 return 0; 598 599 hpet_rtc_flags &= ~bit_mask; 600 return 1; 601 } 602 EXPORT_SYMBOL_GPL(hpet_mask_rtc_irq_bit); 603 604 int hpet_set_rtc_irq_bit(unsigned long bit_mask) 605 { 606 unsigned long oldbits = hpet_rtc_flags; 607 608 if (!is_hpet_enabled()) 609 return 0; 610 611 hpet_rtc_flags |= bit_mask; 612 613 if ((bit_mask & RTC_UIE) && !(oldbits & RTC_UIE)) 614 hpet_prev_update_sec = -1; 615 616 if (!oldbits) 617 hpet_rtc_timer_init(); 618 619 return 1; 620 } 621 EXPORT_SYMBOL_GPL(hpet_set_rtc_irq_bit); 622 623 int hpet_set_alarm_time(unsigned char hrs, unsigned char min, 624 unsigned char sec) 625 { 626 if (!is_hpet_enabled()) 627 return 0; 628 629 hpet_alarm_time.tm_hour = hrs; 630 hpet_alarm_time.tm_min = min; 631 hpet_alarm_time.tm_sec = sec; 632 633 return 1; 634 } 635 EXPORT_SYMBOL_GPL(hpet_set_alarm_time); 636 637 int hpet_set_periodic_freq(unsigned long freq) 638 { 639 uint64_t clc; 640 641 if (!is_hpet_enabled()) 642 return 0; 643 644 if (freq <= DEFAULT_RTC_INT_FREQ) 645 hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq; 646 else { 647 clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC; 648 do_div(clc, freq); 649 clc >>= hpet_clockevent.shift; 650 hpet_pie_delta = (unsigned long) clc; 651 } 652 return 1; 653 } 654 EXPORT_SYMBOL_GPL(hpet_set_periodic_freq); 655 656 int hpet_rtc_dropped_irq(void) 657 { 658 return is_hpet_enabled(); 659 } 660 EXPORT_SYMBOL_GPL(hpet_rtc_dropped_irq); 661 662 static void hpet_rtc_timer_reinit(void) 663 { 664 unsigned long cfg, delta; 665 int lost_ints = -1; 666 667 if (unlikely(!hpet_rtc_flags)) { 668 cfg = hpet_readl(HPET_T1_CFG); 669 cfg &= ~HPET_TN_ENABLE; 670 hpet_writel(cfg, HPET_T1_CFG); 671 return; 672 } 673 674 if (!(hpet_rtc_flags & RTC_PIE) || hpet_pie_limit) 675 delta = hpet_default_delta; 676 else 677 delta = hpet_pie_delta; 678 679 /* 680 * Increment the comparator value until we are ahead of the 681 * current count. 682 */ 683 do { 684 hpet_t1_cmp += delta; 685 hpet_writel(hpet_t1_cmp, HPET_T1_CMP); 686 lost_ints++; 687 } while ((long)(hpet_readl(HPET_COUNTER) - hpet_t1_cmp) > 0); 688 689 if (lost_ints) { 690 if (hpet_rtc_flags & RTC_PIE) 691 hpet_pie_count += lost_ints; 692 if (printk_ratelimit()) 693 printk(KERN_WARNING "hpet1: lost %d rtc interrupts\n", 694 lost_ints); 695 } 696 } 697 698 irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) 699 { 700 struct rtc_time curr_time; 701 unsigned long rtc_int_flag = 0; 702 703 hpet_rtc_timer_reinit(); 704 memset(&curr_time, 0, sizeof(struct rtc_time)); 705 706 if (hpet_rtc_flags & (RTC_UIE | RTC_AIE)) 707 get_rtc_time(&curr_time); 708 709 if (hpet_rtc_flags & RTC_UIE && 710 curr_time.tm_sec != hpet_prev_update_sec) { 711 if (hpet_prev_update_sec >= 0) 712 rtc_int_flag = RTC_UF; 713 hpet_prev_update_sec = curr_time.tm_sec; 714 } 715 716 if (hpet_rtc_flags & RTC_PIE && 717 ++hpet_pie_count >= hpet_pie_limit) { 718 rtc_int_flag |= RTC_PF; 719 hpet_pie_count = 0; 720 } 721 722 if (hpet_rtc_flags & RTC_AIE && 723 (curr_time.tm_sec == hpet_alarm_time.tm_sec) && 724 (curr_time.tm_min == hpet_alarm_time.tm_min) && 725 (curr_time.tm_hour == hpet_alarm_time.tm_hour)) 726 rtc_int_flag |= RTC_AF; 727 728 if (rtc_int_flag) { 729 rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8)); 730 if (irq_handler) 731 irq_handler(rtc_int_flag, dev_id); 732 } 733 return IRQ_HANDLED; 734 } 735 EXPORT_SYMBOL_GPL(hpet_rtc_interrupt); 736 #endif 737