diff options
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r-- | arch/sparc64/kernel/time.c | 368 |
1 files changed, 194 insertions, 174 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index aa5438a4fd50..d072b8632ccd 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -756,24 +756,200 @@ retry: | |||
756 | return -EOPNOTSUPP; | 756 | return -EOPNOTSUPP; |
757 | } | 757 | } |
758 | 758 | ||
759 | void __init clock_probe(void) | 759 | static int __init clock_model_matches(char *model) |
760 | { | ||
761 | if (strcmp(model, "mk48t02") && | ||
762 | strcmp(model, "mk48t08") && | ||
763 | strcmp(model, "mk48t59") && | ||
764 | strcmp(model, "m5819") && | ||
765 | strcmp(model, "m5819p") && | ||
766 | strcmp(model, "m5823") && | ||
767 | strcmp(model, "ds1287")) | ||
768 | return 0; | ||
769 | |||
770 | return 1; | ||
771 | } | ||
772 | |||
773 | static void __init __clock_assign_common(void __iomem *addr, char *model) | ||
774 | { | ||
775 | if (model[5] == '0' && model[6] == '2') { | ||
776 | mstk48t02_regs = addr; | ||
777 | } else if(model[5] == '0' && model[6] == '8') { | ||
778 | mstk48t08_regs = addr; | ||
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 | |||
791 | addr = ((unsigned long) clk_reg[0].phys_addr | | ||
792 | (((unsigned long) clk_reg[0].which_io) << 32UL)); | ||
793 | |||
794 | __clock_assign_common((void __iomem *) addr, model); | ||
795 | } | ||
796 | |||
797 | static int __init clock_probe_central(void) | ||
760 | { | 798 | { |
761 | struct linux_prom_registers clk_reg[2]; | 799 | struct linux_prom_registers clk_reg[2]; |
762 | char model[128]; | 800 | char model[64]; |
763 | int node, busnd = -1, err; | 801 | int node; |
764 | unsigned long flags; | 802 | |
765 | struct linux_central *cbus; | 803 | if (!central_bus) |
804 | return 0; | ||
805 | |||
806 | /* Get Central FHC's prom node. */ | ||
807 | node = central_bus->child->prom_node; | ||
808 | |||
809 | /* Then get the first child device below it. */ | ||
810 | node = prom_getchild(node); | ||
811 | |||
812 | while (node) { | ||
813 | prom_getstring(node, "model", model, sizeof(model)); | ||
814 | if (!clock_model_matches(model)) | ||
815 | goto next_sibling; | ||
816 | |||
817 | prom_getproperty(node, "reg", (char *)clk_reg, | ||
818 | 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 | node = prom_getsibling(node); | ||
828 | } | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | |||
766 | #ifdef CONFIG_PCI | 833 | #ifdef CONFIG_PCI |
767 | struct linux_ebus *ebus = NULL; | 834 | static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model) |
768 | struct sparc_isa_bridge *isa_br = NULL; | 835 | { |
836 | if (!strcmp(model, "ds1287") || | ||
837 | !strcmp(model, "m5819") || | ||
838 | !strcmp(model, "m5819p") || | ||
839 | !strcmp(model, "m5823")) { | ||
840 | ds1287_regs = res->start; | ||
841 | } else { | ||
842 | mstk48t59_regs = (void __iomem *) res->start; | ||
843 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
844 | } | ||
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 | |||
852 | model = of_get_property(dp, "model", NULL); | ||
853 | if (!clock_model_matches(model)) | ||
854 | return 0; | ||
855 | |||
856 | clock_isa_ebus_assign_regs(&edev->resource[0], model); | ||
857 | |||
858 | return 1; | ||
859 | } | ||
860 | |||
861 | static int __init clock_probe_ebus(void) | ||
862 | { | ||
863 | struct linux_ebus *ebus; | ||
864 | |||
865 | for_each_ebus(ebus) { | ||
866 | struct linux_ebus_device *edev; | ||
867 | |||
868 | for_each_ebusdev(edev, ebus) { | ||
869 | if (clock_probe_one_ebus_dev(edev)) | ||
870 | return 1; | ||
871 | } | ||
872 | } | ||
873 | |||
874 | return 0; | ||
875 | } | ||
876 | |||
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 | |||
904 | return 0; | ||
905 | } | ||
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 | |||
924 | return 1; | ||
925 | } | ||
926 | |||
927 | static int __init clock_probe_sbus(void) | ||
928 | { | ||
929 | struct sbus_bus *sbus; | ||
930 | |||
931 | for_each_sbus(sbus) { | ||
932 | struct sbus_dev *sdev; | ||
933 | |||
934 | for_each_sbusdev(sdev, sbus) { | ||
935 | if (clock_probe_one_sbus_dev(sbus, sdev)) | ||
936 | return 1; | ||
937 | } | ||
938 | } | ||
939 | |||
940 | return 0; | ||
941 | } | ||
769 | #endif | 942 | #endif |
943 | |||
944 | void __init clock_probe(void) | ||
945 | { | ||
770 | static int invoked; | 946 | static int invoked; |
947 | unsigned long flags; | ||
771 | 948 | ||
772 | if (invoked) | 949 | if (invoked) |
773 | return; | 950 | return; |
774 | invoked = 1; | 951 | invoked = 1; |
775 | 952 | ||
776 | |||
777 | if (this_is_starfire) { | 953 | if (this_is_starfire) { |
778 | xtime.tv_sec = starfire_get_time(); | 954 | xtime.tv_sec = starfire_get_time(); |
779 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 955 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); |
@@ -789,183 +965,27 @@ void __init clock_probe(void) | |||
789 | return; | 965 | return; |
790 | } | 966 | } |
791 | 967 | ||
792 | local_irq_save(flags); | ||
793 | |||
794 | cbus = central_bus; | ||
795 | if (cbus != NULL) | ||
796 | busnd = central_bus->child->prom_node; | ||
797 | |||
798 | /* Check FHC Central then EBUSs then ISA bridges then SBUSs. | 968 | /* Check FHC Central then EBUSs then ISA bridges then SBUSs. |
799 | * That way we handle the presence of multiple properly. | 969 | * That way we handle the presence of multiple properly. |
800 | * | 970 | * |
801 | * As a special case, machines with Central must provide the | 971 | * As a special case, machines with Central must provide the |
802 | * timer chip there. | 972 | * timer chip there. |
803 | */ | 973 | */ |
974 | if (!clock_probe_central() && | ||
804 | #ifdef CONFIG_PCI | 975 | #ifdef CONFIG_PCI |
805 | if (ebus_chain != NULL) { | 976 | !clock_probe_ebus() && |
806 | ebus = ebus_chain; | 977 | !clock_probe_isa() && |
807 | if (busnd == -1) | ||
808 | busnd = ebus->prom_node; | ||
809 | } | ||
810 | if (isa_chain != NULL) { | ||
811 | isa_br = isa_chain; | ||
812 | if (busnd == -1) | ||
813 | busnd = isa_br->prom_node; | ||
814 | } | ||
815 | #endif | ||
816 | if (sbus_root != NULL && busnd == -1) | ||
817 | busnd = sbus_root->prom_node; | ||
818 | |||
819 | if (busnd == -1) { | ||
820 | prom_printf("clock_probe: problem, cannot find bus to search.\n"); | ||
821 | prom_halt(); | ||
822 | } | ||
823 | |||
824 | node = prom_getchild(busnd); | ||
825 | |||
826 | while (1) { | ||
827 | if (!node) | ||
828 | model[0] = 0; | ||
829 | else | ||
830 | prom_getstring(node, "model", model, sizeof(model)); | ||
831 | if (strcmp(model, "mk48t02") && | ||
832 | strcmp(model, "mk48t08") && | ||
833 | strcmp(model, "mk48t59") && | ||
834 | strcmp(model, "m5819") && | ||
835 | strcmp(model, "m5819p") && | ||
836 | strcmp(model, "m5823") && | ||
837 | strcmp(model, "ds1287")) { | ||
838 | if (cbus != NULL) { | ||
839 | prom_printf("clock_probe: Central bus lacks timer chip.\n"); | ||
840 | prom_halt(); | ||
841 | } | ||
842 | |||
843 | if (node != 0) | ||
844 | node = prom_getsibling(node); | ||
845 | #ifdef CONFIG_PCI | ||
846 | while ((node == 0) && ebus != NULL) { | ||
847 | ebus = ebus->next; | ||
848 | if (ebus != NULL) { | ||
849 | busnd = ebus->prom_node; | ||
850 | node = prom_getchild(busnd); | ||
851 | } | ||
852 | } | ||
853 | while ((node == 0) && isa_br != NULL) { | ||
854 | isa_br = isa_br->next; | ||
855 | if (isa_br != NULL) { | ||
856 | busnd = isa_br->prom_node; | ||
857 | node = prom_getchild(busnd); | ||
858 | } | ||
859 | } | ||
860 | #endif | 978 | #endif |
861 | if (node == 0) { | 979 | #ifdef CONFIG_SBUS |
862 | prom_printf("clock_probe: Cannot find timer chip\n"); | 980 | !clock_probe_sbus() |
863 | prom_halt(); | ||
864 | } | ||
865 | continue; | ||
866 | } | ||
867 | |||
868 | err = prom_getproperty(node, "reg", (char *)clk_reg, | ||
869 | sizeof(clk_reg)); | ||
870 | if(err == -1) { | ||
871 | prom_printf("clock_probe: Cannot get Mostek reg property\n"); | ||
872 | prom_halt(); | ||
873 | } | ||
874 | |||
875 | if (cbus != NULL) { | ||
876 | apply_fhc_ranges(central_bus->child, clk_reg, 1); | ||
877 | apply_central_ranges(central_bus, clk_reg, 1); | ||
878 | } | ||
879 | #ifdef CONFIG_PCI | ||
880 | else if (ebus != NULL) { | ||
881 | struct linux_ebus_device *edev; | ||
882 | |||
883 | for_each_ebusdev(edev, ebus) | ||
884 | if (edev->prom_node == node) | ||
885 | break; | ||
886 | if (edev == NULL) { | ||
887 | if (isa_chain != NULL) | ||
888 | goto try_isa_clock; | ||
889 | prom_printf("%s: Mostek not probed by EBUS\n", | ||
890 | __FUNCTION__); | ||
891 | prom_halt(); | ||
892 | } | ||
893 | |||
894 | if (!strcmp(model, "ds1287") || | ||
895 | !strcmp(model, "m5819") || | ||
896 | !strcmp(model, "m5819p") || | ||
897 | !strcmp(model, "m5823")) { | ||
898 | ds1287_regs = edev->resource[0].start; | ||
899 | } else { | ||
900 | mstk48t59_regs = (void __iomem *) | ||
901 | edev->resource[0].start; | ||
902 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
903 | } | ||
904 | break; | ||
905 | } | ||
906 | else if (isa_br != NULL) { | ||
907 | struct sparc_isa_device *isadev; | ||
908 | |||
909 | try_isa_clock: | ||
910 | for_each_isadev(isadev, isa_br) | ||
911 | if (isadev->prom_node == node) | ||
912 | break; | ||
913 | if (isadev == NULL) { | ||
914 | prom_printf("%s: Mostek not probed by ISA\n"); | ||
915 | prom_halt(); | ||
916 | } | ||
917 | if (!strcmp(model, "ds1287") || | ||
918 | !strcmp(model, "m5819") || | ||
919 | !strcmp(model, "m5819p") || | ||
920 | !strcmp(model, "m5823")) { | ||
921 | ds1287_regs = isadev->resource.start; | ||
922 | } else { | ||
923 | mstk48t59_regs = (void __iomem *) | ||
924 | isadev->resource.start; | ||
925 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
926 | } | ||
927 | break; | ||
928 | } | ||
929 | #endif | 981 | #endif |
930 | else { | 982 | ) { |
931 | if (sbus_root->num_sbus_ranges) { | 983 | printk(KERN_WARNING "No clock chip found.\n"); |
932 | int nranges = sbus_root->num_sbus_ranges; | 984 | return; |
933 | int rngc; | ||
934 | |||
935 | for (rngc = 0; rngc < nranges; rngc++) | ||
936 | if (clk_reg[0].which_io == | ||
937 | sbus_root->sbus_ranges[rngc].ot_child_space) | ||
938 | break; | ||
939 | if (rngc == nranges) { | ||
940 | prom_printf("clock_probe: Cannot find ranges for " | ||
941 | "clock regs.\n"); | ||
942 | prom_halt(); | ||
943 | } | ||
944 | clk_reg[0].which_io = | ||
945 | sbus_root->sbus_ranges[rngc].ot_parent_space; | ||
946 | clk_reg[0].phys_addr += | ||
947 | sbus_root->sbus_ranges[rngc].ot_parent_base; | ||
948 | } | ||
949 | } | ||
950 | |||
951 | if(model[5] == '0' && model[6] == '2') { | ||
952 | mstk48t02_regs = (void __iomem *) | ||
953 | (((u64)clk_reg[0].phys_addr) | | ||
954 | (((u64)clk_reg[0].which_io)<<32UL)); | ||
955 | } else if(model[5] == '0' && model[6] == '8') { | ||
956 | mstk48t08_regs = (void __iomem *) | ||
957 | (((u64)clk_reg[0].phys_addr) | | ||
958 | (((u64)clk_reg[0].which_io)<<32UL)); | ||
959 | mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; | ||
960 | } else { | ||
961 | mstk48t59_regs = (void __iomem *) | ||
962 | (((u64)clk_reg[0].phys_addr) | | ||
963 | (((u64)clk_reg[0].which_io)<<32UL)); | ||
964 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
965 | } | ||
966 | break; | ||
967 | } | 985 | } |
968 | 986 | ||
987 | local_irq_save(flags); | ||
988 | |||
969 | if (mstk48t02_regs != NULL) { | 989 | if (mstk48t02_regs != NULL) { |
970 | /* Report a low battery voltage condition. */ | 990 | /* Report a low battery voltage condition. */ |
971 | if (has_low_battery()) | 991 | if (has_low_battery()) |