diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-29 00:06:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-29 17:16:47 -0400 |
commit | 1518e7ed08019539498f772faa1f9368fed91361 (patch) | |
tree | 386393bea6adeba85bb81ae8add9930945f793d7 /arch | |
parent | a0b31b578f9ab34826703762113f9d42f3ae9819 (diff) |
sparc64: Convert Mostek rtc to use generic RTC layer driver.
Based largely upon a patch by Krzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/Kconfig | 1 | ||||
-rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/time.c | 416 |
3 files changed, 103 insertions, 317 deletions
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 19f0cc8a21ed..0a4e342c041d 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
@@ -20,6 +20,7 @@ config SPARC64 | |||
20 | select HAVE_ARCH_TRACEHOOK | 20 | select HAVE_ARCH_TRACEHOOK |
21 | select ARCH_WANT_OPTIONAL_GPIOLIB | 21 | select ARCH_WANT_OPTIONAL_GPIOLIB |
22 | select RTC_CLASS | 22 | select RTC_CLASS |
23 | select RTC_DRV_M48T59 | ||
23 | 24 | ||
24 | config GENERIC_TIME | 25 | config GENERIC_TIME |
25 | bool | 26 | bool |
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 142c16983d14..4c3a6a87c8a4 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <asm/elf.h> | 36 | #include <asm/elf.h> |
37 | #include <asm/head.h> | 37 | #include <asm/head.h> |
38 | #include <asm/smp.h> | 38 | #include <asm/smp.h> |
39 | #include <asm/mostek.h> | ||
40 | #include <asm/ptrace.h> | 39 | #include <asm/ptrace.h> |
41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
42 | #include <asm/checksum.h> | 41 | #include <asm/checksum.h> |
@@ -152,8 +151,6 @@ EXPORT_SYMBOL(flush_dcache_page); | |||
152 | EXPORT_SYMBOL(__flush_dcache_range); | 151 | EXPORT_SYMBOL(__flush_dcache_range); |
153 | #endif | 152 | #endif |
154 | 153 | ||
155 | EXPORT_SYMBOL(mostek_lock); | ||
156 | EXPORT_SYMBOL(mstk48t02_regs); | ||
157 | #ifdef CONFIG_SUN_AUXIO | 154 | #ifdef CONFIG_SUN_AUXIO |
158 | EXPORT_SYMBOL(auxio_set_led); | 155 | EXPORT_SYMBOL(auxio_set_led); |
159 | EXPORT_SYMBOL(auxio_set_lte); | 156 | EXPORT_SYMBOL(auxio_set_lte); |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 184321b88a68..9c2c3d84443d 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -30,13 +30,14 @@ | |||
30 | #include <linux/percpu.h> | 30 | #include <linux/percpu.h> |
31 | #include <linux/miscdevice.h> | 31 | #include <linux/miscdevice.h> |
32 | #include <linux/rtc.h> | 32 | #include <linux/rtc.h> |
33 | #include <linux/rtc/m48t59.h> | ||
33 | #include <linux/kernel_stat.h> | 34 | #include <linux/kernel_stat.h> |
34 | #include <linux/clockchips.h> | 35 | #include <linux/clockchips.h> |
35 | #include <linux/clocksource.h> | 36 | #include <linux/clocksource.h> |
36 | #include <linux/of_device.h> | 37 | #include <linux/of_device.h> |
38 | #include <linux/platform_device.h> | ||
37 | 39 | ||
38 | #include <asm/oplib.h> | 40 | #include <asm/oplib.h> |
39 | #include <asm/mostek.h> | ||
40 | #include <asm/timer.h> | 41 | #include <asm/timer.h> |
41 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
@@ -50,17 +51,12 @@ | |||
50 | 51 | ||
51 | #include "entry.h" | 52 | #include "entry.h" |
52 | 53 | ||
53 | DEFINE_SPINLOCK(mostek_lock); | ||
54 | DEFINE_SPINLOCK(rtc_lock); | 54 | DEFINE_SPINLOCK(rtc_lock); |
55 | void __iomem *mstk48t02_regs = NULL; | ||
56 | #ifdef CONFIG_PCI | 55 | #ifdef CONFIG_PCI |
57 | unsigned long ds1287_regs = 0UL; | 56 | unsigned long ds1287_regs = 0UL; |
58 | static void __iomem *bq4802_regs; | 57 | static void __iomem *bq4802_regs; |
59 | #endif | 58 | #endif |
60 | 59 | ||
61 | static void __iomem *mstk48t08_regs; | ||
62 | static void __iomem *mstk48t59_regs; | ||
63 | |||
64 | static int set_rtc_mmss(unsigned long); | 60 | static int set_rtc_mmss(unsigned long); |
65 | 61 | ||
66 | #define TICK_PRIV_BIT (1UL << 63) | 62 | #define TICK_PRIV_BIT (1UL << 63) |
@@ -413,144 +409,10 @@ int update_persistent_clock(struct timespec now) | |||
413 | return set_rtc_mmss(now.tv_sec); | 409 | return set_rtc_mmss(now.tv_sec); |
414 | } | 410 | } |
415 | 411 | ||
416 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ | ||
417 | static void __init kick_start_clock(void) | ||
418 | { | ||
419 | void __iomem *regs = mstk48t02_regs; | ||
420 | u8 sec, tmp; | ||
421 | int i, count; | ||
422 | |||
423 | prom_printf("CLOCK: Clock was stopped. Kick start "); | ||
424 | |||
425 | spin_lock_irq(&mostek_lock); | ||
426 | |||
427 | /* Turn on the kick start bit to start the oscillator. */ | ||
428 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
429 | tmp |= MSTK_CREG_WRITE; | ||
430 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
431 | tmp = mostek_read(regs + MOSTEK_SEC); | ||
432 | tmp &= ~MSTK_STOP; | ||
433 | mostek_write(regs + MOSTEK_SEC, tmp); | ||
434 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
435 | tmp |= MSTK_KICK_START; | ||
436 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
437 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
438 | tmp &= ~MSTK_CREG_WRITE; | ||
439 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
440 | |||
441 | spin_unlock_irq(&mostek_lock); | ||
442 | |||
443 | /* Delay to allow the clock oscillator to start. */ | ||
444 | sec = MSTK_REG_SEC(regs); | ||
445 | for (i = 0; i < 3; i++) { | ||
446 | while (sec == MSTK_REG_SEC(regs)) | ||
447 | for (count = 0; count < 100000; count++) | ||
448 | /* nothing */ ; | ||
449 | prom_printf("."); | ||
450 | sec = MSTK_REG_SEC(regs); | ||
451 | } | ||
452 | prom_printf("\n"); | ||
453 | |||
454 | spin_lock_irq(&mostek_lock); | ||
455 | |||
456 | /* Turn off kick start and set a "valid" time and date. */ | ||
457 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
458 | tmp |= MSTK_CREG_WRITE; | ||
459 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
460 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
461 | tmp &= ~MSTK_KICK_START; | ||
462 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
463 | MSTK_SET_REG_SEC(regs,0); | ||
464 | MSTK_SET_REG_MIN(regs,0); | ||
465 | MSTK_SET_REG_HOUR(regs,0); | ||
466 | MSTK_SET_REG_DOW(regs,5); | ||
467 | MSTK_SET_REG_DOM(regs,1); | ||
468 | MSTK_SET_REG_MONTH(regs,8); | ||
469 | MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); | ||
470 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
471 | tmp &= ~MSTK_CREG_WRITE; | ||
472 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
473 | |||
474 | spin_unlock_irq(&mostek_lock); | ||
475 | |||
476 | /* Ensure the kick start bit is off. If it isn't, turn it off. */ | ||
477 | while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) { | ||
478 | prom_printf("CLOCK: Kick start still on!\n"); | ||
479 | |||
480 | spin_lock_irq(&mostek_lock); | ||
481 | |||
482 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
483 | tmp |= MSTK_CREG_WRITE; | ||
484 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
485 | |||
486 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
487 | tmp &= ~MSTK_KICK_START; | ||
488 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
489 | |||
490 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
491 | tmp &= ~MSTK_CREG_WRITE; | ||
492 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
493 | |||
494 | spin_unlock_irq(&mostek_lock); | ||
495 | } | ||
496 | |||
497 | prom_printf("CLOCK: Kick start procedure successful.\n"); | ||
498 | } | ||
499 | |||
500 | /* Return nonzero if the clock chip battery is low. */ | ||
501 | static int __init has_low_battery(void) | ||
502 | { | ||
503 | void __iomem *regs = mstk48t02_regs; | ||
504 | u8 data1, data2; | ||
505 | |||
506 | spin_lock_irq(&mostek_lock); | ||
507 | |||
508 | data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */ | ||
509 | mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */ | ||
510 | data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */ | ||
511 | mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */ | ||
512 | |||
513 | spin_unlock_irq(&mostek_lock); | ||
514 | |||
515 | return (data1 == data2); /* Was the write blocked? */ | ||
516 | } | ||
517 | |||
518 | static void __init mostek_set_system_time(void __iomem *mregs) | ||
519 | { | ||
520 | unsigned int year, mon, day, hour, min, sec; | ||
521 | u8 tmp; | ||
522 | |||
523 | spin_lock_irq(&mostek_lock); | ||
524 | |||
525 | /* Traditional Mostek chip. */ | ||
526 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
527 | tmp |= MSTK_CREG_READ; | ||
528 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
529 | |||
530 | sec = MSTK_REG_SEC(mregs); | ||
531 | min = MSTK_REG_MIN(mregs); | ||
532 | hour = MSTK_REG_HOUR(mregs); | ||
533 | day = MSTK_REG_DOM(mregs); | ||
534 | mon = MSTK_REG_MONTH(mregs); | ||
535 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); | ||
536 | |||
537 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
538 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
539 | set_normalized_timespec(&wall_to_monotonic, | ||
540 | -xtime.tv_sec, -xtime.tv_nsec); | ||
541 | |||
542 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
543 | tmp &= ~MSTK_CREG_READ; | ||
544 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
545 | |||
546 | spin_unlock_irq(&mostek_lock); | ||
547 | } | ||
548 | |||
549 | /* Probe for the real time clock chip. */ | 412 | /* Probe for the real time clock chip. */ |
550 | static void __init set_system_time(void) | 413 | static void __init set_system_time(void) |
551 | { | 414 | { |
552 | unsigned int year, mon, day, hour, min, sec; | 415 | unsigned int year, mon, day, hour, min, sec; |
553 | void __iomem *mregs = mstk48t02_regs; | ||
554 | #ifdef CONFIG_PCI | 416 | #ifdef CONFIG_PCI |
555 | unsigned long dregs = ds1287_regs; | 417 | unsigned long dregs = ds1287_regs; |
556 | void __iomem *bregs = bq4802_regs; | 418 | void __iomem *bregs = bq4802_regs; |
@@ -559,16 +421,11 @@ static void __init set_system_time(void) | |||
559 | void __iomem *bregs = 0UL; | 421 | void __iomem *bregs = 0UL; |
560 | #endif | 422 | #endif |
561 | 423 | ||
562 | if (!mregs && !dregs && !bregs) { | 424 | if (!dregs && !bregs) { |
563 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | 425 | prom_printf("Something wrong, clock regs not mapped yet.\n"); |
564 | prom_halt(); | 426 | prom_halt(); |
565 | } | 427 | } |
566 | 428 | ||
567 | if (mregs) { | ||
568 | mostek_set_system_time(mregs); | ||
569 | return; | ||
570 | } | ||
571 | |||
572 | if (bregs) { | 429 | if (bregs) { |
573 | unsigned char val = readb(bregs + 0x0e); | 430 | unsigned char val = readb(bregs + 0x0e); |
574 | unsigned int century; | 431 | unsigned int century; |
@@ -689,12 +546,9 @@ retry: | |||
689 | return -EOPNOTSUPP; | 546 | return -EOPNOTSUPP; |
690 | } | 547 | } |
691 | 548 | ||
692 | static int __init clock_model_matches(const char *model) | 549 | static int __init rtc_model_matches(const char *model) |
693 | { | 550 | { |
694 | if (strcmp(model, "mk48t02") && | 551 | if (strcmp(model, "m5819") && |
695 | strcmp(model, "mk48t08") && | ||
696 | strcmp(model, "mk48t59") && | ||
697 | strcmp(model, "m5819") && | ||
698 | strcmp(model, "m5819p") && | 552 | strcmp(model, "m5819p") && |
699 | strcmp(model, "m5823") && | 553 | strcmp(model, "m5823") && |
700 | strcmp(model, "ds1287") && | 554 | strcmp(model, "ds1287") && |
@@ -704,7 +558,7 @@ static int __init clock_model_matches(const char *model) | |||
704 | return 1; | 558 | return 1; |
705 | } | 559 | } |
706 | 560 | ||
707 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) | 561 | static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) |
708 | { | 562 | { |
709 | struct device_node *dp = op->node; | 563 | struct device_node *dp = op->node; |
710 | const char *model = of_get_property(dp, "model", NULL); | 564 | const char *model = of_get_property(dp, "model", NULL); |
@@ -715,14 +569,7 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id | |||
715 | if (!model) | 569 | if (!model) |
716 | model = compat; | 570 | model = compat; |
717 | 571 | ||
718 | if (!model || !clock_model_matches(model)) | 572 | if (!model || !rtc_model_matches(model)) |
719 | return -ENODEV; | ||
720 | |||
721 | /* On an Enterprise system there can be multiple mostek clocks. | ||
722 | * We should only match the one that is on the central FHC bus. | ||
723 | */ | ||
724 | if (!strcmp(dp->parent->name, "fhc") && | ||
725 | strcmp(dp->parent->parent->name, "central") != 0) | ||
726 | return -ENODEV; | 573 | return -ENODEV; |
727 | 574 | ||
728 | size = (op->resource[0].end - op->resource[0].start) + 1; | 575 | size = (op->resource[0].end - op->resource[0].start) + 1; |
@@ -738,32 +585,12 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id | |||
738 | ds1287_regs = (unsigned long) regs; | 585 | ds1287_regs = (unsigned long) regs; |
739 | } else if (!strcmp(model, "bq4802")) { | 586 | } else if (!strcmp(model, "bq4802")) { |
740 | bq4802_regs = regs; | 587 | bq4802_regs = regs; |
741 | } else | ||
742 | #endif | ||
743 | if (model[5] == '0' && model[6] == '2') { | ||
744 | mstk48t02_regs = regs; | ||
745 | } else if(model[5] == '0' && model[6] == '8') { | ||
746 | mstk48t08_regs = regs; | ||
747 | mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; | ||
748 | } else { | ||
749 | mstk48t59_regs = regs; | ||
750 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
751 | } | 588 | } |
752 | 589 | #endif | |
753 | printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); | 590 | printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); |
754 | 591 | ||
755 | local_irq_save(flags); | 592 | local_irq_save(flags); |
756 | 593 | ||
757 | if (mstk48t02_regs != NULL) { | ||
758 | /* Report a low battery voltage condition. */ | ||
759 | if (has_low_battery()) | ||
760 | prom_printf("NVRAM: Low battery voltage!\n"); | ||
761 | |||
762 | /* Kick start the clock if it is completely stopped. */ | ||
763 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | ||
764 | kick_start_clock(); | ||
765 | } | ||
766 | |||
767 | set_system_time(); | 594 | set_system_time(); |
768 | 595 | ||
769 | local_irq_restore(flags); | 596 | local_irq_restore(flags); |
@@ -771,21 +598,102 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id | |||
771 | return 0; | 598 | return 0; |
772 | } | 599 | } |
773 | 600 | ||
774 | static struct of_device_id clock_match[] = { | 601 | static struct of_device_id rtc_match[] = { |
775 | { | 602 | { |
776 | .name = "eeprom", | 603 | .name = "rtc", |
604 | }, | ||
605 | {}, | ||
606 | }; | ||
607 | |||
608 | static struct of_platform_driver rtc_driver = { | ||
609 | .match_table = rtc_match, | ||
610 | .probe = rtc_probe, | ||
611 | .driver = { | ||
612 | .name = "rtc", | ||
777 | }, | 613 | }, |
614 | }; | ||
615 | |||
616 | static unsigned char mostek_read_byte(struct device *dev, u32 ofs) | ||
617 | { | ||
618 | struct platform_device *pdev = to_platform_device(dev); | ||
619 | void __iomem *regs; | ||
620 | unsigned char val; | ||
621 | |||
622 | regs = (void __iomem *) pdev->resource[0].start; | ||
623 | val = readb(regs + ofs); | ||
624 | |||
625 | /* the year 0 is 1968 */ | ||
626 | if (ofs == M48T59_YEAR) { | ||
627 | val += 0x68; | ||
628 | if ((val & 0xf) > 9) | ||
629 | val += 6; | ||
630 | } | ||
631 | return val; | ||
632 | } | ||
633 | |||
634 | static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) | ||
635 | { | ||
636 | struct platform_device *pdev = to_platform_device(dev); | ||
637 | void __iomem *regs; | ||
638 | |||
639 | regs = (void __iomem *) pdev->resource[0].start; | ||
640 | if (ofs == M48T59_YEAR) { | ||
641 | if (val < 0x68) | ||
642 | val += 0x32; | ||
643 | else | ||
644 | val -= 0x68; | ||
645 | if ((val & 0xf) > 9) | ||
646 | val += 6; | ||
647 | if ((val & 0xf0) > 0x9A) | ||
648 | val += 0x60; | ||
649 | } | ||
650 | writeb(val, regs + ofs); | ||
651 | } | ||
652 | |||
653 | static struct m48t59_plat_data m48t59_data = { | ||
654 | .read_byte = mostek_read_byte, | ||
655 | .write_byte = mostek_write_byte, | ||
656 | }; | ||
657 | |||
658 | static struct platform_device m48t59_rtc = { | ||
659 | .name = "rtc-m48t59", | ||
660 | .id = 0, | ||
661 | .num_resources = 1, | ||
662 | .dev = { | ||
663 | .platform_data = &m48t59_data, | ||
664 | }, | ||
665 | }; | ||
666 | |||
667 | static int __devinit mostek_probe(struct of_device *op, const struct of_device_id *match) | ||
668 | { | ||
669 | struct device_node *dp = op->node; | ||
670 | |||
671 | /* On an Enterprise system there can be multiple mostek clocks. | ||
672 | * We should only match the one that is on the central FHC bus. | ||
673 | */ | ||
674 | if (!strcmp(dp->parent->name, "fhc") && | ||
675 | strcmp(dp->parent->parent->name, "central") != 0) | ||
676 | return -ENODEV; | ||
677 | |||
678 | printk(KERN_INFO "%s: Mostek regs at 0x%lx\n", | ||
679 | dp->full_name, op->resource[0].start); | ||
680 | |||
681 | m48t59_rtc.resource = &op->resource[0]; | ||
682 | return platform_device_register(&m48t59_rtc); | ||
683 | } | ||
684 | |||
685 | static struct of_device_id mostek_match[] = { | ||
778 | { | 686 | { |
779 | .name = "rtc", | 687 | .name = "eeprom", |
780 | }, | 688 | }, |
781 | {}, | 689 | {}, |
782 | }; | 690 | }; |
783 | 691 | ||
784 | static struct of_platform_driver clock_driver = { | 692 | static struct of_platform_driver mostek_driver = { |
785 | .match_table = clock_match, | 693 | .match_table = mostek_match, |
786 | .probe = clock_probe, | 694 | .probe = mostek_probe, |
787 | .driver = { | 695 | .driver = { |
788 | .name = "clock", | 696 | .name = "mostek", |
789 | }, | 697 | }, |
790 | }; | 698 | }; |
791 | 699 | ||
@@ -806,7 +714,10 @@ static int __init clock_init(void) | |||
806 | return 0; | 714 | return 0; |
807 | } | 715 | } |
808 | 716 | ||
809 | return of_register_driver(&clock_driver, &of_platform_bus_type); | 717 | (void) of_register_driver(&rtc_driver, &of_platform_bus_type); |
718 | (void) of_register_driver(&mostek_driver, &of_platform_bus_type); | ||
719 | |||
720 | return 0; | ||
810 | } | 721 | } |
811 | 722 | ||
812 | /* Must be after subsys_initcall() so that busses are probed. Must | 723 | /* Must be after subsys_initcall() so that busses are probed. Must |
@@ -1078,7 +989,6 @@ unsigned long long sched_clock(void) | |||
1078 | static int set_rtc_mmss(unsigned long nowtime) | 989 | static int set_rtc_mmss(unsigned long nowtime) |
1079 | { | 990 | { |
1080 | int real_seconds, real_minutes, chip_minutes; | 991 | int real_seconds, real_minutes, chip_minutes; |
1081 | void __iomem *mregs = mstk48t02_regs; | ||
1082 | #ifdef CONFIG_PCI | 992 | #ifdef CONFIG_PCI |
1083 | unsigned long dregs = ds1287_regs; | 993 | unsigned long dregs = ds1287_regs; |
1084 | void __iomem *bregs = bq4802_regs; | 994 | void __iomem *bregs = bq4802_regs; |
@@ -1087,62 +997,15 @@ static int set_rtc_mmss(unsigned long nowtime) | |||
1087 | void __iomem *bregs = 0UL; | 997 | void __iomem *bregs = 0UL; |
1088 | #endif | 998 | #endif |
1089 | unsigned long flags; | 999 | unsigned long flags; |
1090 | u8 tmp; | ||
1091 | 1000 | ||
1092 | /* | 1001 | /* |
1093 | * Not having a register set can lead to trouble. | 1002 | * Not having a register set can lead to trouble. |
1094 | * Also starfire doesn't have a tod clock. | 1003 | * Also starfire doesn't have a tod clock. |
1095 | */ | 1004 | */ |
1096 | if (!mregs && !dregs && !bregs) | 1005 | if (!dregs && !bregs) |
1097 | return -1; | 1006 | return -1; |
1098 | 1007 | ||
1099 | if (mregs) { | 1008 | if (bregs) { |
1100 | spin_lock_irqsave(&mostek_lock, flags); | ||
1101 | |||
1102 | /* Read the current RTC minutes. */ | ||
1103 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1104 | tmp |= MSTK_CREG_READ; | ||
1105 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1106 | |||
1107 | chip_minutes = MSTK_REG_MIN(mregs); | ||
1108 | |||
1109 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1110 | tmp &= ~MSTK_CREG_READ; | ||
1111 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1112 | |||
1113 | /* | ||
1114 | * since we're only adjusting minutes and seconds, | ||
1115 | * don't interfere with hour overflow. This avoids | ||
1116 | * messing with unknown time zones but requires your | ||
1117 | * RTC not to be off by more than 15 minutes | ||
1118 | */ | ||
1119 | real_seconds = nowtime % 60; | ||
1120 | real_minutes = nowtime / 60; | ||
1121 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
1122 | real_minutes += 30; /* correct for half hour time zone */ | ||
1123 | real_minutes %= 60; | ||
1124 | |||
1125 | if (abs(real_minutes - chip_minutes) < 30) { | ||
1126 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1127 | tmp |= MSTK_CREG_WRITE; | ||
1128 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1129 | |||
1130 | MSTK_SET_REG_SEC(mregs,real_seconds); | ||
1131 | MSTK_SET_REG_MIN(mregs,real_minutes); | ||
1132 | |||
1133 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1134 | tmp &= ~MSTK_CREG_WRITE; | ||
1135 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1136 | |||
1137 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
1138 | |||
1139 | return 0; | ||
1140 | } else { | ||
1141 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
1142 | |||
1143 | return -1; | ||
1144 | } | ||
1145 | } else if (bregs) { | ||
1146 | int retval = 0; | 1009 | int retval = 0; |
1147 | unsigned char val = readb(bregs + 0x0e); | 1010 | unsigned char val = readb(bregs + 0x0e); |
1148 | 1011 | ||
@@ -1485,74 +1348,6 @@ static int cmos_set_rtc_time(struct rtc_time *rtc_tm) | |||
1485 | } | 1348 | } |
1486 | #endif /* CONFIG_PCI */ | 1349 | #endif /* CONFIG_PCI */ |
1487 | 1350 | ||
1488 | static void mostek_get_rtc_time(struct rtc_time *rtc_tm) | ||
1489 | { | ||
1490 | void __iomem *regs = mstk48t02_regs; | ||
1491 | u8 tmp; | ||
1492 | |||
1493 | spin_lock_irq(&mostek_lock); | ||
1494 | |||
1495 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1496 | tmp |= MSTK_CREG_READ; | ||
1497 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1498 | |||
1499 | rtc_tm->tm_sec = MSTK_REG_SEC(regs); | ||
1500 | rtc_tm->tm_min = MSTK_REG_MIN(regs); | ||
1501 | rtc_tm->tm_hour = MSTK_REG_HOUR(regs); | ||
1502 | rtc_tm->tm_mday = MSTK_REG_DOM(regs); | ||
1503 | rtc_tm->tm_mon = MSTK_REG_MONTH(regs); | ||
1504 | rtc_tm->tm_year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); | ||
1505 | rtc_tm->tm_wday = MSTK_REG_DOW(regs); | ||
1506 | |||
1507 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1508 | tmp &= ~MSTK_CREG_READ; | ||
1509 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1510 | |||
1511 | spin_unlock_irq(&mostek_lock); | ||
1512 | |||
1513 | rtc_tm->tm_mon--; | ||
1514 | rtc_tm->tm_wday--; | ||
1515 | rtc_tm->tm_year -= 1900; | ||
1516 | } | ||
1517 | |||
1518 | static int mostek_set_rtc_time(struct rtc_time *rtc_tm) | ||
1519 | { | ||
1520 | unsigned char mon, day, hrs, min, sec, wday; | ||
1521 | void __iomem *regs = mstk48t02_regs; | ||
1522 | unsigned int yrs; | ||
1523 | u8 tmp; | ||
1524 | |||
1525 | yrs = rtc_tm->tm_year + 1900; | ||
1526 | mon = rtc_tm->tm_mon + 1; | ||
1527 | day = rtc_tm->tm_mday; | ||
1528 | wday = rtc_tm->tm_wday + 1; | ||
1529 | hrs = rtc_tm->tm_hour; | ||
1530 | min = rtc_tm->tm_min; | ||
1531 | sec = rtc_tm->tm_sec; | ||
1532 | |||
1533 | spin_lock_irq(&mostek_lock); | ||
1534 | |||
1535 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1536 | tmp |= MSTK_CREG_WRITE; | ||
1537 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1538 | |||
1539 | MSTK_SET_REG_SEC(regs, sec); | ||
1540 | MSTK_SET_REG_MIN(regs, min); | ||
1541 | MSTK_SET_REG_HOUR(regs, hrs); | ||
1542 | MSTK_SET_REG_DOW(regs, wday); | ||
1543 | MSTK_SET_REG_DOM(regs, day); | ||
1544 | MSTK_SET_REG_MONTH(regs, mon); | ||
1545 | MSTK_SET_REG_YEAR(regs, yrs - MSTK_YEAR_ZERO); | ||
1546 | |||
1547 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1548 | tmp &= ~MSTK_CREG_WRITE; | ||
1549 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1550 | |||
1551 | spin_unlock_irq(&mostek_lock); | ||
1552 | |||
1553 | return 0; | ||
1554 | } | ||
1555 | |||
1556 | struct mini_rtc_ops { | 1351 | struct mini_rtc_ops { |
1557 | void (*get_rtc_time)(struct rtc_time *); | 1352 | void (*get_rtc_time)(struct rtc_time *); |
1558 | int (*set_rtc_time)(struct rtc_time *); | 1353 | int (*set_rtc_time)(struct rtc_time *); |
@@ -1580,11 +1375,6 @@ static struct mini_rtc_ops cmos_rtc_ops = { | |||
1580 | }; | 1375 | }; |
1581 | #endif /* CONFIG_PCI */ | 1376 | #endif /* CONFIG_PCI */ |
1582 | 1377 | ||
1583 | static struct mini_rtc_ops mostek_rtc_ops = { | ||
1584 | .get_rtc_time = mostek_get_rtc_time, | ||
1585 | .set_rtc_time = mostek_set_rtc_time, | ||
1586 | }; | ||
1587 | |||
1588 | static struct mini_rtc_ops *mini_rtc_ops; | 1378 | static struct mini_rtc_ops *mini_rtc_ops; |
1589 | 1379 | ||
1590 | static inline void mini_get_rtc_time(struct rtc_time *time) | 1380 | static inline void mini_get_rtc_time(struct rtc_time *time) |
@@ -1717,8 +1507,6 @@ static int __init rtc_mini_init(void) | |||
1717 | else if (ds1287_regs) | 1507 | else if (ds1287_regs) |
1718 | mini_rtc_ops = &cmos_rtc_ops; | 1508 | mini_rtc_ops = &cmos_rtc_ops; |
1719 | #endif /* CONFIG_PCI */ | 1509 | #endif /* CONFIG_PCI */ |
1720 | else if (mstk48t02_regs) | ||
1721 | mini_rtc_ops = &mostek_rtc_ops; | ||
1722 | else | 1510 | else |
1723 | return -ENODEV; | 1511 | return -ENODEV; |
1724 | 1512 | ||