diff options
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 91 |
1 files changed, 73 insertions, 18 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 963ad0b6a4e9..5549231179a2 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 |
@@ -203,26 +240,26 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
203 | /* REVISIT this assumes PC style usage: always BCD */ | 240 | /* REVISIT this assumes PC style usage: always BCD */ |
204 | 241 | ||
205 | if (((unsigned)t->time.tm_sec) < 0x60) | 242 | if (((unsigned)t->time.tm_sec) < 0x60) |
206 | t->time.tm_sec = BCD2BIN(t->time.tm_sec); | 243 | t->time.tm_sec = bcd2bin(t->time.tm_sec); |
207 | else | 244 | else |
208 | t->time.tm_sec = -1; | 245 | t->time.tm_sec = -1; |
209 | if (((unsigned)t->time.tm_min) < 0x60) | 246 | if (((unsigned)t->time.tm_min) < 0x60) |
210 | t->time.tm_min = BCD2BIN(t->time.tm_min); | 247 | t->time.tm_min = bcd2bin(t->time.tm_min); |
211 | else | 248 | else |
212 | t->time.tm_min = -1; | 249 | t->time.tm_min = -1; |
213 | if (((unsigned)t->time.tm_hour) < 0x24) | 250 | if (((unsigned)t->time.tm_hour) < 0x24) |
214 | t->time.tm_hour = BCD2BIN(t->time.tm_hour); | 251 | t->time.tm_hour = bcd2bin(t->time.tm_hour); |
215 | else | 252 | else |
216 | t->time.tm_hour = -1; | 253 | t->time.tm_hour = -1; |
217 | 254 | ||
218 | if (cmos->day_alrm) { | 255 | if (cmos->day_alrm) { |
219 | if (((unsigned)t->time.tm_mday) <= 0x31) | 256 | if (((unsigned)t->time.tm_mday) <= 0x31) |
220 | t->time.tm_mday = BCD2BIN(t->time.tm_mday); | 257 | t->time.tm_mday = bcd2bin(t->time.tm_mday); |
221 | else | 258 | else |
222 | t->time.tm_mday = -1; | 259 | t->time.tm_mday = -1; |
223 | if (cmos->mon_alrm) { | 260 | if (cmos->mon_alrm) { |
224 | if (((unsigned)t->time.tm_mon) <= 0x12) | 261 | if (((unsigned)t->time.tm_mon) <= 0x12) |
225 | t->time.tm_mon = BCD2BIN(t->time.tm_mon) - 1; | 262 | t->time.tm_mon = bcd2bin(t->time.tm_mon) - 1; |
226 | else | 263 | else |
227 | t->time.tm_mon = -1; | 264 | t->time.tm_mon = -1; |
228 | } | 265 | } |
@@ -294,19 +331,19 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
294 | /* Writing 0xff means "don't care" or "match all". */ | 331 | /* Writing 0xff means "don't care" or "match all". */ |
295 | 332 | ||
296 | mon = t->time.tm_mon + 1; | 333 | mon = t->time.tm_mon + 1; |
297 | mon = (mon <= 12) ? BIN2BCD(mon) : 0xff; | 334 | mon = (mon <= 12) ? bin2bcd(mon) : 0xff; |
298 | 335 | ||
299 | mday = t->time.tm_mday; | 336 | mday = t->time.tm_mday; |
300 | mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff; | 337 | mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff; |
301 | 338 | ||
302 | hrs = t->time.tm_hour; | 339 | hrs = t->time.tm_hour; |
303 | hrs = (hrs < 24) ? BIN2BCD(hrs) : 0xff; | 340 | hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff; |
304 | 341 | ||
305 | min = t->time.tm_min; | 342 | min = t->time.tm_min; |
306 | min = (min < 60) ? BIN2BCD(min) : 0xff; | 343 | min = (min < 60) ? bin2bcd(min) : 0xff; |
307 | 344 | ||
308 | sec = t->time.tm_sec; | 345 | sec = t->time.tm_sec; |
309 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; | 346 | sec = (sec < 60) ? bin2bcd(sec) : 0xff; |
310 | 347 | ||
311 | spin_lock_irq(&rtc_lock); | 348 | spin_lock_irq(&rtc_lock); |
312 | 349 | ||
@@ -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 | ||
@@ -539,7 +592,6 @@ static struct bin_attribute nvram = { | |||
539 | .attr = { | 592 | .attr = { |
540 | .name = "nvram", | 593 | .name = "nvram", |
541 | .mode = S_IRUGO | S_IWUSR, | 594 | .mode = S_IRUGO | S_IWUSR, |
542 | .owner = THIS_MODULE, | ||
543 | }, | 595 | }, |
544 | 596 | ||
545 | .read = cmos_nvram_read, | 597 | .read = cmos_nvram_read, |
@@ -631,8 +683,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
631 | 683 | ||
632 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM | 684 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM |
633 | * driver did, but don't reject unknown configs. Old hardware | 685 | * driver did, but don't reject unknown configs. Old hardware |
634 | * won't address 128 bytes, and for now we ignore the way newer | 686 | * won't address 128 bytes. Newer chips have multiple banks, |
635 | * chips can address 256 bytes (using two more i/o ports). | 687 | * though they may not be listed in one I/O resource. |
636 | */ | 688 | */ |
637 | #if defined(CONFIG_ATARI) | 689 | #if defined(CONFIG_ATARI) |
638 | address_space = 64; | 690 | address_space = 64; |
@@ -642,6 +694,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. | 694 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
643 | address_space = 128; | 695 | address_space = 128; |
644 | #endif | 696 | #endif |
697 | if (can_bank2 && ports->end > (ports->start + 1)) | ||
698 | address_space = 256; | ||
645 | 699 | ||
646 | /* For ACPI systems extension info comes from the FADT. On others, | 700 | /* For ACPI systems extension info comes from the FADT. On others, |
647 | * board specific setup provides it as appropriate. Systems where | 701 | * board specific setup provides it as appropriate. Systems where |
@@ -740,7 +794,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
740 | goto cleanup2; | 794 | goto cleanup2; |
741 | } | 795 | } |
742 | 796 | ||
743 | pr_info("%s: alarms up to one %s%s%s\n", | 797 | pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n", |
744 | cmos_rtc.rtc->dev.bus_id, | 798 | cmos_rtc.rtc->dev.bus_id, |
745 | is_valid_irq(rtc_irq) | 799 | is_valid_irq(rtc_irq) |
746 | ? (cmos_rtc.mon_alrm | 800 | ? (cmos_rtc.mon_alrm |
@@ -749,6 +803,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
749 | ? "month" : "day")) | 803 | ? "month" : "day")) |
750 | : "no", | 804 | : "no", |
751 | cmos_rtc.century ? ", y3k" : "", | 805 | cmos_rtc.century ? ", y3k" : "", |
806 | nvram.size, | ||
752 | is_hpet_enabled() ? ", hpet irqs" : ""); | 807 | is_hpet_enabled() ? ", hpet irqs" : ""); |
753 | 808 | ||
754 | return 0; | 809 | return 0; |