diff options
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r-- | arch/sparc64/kernel/time.c | 246 |
1 files changed, 54 insertions, 192 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 348b82035561..540e4b6c2dee 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -770,237 +770,99 @@ static int __init clock_model_matches(char *model) | |||
770 | return 1; | 770 | return 1; |
771 | } | 771 | } |
772 | 772 | ||
773 | static void __init __clock_assign_common(void __iomem *addr, char *model) | 773 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) |
774 | { | 774 | { |
775 | if (model[5] == '0' && model[6] == '2') { | 775 | struct device_node *dp = op->node; |
776 | mstk48t02_regs = addr; | 776 | char *model = of_get_property(dp, "model", NULL); |
777 | } else if(model[5] == '0' && model[6] == '8') { | 777 | unsigned long size, flags; |
778 | mstk48t08_regs = addr; | 778 | void __iomem *regs; |
779 | mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; | ||
780 | } else { | ||
781 | mstk48t59_regs = addr; | ||
782 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg, | ||
787 | char *model) | ||
788 | { | ||
789 | unsigned long addr; | ||
790 | 779 | ||
791 | addr = ((unsigned long) clk_reg[0].phys_addr | | 780 | if (!model || !clock_model_matches(model)) |
792 | (((unsigned long) clk_reg[0].which_io) << 32UL)); | 781 | return -ENODEV; |
793 | |||
794 | __clock_assign_common((void __iomem *) addr, model); | ||
795 | } | ||
796 | |||
797 | static int __init clock_probe_central(void) | ||
798 | { | ||
799 | struct linux_prom_registers clk_reg[2], *pr; | ||
800 | struct device_node *dp; | ||
801 | char *model; | ||
802 | |||
803 | if (!central_bus) | ||
804 | return 0; | ||
805 | |||
806 | /* Get Central FHC's prom node. */ | ||
807 | dp = central_bus->child->prom_node; | ||
808 | |||
809 | /* Then get the first child device below it. */ | ||
810 | dp = dp->child; | ||
811 | |||
812 | while (dp) { | ||
813 | model = of_get_property(dp, "model", NULL); | ||
814 | if (!model || !clock_model_matches(model)) | ||
815 | goto next_sibling; | ||
816 | |||
817 | pr = of_get_property(dp, "reg", NULL); | ||
818 | memcpy(clk_reg, pr, sizeof(clk_reg)); | ||
819 | |||
820 | apply_fhc_ranges(central_bus->child, clk_reg, 1); | ||
821 | apply_central_ranges(central_bus, clk_reg, 1); | ||
822 | |||
823 | clock_assign_clk_reg(clk_reg, model); | ||
824 | return 1; | ||
825 | |||
826 | next_sibling: | ||
827 | dp = dp->sibling; | ||
828 | } | ||
829 | 782 | ||
830 | return 0; | 783 | size = (op->resource[0].end - op->resource[0].start) + 1; |
831 | } | 784 | regs = of_ioremap(&op->resource[0], 0, size, "clock"); |
785 | if (!regs) | ||
786 | return -ENOMEM; | ||
832 | 787 | ||
833 | #ifdef CONFIG_PCI | ||
834 | static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model) | ||
835 | { | ||
836 | if (!strcmp(model, "ds1287") || | 788 | if (!strcmp(model, "ds1287") || |
837 | !strcmp(model, "m5819") || | 789 | !strcmp(model, "m5819") || |
838 | !strcmp(model, "m5819p") || | 790 | !strcmp(model, "m5819p") || |
839 | !strcmp(model, "m5823")) { | 791 | !strcmp(model, "m5823")) { |
840 | ds1287_regs = res->start; | 792 | ds1287_regs = (unsigned long) regs; |
793 | } else if (model[5] == '0' && model[6] == '2') { | ||
794 | mstk48t02_regs = regs; | ||
795 | } else if(model[5] == '0' && model[6] == '8') { | ||
796 | mstk48t08_regs = regs; | ||
797 | mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; | ||
841 | } else { | 798 | } else { |
842 | mstk48t59_regs = (void __iomem *) res->start; | 799 | mstk48t59_regs = regs; |
843 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | 800 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; |
844 | } | 801 | } |
845 | } | ||
846 | |||
847 | static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev) | ||
848 | { | ||
849 | struct device_node *dp = edev->prom_node; | ||
850 | char *model; | ||
851 | 802 | ||
852 | model = of_get_property(dp, "model", NULL); | 803 | printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); |
853 | if (!clock_model_matches(model)) | ||
854 | return 0; | ||
855 | |||
856 | clock_isa_ebus_assign_regs(&edev->resource[0], model); | ||
857 | 804 | ||
858 | return 1; | 805 | local_irq_save(flags); |
859 | } | ||
860 | |||
861 | static int __init clock_probe_ebus(void) | ||
862 | { | ||
863 | struct linux_ebus *ebus; | ||
864 | 806 | ||
865 | for_each_ebus(ebus) { | 807 | if (mstk48t02_regs != NULL) { |
866 | struct linux_ebus_device *edev; | 808 | /* Report a low battery voltage condition. */ |
809 | if (has_low_battery()) | ||
810 | prom_printf("NVRAM: Low battery voltage!\n"); | ||
867 | 811 | ||
868 | for_each_ebusdev(edev, ebus) { | 812 | /* Kick start the clock if it is completely stopped. */ |
869 | if (clock_probe_one_ebus_dev(edev)) | 813 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) |
870 | return 1; | 814 | kick_start_clock(); |
871 | } | ||
872 | } | 815 | } |
873 | 816 | ||
874 | return 0; | 817 | set_system_time(); |
875 | } | 818 | |
876 | 819 | local_irq_restore(flags); | |
877 | static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev) | ||
878 | { | ||
879 | struct device_node *dp = idev->prom_node; | ||
880 | char *model; | ||
881 | |||
882 | model = of_get_property(dp, "model", NULL); | ||
883 | if (!clock_model_matches(model)) | ||
884 | return 0; | ||
885 | |||
886 | clock_isa_ebus_assign_regs(&idev->resource, model); | ||
887 | |||
888 | return 1; | ||
889 | } | ||
890 | |||
891 | static int __init clock_probe_isa(void) | ||
892 | { | ||
893 | struct sparc_isa_bridge *isa_br; | ||
894 | |||
895 | for_each_isa(isa_br) { | ||
896 | struct sparc_isa_device *isa_dev; | ||
897 | |||
898 | for_each_isadev(isa_dev, isa_br) { | ||
899 | if (clock_probe_one_isa_dev(isa_dev)) | ||
900 | return 1; | ||
901 | } | ||
902 | } | ||
903 | 820 | ||
904 | return 0; | 821 | return 0; |
905 | } | 822 | } |
906 | #endif /* CONFIG_PCI */ | ||
907 | |||
908 | #ifdef CONFIG_SBUS | ||
909 | static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev) | ||
910 | { | ||
911 | struct resource *res; | ||
912 | char model[64]; | ||
913 | void __iomem *addr; | ||
914 | |||
915 | prom_getstring(sdev->prom_node, "model", model, sizeof(model)); | ||
916 | if (!clock_model_matches(model)) | ||
917 | return 0; | ||
918 | |||
919 | res = &sdev->resource[0]; | ||
920 | addr = sbus_ioremap(res, 0, 0x800UL, "eeprom"); | ||
921 | |||
922 | __clock_assign_common(addr, model); | ||
923 | 823 | ||
924 | return 1; | 824 | static struct of_device_id clock_match[] = { |
925 | } | 825 | { |
926 | 826 | .name = "eeprom", | |
927 | static int __init clock_probe_sbus(void) | 827 | }, |
928 | { | 828 | { |
929 | struct sbus_bus *sbus; | 829 | .name = "rtc", |
930 | 830 | }, | |
931 | for_each_sbus(sbus) { | 831 | {}, |
932 | struct sbus_dev *sdev; | 832 | }; |
933 | |||
934 | for_each_sbusdev(sdev, sbus) { | ||
935 | if (clock_probe_one_sbus_dev(sbus, sdev)) | ||
936 | return 1; | ||
937 | } | ||
938 | } | ||
939 | 833 | ||
940 | return 0; | 834 | static struct of_platform_driver clock_driver = { |
941 | } | 835 | .name = "clock", |
942 | #endif | 836 | .match_table = clock_match, |
837 | .probe = clock_probe, | ||
838 | }; | ||
943 | 839 | ||
944 | void __init clock_probe(void) | 840 | static int __init clock_init(void) |
945 | { | 841 | { |
946 | static int invoked; | ||
947 | unsigned long flags; | ||
948 | |||
949 | if (invoked) | ||
950 | return; | ||
951 | invoked = 1; | ||
952 | |||
953 | if (this_is_starfire) { | 842 | if (this_is_starfire) { |
954 | xtime.tv_sec = starfire_get_time(); | 843 | xtime.tv_sec = starfire_get_time(); |
955 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 844 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); |
956 | set_normalized_timespec(&wall_to_monotonic, | 845 | set_normalized_timespec(&wall_to_monotonic, |
957 | -xtime.tv_sec, -xtime.tv_nsec); | 846 | -xtime.tv_sec, -xtime.tv_nsec); |
958 | return; | 847 | return 0; |
959 | } | 848 | } |
960 | if (tlb_type == hypervisor) { | 849 | if (tlb_type == hypervisor) { |
961 | xtime.tv_sec = hypervisor_get_time(); | 850 | xtime.tv_sec = hypervisor_get_time(); |
962 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 851 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); |
963 | set_normalized_timespec(&wall_to_monotonic, | 852 | set_normalized_timespec(&wall_to_monotonic, |
964 | -xtime.tv_sec, -xtime.tv_nsec); | 853 | -xtime.tv_sec, -xtime.tv_nsec); |
965 | return; | 854 | return 0; |
966 | } | ||
967 | |||
968 | /* Check FHC Central then EBUSs then ISA bridges then SBUSs. | ||
969 | * That way we handle the presence of multiple properly. | ||
970 | * | ||
971 | * As a special case, machines with Central must provide the | ||
972 | * timer chip there. | ||
973 | */ | ||
974 | if (!clock_probe_central() && | ||
975 | #ifdef CONFIG_PCI | ||
976 | !clock_probe_ebus() && | ||
977 | !clock_probe_isa() && | ||
978 | #endif | ||
979 | #ifdef CONFIG_SBUS | ||
980 | !clock_probe_sbus() | ||
981 | #endif | ||
982 | ) { | ||
983 | printk(KERN_WARNING "No clock chip found.\n"); | ||
984 | return; | ||
985 | } | ||
986 | |||
987 | local_irq_save(flags); | ||
988 | |||
989 | if (mstk48t02_regs != NULL) { | ||
990 | /* Report a low battery voltage condition. */ | ||
991 | if (has_low_battery()) | ||
992 | prom_printf("NVRAM: Low battery voltage!\n"); | ||
993 | |||
994 | /* Kick start the clock if it is completely stopped. */ | ||
995 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | ||
996 | kick_start_clock(); | ||
997 | } | 855 | } |
998 | 856 | ||
999 | set_system_time(); | 857 | return of_register_driver(&clock_driver, &of_bus_type); |
1000 | |||
1001 | local_irq_restore(flags); | ||
1002 | } | 858 | } |
1003 | 859 | ||
860 | /* Must be after subsys_initcall() so that busses are probed. Must | ||
861 | * be before device_initcall() because things like the RTC driver | ||
862 | * need to see the clock registers. | ||
863 | */ | ||
864 | fs_initcall(clock_init); | ||
865 | |||
1004 | /* This is gets the master TICK_INT timer going. */ | 866 | /* This is gets the master TICK_INT timer going. */ |
1005 | static unsigned long sparc64_init_timers(void) | 867 | static unsigned long sparc64_init_timers(void) |
1006 | { | 868 | { |