diff options
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 963ad0b6a4e9..f1695d7fa0fa 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -143,6 +143,43 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler) | |||
| 143 | 143 | ||
| 144 | /*----------------------------------------------------------------*/ | 144 | /*----------------------------------------------------------------*/ |
| 145 | 145 | ||
| 146 | #ifdef RTC_PORT | ||
| 147 | |||
| 148 | /* Most newer x86 systems have two register banks, the first used | ||
| 149 | * for RTC and NVRAM and the second only for NVRAM. Caller must | ||
| 150 | * own rtc_lock ... and we won't worry about access during NMI. | ||
| 151 | */ | ||
| 152 | #define can_bank2 true | ||
| 153 | |||
| 154 | static inline unsigned char cmos_read_bank2(unsigned char addr) | ||
| 155 | { | ||
| 156 | outb(addr, RTC_PORT(2)); | ||
| 157 | return inb(RTC_PORT(3)); | ||
| 158 | } | ||
| 159 | |||
| 160 | static inline void cmos_write_bank2(unsigned char val, unsigned char addr) | ||
| 161 | { | ||
| 162 | outb(addr, RTC_PORT(2)); | ||
| 163 | outb(val, RTC_PORT(2)); | ||
| 164 | } | ||
| 165 | |||
| 166 | #else | ||
| 167 | |||
| 168 | #define can_bank2 false | ||
| 169 | |||
| 170 | static inline unsigned char cmos_read_bank2(unsigned char addr) | ||
| 171 | { | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | static inline void cmos_write_bank2(unsigned char val, unsigned char addr) | ||
| 176 | { | ||
| 177 | } | ||
| 178 | |||
| 179 | #endif | ||
| 180 | |||
| 181 | /*----------------------------------------------------------------*/ | ||
| 182 | |||
| 146 | static int cmos_read_time(struct device *dev, struct rtc_time *t) | 183 | static int cmos_read_time(struct device *dev, struct rtc_time *t) |
| 147 | { | 184 | { |
| 148 | /* REVISIT: if the clock has a "century" register, use | 185 | /* REVISIT: if the clock has a "century" register, use |
| @@ -491,12 +528,21 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
| 491 | 528 | ||
| 492 | if (unlikely(off >= attr->size)) | 529 | if (unlikely(off >= attr->size)) |
| 493 | return 0; | 530 | return 0; |
| 531 | if (unlikely(off < 0)) | ||
| 532 | return -EINVAL; | ||
| 494 | if ((off + count) > attr->size) | 533 | if ((off + count) > attr->size) |
| 495 | count = attr->size - off; | 534 | count = attr->size - off; |
| 496 | 535 | ||
| 536 | off += NVRAM_OFFSET; | ||
| 497 | spin_lock_irq(&rtc_lock); | 537 | spin_lock_irq(&rtc_lock); |
| 498 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) | 538 | for (retval = 0; count; count--, off++, retval++) { |
| 499 | *buf++ = CMOS_READ(off); | 539 | if (off < 128) |
| 540 | *buf++ = CMOS_READ(off); | ||
| 541 | else if (can_bank2) | ||
| 542 | *buf++ = cmos_read_bank2(off); | ||
| 543 | else | ||
| 544 | break; | ||
| 545 | } | ||
| 500 | spin_unlock_irq(&rtc_lock); | 546 | spin_unlock_irq(&rtc_lock); |
| 501 | 547 | ||
| 502 | return retval; | 548 | return retval; |
| @@ -512,6 +558,8 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
| 512 | cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); | 558 | cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); |
| 513 | if (unlikely(off >= attr->size)) | 559 | if (unlikely(off >= attr->size)) |
| 514 | return -EFBIG; | 560 | return -EFBIG; |
| 561 | if (unlikely(off < 0)) | ||
| 562 | return -EINVAL; | ||
| 515 | if ((off + count) > attr->size) | 563 | if ((off + count) > attr->size) |
| 516 | count = attr->size - off; | 564 | count = attr->size - off; |
| 517 | 565 | ||
| @@ -520,15 +568,20 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
| 520 | * here. If userspace is smart enough to know what fields of | 568 | * here. If userspace is smart enough to know what fields of |
| 521 | * NVRAM to update, updating checksums is also part of its job. | 569 | * NVRAM to update, updating checksums is also part of its job. |
| 522 | */ | 570 | */ |
| 571 | off += NVRAM_OFFSET; | ||
| 523 | spin_lock_irq(&rtc_lock); | 572 | spin_lock_irq(&rtc_lock); |
| 524 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) { | 573 | for (retval = 0; count; count--, off++, retval++) { |
| 525 | /* don't trash RTC registers */ | 574 | /* don't trash RTC registers */ |
| 526 | if (off == cmos->day_alrm | 575 | if (off == cmos->day_alrm |
| 527 | || off == cmos->mon_alrm | 576 | || off == cmos->mon_alrm |
| 528 | || off == cmos->century) | 577 | || off == cmos->century) |
| 529 | buf++; | 578 | buf++; |
| 530 | else | 579 | else if (off < 128) |
| 531 | CMOS_WRITE(*buf++, off); | 580 | CMOS_WRITE(*buf++, off); |
| 581 | else if (can_bank2) | ||
| 582 | cmos_write_bank2(*buf++, off); | ||
| 583 | else | ||
| 584 | break; | ||
| 532 | } | 585 | } |
| 533 | spin_unlock_irq(&rtc_lock); | 586 | spin_unlock_irq(&rtc_lock); |
| 534 | 587 | ||
| @@ -631,8 +684,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 631 | 684 | ||
| 632 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM | 685 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM |
| 633 | * driver did, but don't reject unknown configs. Old hardware | 686 | * driver did, but don't reject unknown configs. Old hardware |
| 634 | * won't address 128 bytes, and for now we ignore the way newer | 687 | * won't address 128 bytes. Newer chips have multiple banks, |
| 635 | * chips can address 256 bytes (using two more i/o ports). | 688 | * though they may not be listed in one I/O resource. |
| 636 | */ | 689 | */ |
| 637 | #if defined(CONFIG_ATARI) | 690 | #if defined(CONFIG_ATARI) |
| 638 | address_space = 64; | 691 | address_space = 64; |
| @@ -642,6 +695,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 642 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 695 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
| 643 | address_space = 128; | 696 | address_space = 128; |
| 644 | #endif | 697 | #endif |
| 698 | if (can_bank2 && ports->end > (ports->start + 1)) | ||
| 699 | address_space = 256; | ||
| 645 | 700 | ||
| 646 | /* For ACPI systems extension info comes from the FADT. On others, | 701 | /* For ACPI systems extension info comes from the FADT. On others, |
| 647 | * board specific setup provides it as appropriate. Systems where | 702 | * board specific setup provides it as appropriate. Systems where |
| @@ -740,7 +795,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 740 | goto cleanup2; | 795 | goto cleanup2; |
| 741 | } | 796 | } |
| 742 | 797 | ||
| 743 | pr_info("%s: alarms up to one %s%s%s\n", | 798 | pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n", |
| 744 | cmos_rtc.rtc->dev.bus_id, | 799 | cmos_rtc.rtc->dev.bus_id, |
| 745 | is_valid_irq(rtc_irq) | 800 | is_valid_irq(rtc_irq) |
| 746 | ? (cmos_rtc.mon_alrm | 801 | ? (cmos_rtc.mon_alrm |
| @@ -749,6 +804,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 749 | ? "month" : "day")) | 804 | ? "month" : "day")) |
| 750 | : "no", | 805 | : "no", |
| 751 | cmos_rtc.century ? ", y3k" : "", | 806 | cmos_rtc.century ? ", y3k" : "", |
| 807 | nvram.size, | ||
| 752 | is_hpet_enabled() ? ", hpet irqs" : ""); | 808 | is_hpet_enabled() ? ", hpet irqs" : ""); |
| 753 | 809 | ||
| 754 | return 0; | 810 | return 0; |
