| .. | .. |
|---|
| 53 | 53 | |
|---|
| 54 | 54 | #define RTC_VERSION "1.10d" |
|---|
| 55 | 55 | |
|---|
| 56 | | -static DEFINE_MUTEX(hp_sdc_rtc_mutex); |
|---|
| 57 | 56 | static unsigned long epoch = 2000; |
|---|
| 58 | 57 | |
|---|
| 59 | 58 | static struct semaphore i8042tregs; |
|---|
| 60 | | - |
|---|
| 61 | | -static hp_sdc_irqhook hp_sdc_rtc_isr; |
|---|
| 62 | | - |
|---|
| 63 | | -static struct fasync_struct *hp_sdc_rtc_async_queue; |
|---|
| 64 | | - |
|---|
| 65 | | -static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); |
|---|
| 66 | | - |
|---|
| 67 | | -static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, |
|---|
| 68 | | - size_t count, loff_t *ppos); |
|---|
| 69 | | - |
|---|
| 70 | | -static long hp_sdc_rtc_unlocked_ioctl(struct file *file, |
|---|
| 71 | | - unsigned int cmd, unsigned long arg); |
|---|
| 72 | | - |
|---|
| 73 | | -static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait); |
|---|
| 74 | | - |
|---|
| 75 | | -static int hp_sdc_rtc_open(struct inode *inode, struct file *file); |
|---|
| 76 | | -static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on); |
|---|
| 77 | 59 | |
|---|
| 78 | 60 | static void hp_sdc_rtc_isr (int irq, void *dev_id, |
|---|
| 79 | 61 | uint8_t status, uint8_t data) |
|---|
| .. | .. |
|---|
| 283 | 265 | return 0; |
|---|
| 284 | 266 | } |
|---|
| 285 | 267 | |
|---|
| 286 | | - |
|---|
| 287 | | -#if 0 /* not used yet */ |
|---|
| 288 | | -/* Set the i8042 real-time clock */ |
|---|
| 289 | | -static int hp_sdc_rtc_set_rt (struct timeval *setto) |
|---|
| 290 | | -{ |
|---|
| 291 | | - uint32_t tenms; |
|---|
| 292 | | - unsigned int days; |
|---|
| 293 | | - hp_sdc_transaction t; |
|---|
| 294 | | - uint8_t tseq[11] = { |
|---|
| 295 | | - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, |
|---|
| 296 | | - HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0, |
|---|
| 297 | | - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, |
|---|
| 298 | | - HP_SDC_CMD_SET_RTD, 2, 0, 0 |
|---|
| 299 | | - }; |
|---|
| 300 | | - |
|---|
| 301 | | - t.endidx = 10; |
|---|
| 302 | | - |
|---|
| 303 | | - if (0xffff < setto->tv_sec / 86400) return -1; |
|---|
| 304 | | - days = setto->tv_sec / 86400; |
|---|
| 305 | | - if (0xffff < setto->tv_usec / 1000000 / 86400) return -1; |
|---|
| 306 | | - days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400; |
|---|
| 307 | | - if (days > 0xffff) return -1; |
|---|
| 308 | | - |
|---|
| 309 | | - if (0xffffff < setto->tv_sec) return -1; |
|---|
| 310 | | - tenms = setto->tv_sec * 100; |
|---|
| 311 | | - if (0xffffff < setto->tv_usec / 10000) return -1; |
|---|
| 312 | | - tenms += setto->tv_usec / 10000; |
|---|
| 313 | | - if (tenms > 0xffffff) return -1; |
|---|
| 314 | | - |
|---|
| 315 | | - tseq[3] = (uint8_t)(tenms & 0xff); |
|---|
| 316 | | - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); |
|---|
| 317 | | - tseq[5] = (uint8_t)((tenms >> 16) & 0xff); |
|---|
| 318 | | - |
|---|
| 319 | | - tseq[9] = (uint8_t)(days & 0xff); |
|---|
| 320 | | - tseq[10] = (uint8_t)((days >> 8) & 0xff); |
|---|
| 321 | | - |
|---|
| 322 | | - t.seq = tseq; |
|---|
| 323 | | - |
|---|
| 324 | | - if (hp_sdc_enqueue_transaction(&t)) return -1; |
|---|
| 325 | | - return 0; |
|---|
| 326 | | -} |
|---|
| 327 | | - |
|---|
| 328 | | -/* Set the i8042 fast handshake timer */ |
|---|
| 329 | | -static int hp_sdc_rtc_set_fhs (struct timeval *setto) |
|---|
| 330 | | -{ |
|---|
| 331 | | - uint32_t tenms; |
|---|
| 332 | | - hp_sdc_transaction t; |
|---|
| 333 | | - uint8_t tseq[5] = { |
|---|
| 334 | | - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, |
|---|
| 335 | | - HP_SDC_CMD_SET_FHS, 2, 0, 0 |
|---|
| 336 | | - }; |
|---|
| 337 | | - |
|---|
| 338 | | - t.endidx = 4; |
|---|
| 339 | | - |
|---|
| 340 | | - if (0xffff < setto->tv_sec) return -1; |
|---|
| 341 | | - tenms = setto->tv_sec * 100; |
|---|
| 342 | | - if (0xffff < setto->tv_usec / 10000) return -1; |
|---|
| 343 | | - tenms += setto->tv_usec / 10000; |
|---|
| 344 | | - if (tenms > 0xffff) return -1; |
|---|
| 345 | | - |
|---|
| 346 | | - tseq[3] = (uint8_t)(tenms & 0xff); |
|---|
| 347 | | - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); |
|---|
| 348 | | - |
|---|
| 349 | | - t.seq = tseq; |
|---|
| 350 | | - |
|---|
| 351 | | - if (hp_sdc_enqueue_transaction(&t)) return -1; |
|---|
| 352 | | - return 0; |
|---|
| 353 | | -} |
|---|
| 354 | | - |
|---|
| 355 | | - |
|---|
| 356 | | -/* Set the i8042 match timer (a.k.a. alarm) */ |
|---|
| 357 | | -#define hp_sdc_rtc_set_mt (setto) \ |
|---|
| 358 | | - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT) |
|---|
| 359 | | - |
|---|
| 360 | | -/* Set the i8042 delay timer */ |
|---|
| 361 | | -#define hp_sdc_rtc_set_dt (setto) \ |
|---|
| 362 | | - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT) |
|---|
| 363 | | - |
|---|
| 364 | | -/* Set the i8042 cycle timer (a.k.a. periodic) */ |
|---|
| 365 | | -#define hp_sdc_rtc_set_ct (setto) \ |
|---|
| 366 | | - hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT) |
|---|
| 367 | | - |
|---|
| 368 | | -/* Set one of the i8042 3-byte wide timers */ |
|---|
| 369 | | -static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) |
|---|
| 370 | | -{ |
|---|
| 371 | | - uint32_t tenms; |
|---|
| 372 | | - hp_sdc_transaction t; |
|---|
| 373 | | - uint8_t tseq[6] = { |
|---|
| 374 | | - HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT, |
|---|
| 375 | | - 0, 3, 0, 0, 0 |
|---|
| 376 | | - }; |
|---|
| 377 | | - |
|---|
| 378 | | - t.endidx = 6; |
|---|
| 379 | | - |
|---|
| 380 | | - if (0xffffff < setto->tv_sec) return -1; |
|---|
| 381 | | - tenms = setto->tv_sec * 100; |
|---|
| 382 | | - if (0xffffff < setto->tv_usec / 10000) return -1; |
|---|
| 383 | | - tenms += setto->tv_usec / 10000; |
|---|
| 384 | | - if (tenms > 0xffffff) return -1; |
|---|
| 385 | | - |
|---|
| 386 | | - tseq[1] = setcmd; |
|---|
| 387 | | - tseq[3] = (uint8_t)(tenms & 0xff); |
|---|
| 388 | | - tseq[4] = (uint8_t)((tenms >> 8) & 0xff); |
|---|
| 389 | | - tseq[5] = (uint8_t)((tenms >> 16) & 0xff); |
|---|
| 390 | | - |
|---|
| 391 | | - t.seq = tseq; |
|---|
| 392 | | - |
|---|
| 393 | | - if (hp_sdc_enqueue_transaction(&t)) { |
|---|
| 394 | | - return -1; |
|---|
| 395 | | - } |
|---|
| 396 | | - return 0; |
|---|
| 397 | | -} |
|---|
| 398 | | -#endif |
|---|
| 399 | | - |
|---|
| 400 | | -static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf, |
|---|
| 401 | | - size_t count, loff_t *ppos) { |
|---|
| 402 | | - ssize_t retval; |
|---|
| 403 | | - |
|---|
| 404 | | - if (count < sizeof(unsigned long)) |
|---|
| 405 | | - return -EINVAL; |
|---|
| 406 | | - |
|---|
| 407 | | - retval = put_user(68, (unsigned long __user *)buf); |
|---|
| 408 | | - return retval; |
|---|
| 409 | | -} |
|---|
| 410 | | - |
|---|
| 411 | | -static __poll_t hp_sdc_rtc_poll(struct file *file, poll_table *wait) |
|---|
| 412 | | -{ |
|---|
| 413 | | - unsigned long l; |
|---|
| 414 | | - |
|---|
| 415 | | - l = 0; |
|---|
| 416 | | - if (l != 0) |
|---|
| 417 | | - return EPOLLIN | EPOLLRDNORM; |
|---|
| 418 | | - return 0; |
|---|
| 419 | | -} |
|---|
| 420 | | - |
|---|
| 421 | | -static int hp_sdc_rtc_open(struct inode *inode, struct file *file) |
|---|
| 422 | | -{ |
|---|
| 423 | | - return 0; |
|---|
| 424 | | -} |
|---|
| 425 | | - |
|---|
| 426 | | -static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on) |
|---|
| 427 | | -{ |
|---|
| 428 | | - return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue); |
|---|
| 429 | | -} |
|---|
| 430 | | - |
|---|
| 431 | 268 | static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v) |
|---|
| 432 | 269 | { |
|---|
| 433 | 270 | #define YN(bit) ("no") |
|---|
| .. | .. |
|---|
| 441 | 278 | seq_puts(m, "BBRTC\t\t: READ FAILED!\n"); |
|---|
| 442 | 279 | } else { |
|---|
| 443 | 280 | seq_printf(m, |
|---|
| 444 | | - "rtc_time\t: %02d:%02d:%02d\n" |
|---|
| 445 | | - "rtc_date\t: %04d-%02d-%02d\n" |
|---|
| 281 | + "rtc_time\t: %ptRt\n" |
|---|
| 282 | + "rtc_date\t: %ptRd\n" |
|---|
| 446 | 283 | "rtc_epoch\t: %04lu\n", |
|---|
| 447 | | - tm.tm_hour, tm.tm_min, tm.tm_sec, |
|---|
| 448 | | - tm.tm_year + 1900, tm.tm_mon + 1, |
|---|
| 449 | | - tm.tm_mday, epoch); |
|---|
| 284 | + &tm, &tm, epoch); |
|---|
| 450 | 285 | } |
|---|
| 451 | 286 | |
|---|
| 452 | 287 | if (hp_sdc_rtc_read_rt(&tv)) { |
|---|
| .. | .. |
|---|
| 509 | 344 | #undef NY |
|---|
| 510 | 345 | } |
|---|
| 511 | 346 | |
|---|
| 512 | | -static int hp_sdc_rtc_ioctl(struct file *file, |
|---|
| 513 | | - unsigned int cmd, unsigned long arg) |
|---|
| 514 | | -{ |
|---|
| 515 | | -#if 1 |
|---|
| 516 | | - return -EINVAL; |
|---|
| 517 | | -#else |
|---|
| 518 | | - |
|---|
| 519 | | - struct rtc_time wtime; |
|---|
| 520 | | - struct timeval ttime; |
|---|
| 521 | | - int use_wtime = 0; |
|---|
| 522 | | - |
|---|
| 523 | | - /* This needs major work. */ |
|---|
| 524 | | - |
|---|
| 525 | | - switch (cmd) { |
|---|
| 526 | | - |
|---|
| 527 | | - case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ |
|---|
| 528 | | - case RTC_AIE_ON: /* Allow alarm interrupts. */ |
|---|
| 529 | | - case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ |
|---|
| 530 | | - case RTC_PIE_ON: /* Allow periodic ints */ |
|---|
| 531 | | - case RTC_UIE_ON: /* Allow ints for RTC updates. */ |
|---|
| 532 | | - case RTC_UIE_OFF: /* Allow ints for RTC updates. */ |
|---|
| 533 | | - { |
|---|
| 534 | | - /* We cannot mask individual user timers and we |
|---|
| 535 | | - cannot tell them apart when they occur, so it |
|---|
| 536 | | - would be disingenuous to succeed these IOCTLs */ |
|---|
| 537 | | - return -EINVAL; |
|---|
| 538 | | - } |
|---|
| 539 | | - case RTC_ALM_READ: /* Read the present alarm time */ |
|---|
| 540 | | - { |
|---|
| 541 | | - if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT; |
|---|
| 542 | | - if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; |
|---|
| 543 | | - |
|---|
| 544 | | - wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600; |
|---|
| 545 | | - wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60; |
|---|
| 546 | | - wtime.tm_sec = ttime.tv_sec; |
|---|
| 547 | | - |
|---|
| 548 | | - break; |
|---|
| 549 | | - } |
|---|
| 550 | | - case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ |
|---|
| 551 | | - { |
|---|
| 552 | | - return put_user(hp_sdc_rtc_freq, (unsigned long *)arg); |
|---|
| 553 | | - } |
|---|
| 554 | | - case RTC_IRQP_SET: /* Set periodic IRQ rate. */ |
|---|
| 555 | | - { |
|---|
| 556 | | - /* |
|---|
| 557 | | - * The max we can do is 100Hz. |
|---|
| 558 | | - */ |
|---|
| 559 | | - |
|---|
| 560 | | - if ((arg < 1) || (arg > 100)) return -EINVAL; |
|---|
| 561 | | - ttime.tv_sec = 0; |
|---|
| 562 | | - ttime.tv_usec = 1000000 / arg; |
|---|
| 563 | | - if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT; |
|---|
| 564 | | - hp_sdc_rtc_freq = arg; |
|---|
| 565 | | - return 0; |
|---|
| 566 | | - } |
|---|
| 567 | | - case RTC_ALM_SET: /* Store a time into the alarm */ |
|---|
| 568 | | - { |
|---|
| 569 | | - /* |
|---|
| 570 | | - * This expects a struct hp_sdc_rtc_time. Writing 0xff means |
|---|
| 571 | | - * "don't care" or "match all" for PC timers. The HP SDC |
|---|
| 572 | | - * does not support that perk, but it could be emulated fairly |
|---|
| 573 | | - * easily. Only the tm_hour, tm_min and tm_sec are used. |
|---|
| 574 | | - * We could do it with 10ms accuracy with the HP SDC, if the |
|---|
| 575 | | - * rtc interface left us a way to do that. |
|---|
| 576 | | - */ |
|---|
| 577 | | - struct hp_sdc_rtc_time alm_tm; |
|---|
| 578 | | - |
|---|
| 579 | | - if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg, |
|---|
| 580 | | - sizeof(struct hp_sdc_rtc_time))) |
|---|
| 581 | | - return -EFAULT; |
|---|
| 582 | | - |
|---|
| 583 | | - if (alm_tm.tm_hour > 23) return -EINVAL; |
|---|
| 584 | | - if (alm_tm.tm_min > 59) return -EINVAL; |
|---|
| 585 | | - if (alm_tm.tm_sec > 59) return -EINVAL; |
|---|
| 586 | | - |
|---|
| 587 | | - ttime.sec = alm_tm.tm_hour * 3600 + |
|---|
| 588 | | - alm_tm.tm_min * 60 + alm_tm.tm_sec; |
|---|
| 589 | | - ttime.usec = 0; |
|---|
| 590 | | - if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT; |
|---|
| 591 | | - return 0; |
|---|
| 592 | | - } |
|---|
| 593 | | - case RTC_RD_TIME: /* Read the time/date from RTC */ |
|---|
| 594 | | - { |
|---|
| 595 | | - if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT; |
|---|
| 596 | | - break; |
|---|
| 597 | | - } |
|---|
| 598 | | - case RTC_SET_TIME: /* Set the RTC */ |
|---|
| 599 | | - { |
|---|
| 600 | | - struct rtc_time hp_sdc_rtc_tm; |
|---|
| 601 | | - unsigned char mon, day, hrs, min, sec, leap_yr; |
|---|
| 602 | | - unsigned int yrs; |
|---|
| 603 | | - |
|---|
| 604 | | - if (!capable(CAP_SYS_TIME)) |
|---|
| 605 | | - return -EACCES; |
|---|
| 606 | | - if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg, |
|---|
| 607 | | - sizeof(struct rtc_time))) |
|---|
| 608 | | - return -EFAULT; |
|---|
| 609 | | - |
|---|
| 610 | | - yrs = hp_sdc_rtc_tm.tm_year + 1900; |
|---|
| 611 | | - mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ |
|---|
| 612 | | - day = hp_sdc_rtc_tm.tm_mday; |
|---|
| 613 | | - hrs = hp_sdc_rtc_tm.tm_hour; |
|---|
| 614 | | - min = hp_sdc_rtc_tm.tm_min; |
|---|
| 615 | | - sec = hp_sdc_rtc_tm.tm_sec; |
|---|
| 616 | | - |
|---|
| 617 | | - if (yrs < 1970) |
|---|
| 618 | | - return -EINVAL; |
|---|
| 619 | | - |
|---|
| 620 | | - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); |
|---|
| 621 | | - |
|---|
| 622 | | - if ((mon > 12) || (day == 0)) |
|---|
| 623 | | - return -EINVAL; |
|---|
| 624 | | - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) |
|---|
| 625 | | - return -EINVAL; |
|---|
| 626 | | - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) |
|---|
| 627 | | - return -EINVAL; |
|---|
| 628 | | - |
|---|
| 629 | | - if ((yrs -= eH) > 255) /* They are unsigned */ |
|---|
| 630 | | - return -EINVAL; |
|---|
| 631 | | - |
|---|
| 632 | | - |
|---|
| 633 | | - return 0; |
|---|
| 634 | | - } |
|---|
| 635 | | - case RTC_EPOCH_READ: /* Read the epoch. */ |
|---|
| 636 | | - { |
|---|
| 637 | | - return put_user (epoch, (unsigned long *)arg); |
|---|
| 638 | | - } |
|---|
| 639 | | - case RTC_EPOCH_SET: /* Set the epoch. */ |
|---|
| 640 | | - { |
|---|
| 641 | | - /* |
|---|
| 642 | | - * There were no RTC clocks before 1900. |
|---|
| 643 | | - */ |
|---|
| 644 | | - if (arg < 1900) |
|---|
| 645 | | - return -EINVAL; |
|---|
| 646 | | - if (!capable(CAP_SYS_TIME)) |
|---|
| 647 | | - return -EACCES; |
|---|
| 648 | | - |
|---|
| 649 | | - epoch = arg; |
|---|
| 650 | | - return 0; |
|---|
| 651 | | - } |
|---|
| 652 | | - default: |
|---|
| 653 | | - return -EINVAL; |
|---|
| 654 | | - } |
|---|
| 655 | | - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; |
|---|
| 656 | | -#endif |
|---|
| 657 | | -} |
|---|
| 658 | | - |
|---|
| 659 | | -static long hp_sdc_rtc_unlocked_ioctl(struct file *file, |
|---|
| 660 | | - unsigned int cmd, unsigned long arg) |
|---|
| 661 | | -{ |
|---|
| 662 | | - int ret; |
|---|
| 663 | | - |
|---|
| 664 | | - mutex_lock(&hp_sdc_rtc_mutex); |
|---|
| 665 | | - ret = hp_sdc_rtc_ioctl(file, cmd, arg); |
|---|
| 666 | | - mutex_unlock(&hp_sdc_rtc_mutex); |
|---|
| 667 | | - |
|---|
| 668 | | - return ret; |
|---|
| 669 | | -} |
|---|
| 670 | | - |
|---|
| 671 | | - |
|---|
| 672 | | -static const struct file_operations hp_sdc_rtc_fops = { |
|---|
| 673 | | - .owner = THIS_MODULE, |
|---|
| 674 | | - .llseek = no_llseek, |
|---|
| 675 | | - .read = hp_sdc_rtc_read, |
|---|
| 676 | | - .poll = hp_sdc_rtc_poll, |
|---|
| 677 | | - .unlocked_ioctl = hp_sdc_rtc_unlocked_ioctl, |
|---|
| 678 | | - .open = hp_sdc_rtc_open, |
|---|
| 679 | | - .fasync = hp_sdc_rtc_fasync, |
|---|
| 680 | | -}; |
|---|
| 681 | | - |
|---|
| 682 | | -static struct miscdevice hp_sdc_rtc_dev = { |
|---|
| 683 | | - .minor = RTC_MINOR, |
|---|
| 684 | | - .name = "rtc_HIL", |
|---|
| 685 | | - .fops = &hp_sdc_rtc_fops |
|---|
| 686 | | -}; |
|---|
| 687 | | - |
|---|
| 688 | 347 | static int __init hp_sdc_rtc_init(void) |
|---|
| 689 | 348 | { |
|---|
| 690 | 349 | int ret; |
|---|
| .. | .. |
|---|
| 698 | 357 | |
|---|
| 699 | 358 | if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) |
|---|
| 700 | 359 | return ret; |
|---|
| 701 | | - if (misc_register(&hp_sdc_rtc_dev) != 0) |
|---|
| 702 | | - printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n"); |
|---|
| 703 | 360 | |
|---|
| 704 | 361 | proc_create_single("driver/rtc", 0, NULL, hp_sdc_rtc_proc_show); |
|---|
| 705 | 362 | |
|---|
| .. | .. |
|---|
| 712 | 369 | static void __exit hp_sdc_rtc_exit(void) |
|---|
| 713 | 370 | { |
|---|
| 714 | 371 | remove_proc_entry ("driver/rtc", NULL); |
|---|
| 715 | | - misc_deregister(&hp_sdc_rtc_dev); |
|---|
| 716 | 372 | hp_sdc_release_timer_irq(hp_sdc_rtc_isr); |
|---|
| 717 | 373 | printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n"); |
|---|
| 718 | 374 | } |
|---|