diff options
author | David S. Miller <davem@davemloft.net> | 2006-06-29 17:36:52 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-29 19:37:23 -0400 |
commit | ee5caf0ee19f65a5e29bf20a0dffd8be8b4827fd (patch) | |
tree | 68eaa50b1bcc4eda6200d4121248354766e77a1d /arch | |
parent | 36a59bd89c50c1090c7438db89f751720974a6fc (diff) |
[SPARC]: Convert clock drivers to of_driver framework.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc/kernel/time.c | 109 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/sbus.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/time.c | 246 |
4 files changed, 94 insertions, 265 deletions
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 7dadcdb4ca42..9631e8f4ae60 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <asm/sun4paddr.h> | 42 | #include <asm/sun4paddr.h> |
43 | #include <asm/page.h> | 43 | #include <asm/page.h> |
44 | #include <asm/pcic.h> | 44 | #include <asm/pcic.h> |
45 | #include <asm/of_device.h> | ||
45 | 46 | ||
46 | extern unsigned long wall_jiffies; | 47 | extern unsigned long wall_jiffies; |
47 | 48 | ||
@@ -273,83 +274,31 @@ static __inline__ void sun4_clock_probe(void) | |||
273 | #endif | 274 | #endif |
274 | } | 275 | } |
275 | 276 | ||
276 | /* Probe for the mostek real time clock chip. */ | 277 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) |
277 | static __inline__ void clock_probe(void) | ||
278 | { | 278 | { |
279 | struct linux_prom_registers clk_reg[2]; | 279 | struct device_node *dp = op->node; |
280 | char model[128]; | 280 | char *model = of_get_property(dp, "model", NULL); |
281 | register int node, cpuunit, bootbus; | ||
282 | struct resource r; | ||
283 | |||
284 | cpuunit = bootbus = 0; | ||
285 | memset(&r, 0, sizeof(r)); | ||
286 | |||
287 | /* Determine the correct starting PROM node for the probe. */ | ||
288 | node = prom_getchild(prom_root_node); | ||
289 | switch (sparc_cpu_model) { | ||
290 | case sun4c: | ||
291 | break; | ||
292 | case sun4m: | ||
293 | node = prom_getchild(prom_searchsiblings(node, "obio")); | ||
294 | break; | ||
295 | case sun4d: | ||
296 | node = prom_getchild(bootbus = prom_searchsiblings(prom_getchild(cpuunit = prom_searchsiblings(node, "cpu-unit")), "bootbus")); | ||
297 | break; | ||
298 | default: | ||
299 | prom_printf("CLOCK: Unsupported architecture!\n"); | ||
300 | prom_halt(); | ||
301 | } | ||
302 | 281 | ||
303 | /* Find the PROM node describing the real time clock. */ | 282 | if (!model) |
304 | sp_clock_typ = MSTK_INVALID; | 283 | return -ENODEV; |
305 | node = prom_searchsiblings(node,"eeprom"); | ||
306 | if (!node) { | ||
307 | prom_printf("CLOCK: No clock found!\n"); | ||
308 | prom_halt(); | ||
309 | } | ||
310 | 284 | ||
311 | /* Get the model name and setup everything up. */ | 285 | if (!strcmp(model, "mk48t02")) { |
312 | model[0] = '\0'; | ||
313 | prom_getstring(node, "model", model, sizeof(model)); | ||
314 | if (strcmp(model, "mk48t02") == 0) { | ||
315 | sp_clock_typ = MSTK48T02; | 286 | sp_clock_typ = MSTK48T02; |
316 | if (prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) { | 287 | |
317 | prom_printf("clock_probe: FAILED!\n"); | ||
318 | prom_halt(); | ||
319 | } | ||
320 | if (sparc_cpu_model == sun4d) | ||
321 | prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); | ||
322 | else | ||
323 | prom_apply_obio_ranges(clk_reg, 1); | ||
324 | /* Map the clock register io area read-only */ | 288 | /* Map the clock register io area read-only */ |
325 | r.flags = clk_reg[0].which_io; | 289 | mstk48t02_regs = of_ioremap(&op->resource[0], 0, |
326 | r.start = clk_reg[0].phys_addr; | 290 | sizeof(struct mostek48t02), |
327 | mstk48t02_regs = sbus_ioremap(&r, 0, | 291 | "mk48t02"); |
328 | sizeof(struct mostek48t02), "mk48t02"); | ||
329 | mstk48t08_regs = NULL; /* To catch weirdness */ | 292 | mstk48t08_regs = NULL; /* To catch weirdness */ |
330 | } else if (strcmp(model, "mk48t08") == 0) { | 293 | } else if (!strcmp(model, "mk48t08")) { |
331 | sp_clock_typ = MSTK48T08; | 294 | sp_clock_typ = MSTK48T08; |
332 | if(prom_getproperty(node, "reg", (char *) clk_reg, | 295 | mstk48t08_regs = of_ioremap(&op->resource[0], 0, |
333 | sizeof(clk_reg)) == -1) { | 296 | sizeof(struct mostek48t08), |
334 | prom_printf("clock_probe: FAILED!\n"); | 297 | "mk48t08"); |
335 | prom_halt(); | ||
336 | } | ||
337 | if (sparc_cpu_model == sun4d) | ||
338 | prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); | ||
339 | else | ||
340 | prom_apply_obio_ranges(clk_reg, 1); | ||
341 | /* Map the clock register io area read-only */ | ||
342 | /* XXX r/o attribute is somewhere in r.flags */ | ||
343 | r.flags = clk_reg[0].which_io; | ||
344 | r.start = clk_reg[0].phys_addr; | ||
345 | mstk48t08_regs = sbus_ioremap(&r, 0, | ||
346 | sizeof(struct mostek48t08), "mk48t08"); | ||
347 | 298 | ||
348 | mstk48t02_regs = &mstk48t08_regs->regs; | 299 | mstk48t02_regs = &mstk48t08_regs->regs; |
349 | } else { | 300 | } else |
350 | prom_printf("CLOCK: Unknown model name '%s'\n",model); | 301 | return -ENODEV; |
351 | prom_halt(); | ||
352 | } | ||
353 | 302 | ||
354 | /* Report a low battery voltage condition. */ | 303 | /* Report a low battery voltage condition. */ |
355 | if (has_low_battery()) | 304 | if (has_low_battery()) |
@@ -358,6 +307,28 @@ static __inline__ void clock_probe(void) | |||
358 | /* Kick start the clock if it is completely stopped. */ | 307 | /* Kick start the clock if it is completely stopped. */ |
359 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | 308 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) |
360 | kick_start_clock(); | 309 | kick_start_clock(); |
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static struct of_device_id clock_match[] = { | ||
315 | { | ||
316 | .name = "eeprom", | ||
317 | }, | ||
318 | {}, | ||
319 | }; | ||
320 | |||
321 | static struct of_platform_driver clock_driver = { | ||
322 | .name = "clock", | ||
323 | .match_table = clock_match, | ||
324 | .probe = clock_probe, | ||
325 | }; | ||
326 | |||
327 | |||
328 | /* Probe for the mostek real time clock chip. */ | ||
329 | static void clock_init(void) | ||
330 | { | ||
331 | of_register_driver(&clock_driver, &of_bus_type); | ||
361 | } | 332 | } |
362 | 333 | ||
363 | void __init sbus_time_init(void) | 334 | void __init sbus_time_init(void) |
@@ -376,7 +347,7 @@ void __init sbus_time_init(void) | |||
376 | if (ARCH_SUN4) | 347 | if (ARCH_SUN4) |
377 | sun4_clock_probe(); | 348 | sun4_clock_probe(); |
378 | else | 349 | else |
379 | clock_probe(); | 350 | clock_init(); |
380 | 351 | ||
381 | sparc_init_timers(timer_interrupt); | 352 | sparc_init_timers(timer_interrupt); |
382 | 353 | ||
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 20ca9ec8fd3b..7b9625828603 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -307,7 +307,6 @@ static void __init pci_scan_each_controller_bus(void) | |||
307 | p->scan_bus(p); | 307 | p->scan_bus(p); |
308 | } | 308 | } |
309 | 309 | ||
310 | extern void clock_probe(void); | ||
311 | extern void power_init(void); | 310 | extern void power_init(void); |
312 | 311 | ||
313 | static int __init pcibios_init(void) | 312 | static int __init pcibios_init(void) |
@@ -320,7 +319,6 @@ static int __init pcibios_init(void) | |||
320 | 319 | ||
321 | isa_init(); | 320 | isa_init(); |
322 | ebus_init(); | 321 | ebus_init(); |
323 | clock_probe(); | ||
324 | power_init(); | 322 | power_init(); |
325 | 323 | ||
326 | return 0; | 324 | return 0; |
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 945222e66980..ef68aa4fec65 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
@@ -1267,8 +1267,6 @@ int __init sbus_arch_preinit(void) | |||
1267 | void __init sbus_arch_postinit(void) | 1267 | void __init sbus_arch_postinit(void) |
1268 | { | 1268 | { |
1269 | extern void firetruck_init(void); | 1269 | extern void firetruck_init(void); |
1270 | extern void clock_probe(void); | ||
1271 | 1270 | ||
1272 | firetruck_init(); | 1271 | firetruck_init(); |
1273 | clock_probe(); | ||
1274 | } | 1272 | } |
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 | { |