From ee5caf0ee19f65a5e29bf20a0dffd8be8b4827fd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Jun 2006 14:36:52 -0700 Subject: [SPARC]: Convert clock drivers to of_driver framework. Signed-off-by: David S. Miller --- arch/sparc/kernel/time.c | 109 ++++++++------------ arch/sparc64/kernel/pci.c | 2 - arch/sparc64/kernel/sbus.c | 2 - arch/sparc64/kernel/time.c | 246 ++++++++++----------------------------------- 4 files changed, 94 insertions(+), 265 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 7dadcdb..9631e8f 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -42,6 +42,7 @@ #include #include #include +#include extern unsigned long wall_jiffies; @@ -273,83 +274,31 @@ static __inline__ void sun4_clock_probe(void) #endif } -/* Probe for the mostek real time clock chip. */ -static __inline__ void clock_probe(void) +static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { - struct linux_prom_registers clk_reg[2]; - char model[128]; - register int node, cpuunit, bootbus; - struct resource r; - - cpuunit = bootbus = 0; - memset(&r, 0, sizeof(r)); - - /* Determine the correct starting PROM node for the probe. */ - node = prom_getchild(prom_root_node); - switch (sparc_cpu_model) { - case sun4c: - break; - case sun4m: - node = prom_getchild(prom_searchsiblings(node, "obio")); - break; - case sun4d: - node = prom_getchild(bootbus = prom_searchsiblings(prom_getchild(cpuunit = prom_searchsiblings(node, "cpu-unit")), "bootbus")); - break; - default: - prom_printf("CLOCK: Unsupported architecture!\n"); - prom_halt(); - } + struct device_node *dp = op->node; + char *model = of_get_property(dp, "model", NULL); - /* Find the PROM node describing the real time clock. */ - sp_clock_typ = MSTK_INVALID; - node = prom_searchsiblings(node,"eeprom"); - if (!node) { - prom_printf("CLOCK: No clock found!\n"); - prom_halt(); - } + if (!model) + return -ENODEV; - /* Get the model name and setup everything up. */ - model[0] = '\0'; - prom_getstring(node, "model", model, sizeof(model)); - if (strcmp(model, "mk48t02") == 0) { + if (!strcmp(model, "mk48t02")) { sp_clock_typ = MSTK48T02; - if (prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) { - prom_printf("clock_probe: FAILED!\n"); - prom_halt(); - } - if (sparc_cpu_model == sun4d) - prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); - else - prom_apply_obio_ranges(clk_reg, 1); + /* Map the clock register io area read-only */ - r.flags = clk_reg[0].which_io; - r.start = clk_reg[0].phys_addr; - mstk48t02_regs = sbus_ioremap(&r, 0, - sizeof(struct mostek48t02), "mk48t02"); + mstk48t02_regs = of_ioremap(&op->resource[0], 0, + sizeof(struct mostek48t02), + "mk48t02"); mstk48t08_regs = NULL; /* To catch weirdness */ - } else if (strcmp(model, "mk48t08") == 0) { + } else if (!strcmp(model, "mk48t08")) { sp_clock_typ = MSTK48T08; - if(prom_getproperty(node, "reg", (char *) clk_reg, - sizeof(clk_reg)) == -1) { - prom_printf("clock_probe: FAILED!\n"); - prom_halt(); - } - if (sparc_cpu_model == sun4d) - prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); - else - prom_apply_obio_ranges(clk_reg, 1); - /* Map the clock register io area read-only */ - /* XXX r/o attribute is somewhere in r.flags */ - r.flags = clk_reg[0].which_io; - r.start = clk_reg[0].phys_addr; - mstk48t08_regs = sbus_ioremap(&r, 0, - sizeof(struct mostek48t08), "mk48t08"); + mstk48t08_regs = of_ioremap(&op->resource[0], 0, + sizeof(struct mostek48t08), + "mk48t08"); mstk48t02_regs = &mstk48t08_regs->regs; - } else { - prom_printf("CLOCK: Unknown model name '%s'\n",model); - prom_halt(); - } + } else + return -ENODEV; /* Report a low battery voltage condition. */ if (has_low_battery()) @@ -358,6 +307,28 @@ static __inline__ void clock_probe(void) /* Kick start the clock if it is completely stopped. */ if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) kick_start_clock(); + + return 0; +} + +static struct of_device_id clock_match[] = { + { + .name = "eeprom", + }, + {}, +}; + +static struct of_platform_driver clock_driver = { + .name = "clock", + .match_table = clock_match, + .probe = clock_probe, +}; + + +/* Probe for the mostek real time clock chip. */ +static void clock_init(void) +{ + of_register_driver(&clock_driver, &of_bus_type); } void __init sbus_time_init(void) @@ -376,7 +347,7 @@ void __init sbus_time_init(void) if (ARCH_SUN4) sun4_clock_probe(); else - clock_probe(); + clock_init(); sparc_init_timers(timer_interrupt); diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 20ca9ec..7b96258 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) p->scan_bus(p); } -extern void clock_probe(void); extern void power_init(void); static int __init pcibios_init(void) @@ -320,7 +319,6 @@ static int __init pcibios_init(void) isa_init(); ebus_init(); - clock_probe(); power_init(); return 0; diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 945222e..ef68aa4 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1267,8 +1267,6 @@ int __init sbus_arch_preinit(void) void __init sbus_arch_postinit(void) { extern void firetruck_init(void); - extern void clock_probe(void); firetruck_init(); - clock_probe(); } diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 348b820..540e4b6 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) return 1; } -static void __init __clock_assign_common(void __iomem *addr, char *model) +static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { - if (model[5] == '0' && model[6] == '2') { - mstk48t02_regs = addr; - } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = addr; - mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; - } else { - mstk48t59_regs = addr; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; - } -} - -static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg, - char *model) -{ - unsigned long addr; + struct device_node *dp = op->node; + char *model = of_get_property(dp, "model", NULL); + unsigned long size, flags; + void __iomem *regs; - addr = ((unsigned long) clk_reg[0].phys_addr | - (((unsigned long) clk_reg[0].which_io) << 32UL)); - - __clock_assign_common((void __iomem *) addr, model); -} - -static int __init clock_probe_central(void) -{ - struct linux_prom_registers clk_reg[2], *pr; - struct device_node *dp; - char *model; - - if (!central_bus) - return 0; - - /* Get Central FHC's prom node. */ - dp = central_bus->child->prom_node; - - /* Then get the first child device below it. */ - dp = dp->child; - - while (dp) { - model = of_get_property(dp, "model", NULL); - if (!model || !clock_model_matches(model)) - goto next_sibling; - - pr = of_get_property(dp, "reg", NULL); - memcpy(clk_reg, pr, sizeof(clk_reg)); - - apply_fhc_ranges(central_bus->child, clk_reg, 1); - apply_central_ranges(central_bus, clk_reg, 1); - - clock_assign_clk_reg(clk_reg, model); - return 1; - - next_sibling: - dp = dp->sibling; - } + if (!model || !clock_model_matches(model)) + return -ENODEV; - return 0; -} + size = (op->resource[0].end - op->resource[0].start) + 1; + regs = of_ioremap(&op->resource[0], 0, size, "clock"); + if (!regs) + return -ENOMEM; -#ifdef CONFIG_PCI -static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model) -{ if (!strcmp(model, "ds1287") || !strcmp(model, "m5819") || !strcmp(model, "m5819p") || !strcmp(model, "m5823")) { - ds1287_regs = res->start; + ds1287_regs = (unsigned long) regs; + } else if (model[5] == '0' && model[6] == '2') { + mstk48t02_regs = regs; + } else if(model[5] == '0' && model[6] == '8') { + mstk48t08_regs = regs; + mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; } else { - mstk48t59_regs = (void __iomem *) res->start; + mstk48t59_regs = regs; mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } -} - -static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev) -{ - struct device_node *dp = edev->prom_node; - char *model; - model = of_get_property(dp, "model", NULL); - if (!clock_model_matches(model)) - return 0; - - clock_isa_ebus_assign_regs(&edev->resource[0], model); + printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); - return 1; -} - -static int __init clock_probe_ebus(void) -{ - struct linux_ebus *ebus; + local_irq_save(flags); - for_each_ebus(ebus) { - struct linux_ebus_device *edev; + if (mstk48t02_regs != NULL) { + /* Report a low battery voltage condition. */ + if (has_low_battery()) + prom_printf("NVRAM: Low battery voltage!\n"); - for_each_ebusdev(edev, ebus) { - if (clock_probe_one_ebus_dev(edev)) - return 1; - } + /* Kick start the clock if it is completely stopped. */ + if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) + kick_start_clock(); } - return 0; -} - -static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev) -{ - struct device_node *dp = idev->prom_node; - char *model; - - model = of_get_property(dp, "model", NULL); - if (!clock_model_matches(model)) - return 0; - - clock_isa_ebus_assign_regs(&idev->resource, model); - - return 1; -} - -static int __init clock_probe_isa(void) -{ - struct sparc_isa_bridge *isa_br; - - for_each_isa(isa_br) { - struct sparc_isa_device *isa_dev; - - for_each_isadev(isa_dev, isa_br) { - if (clock_probe_one_isa_dev(isa_dev)) - return 1; - } - } + set_system_time(); + + local_irq_restore(flags); return 0; } -#endif /* CONFIG_PCI */ - -#ifdef CONFIG_SBUS -static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev) -{ - struct resource *res; - char model[64]; - void __iomem *addr; - - prom_getstring(sdev->prom_node, "model", model, sizeof(model)); - if (!clock_model_matches(model)) - return 0; - - res = &sdev->resource[0]; - addr = sbus_ioremap(res, 0, 0x800UL, "eeprom"); - - __clock_assign_common(addr, model); - return 1; -} - -static int __init clock_probe_sbus(void) -{ - struct sbus_bus *sbus; - - for_each_sbus(sbus) { - struct sbus_dev *sdev; - - for_each_sbusdev(sdev, sbus) { - if (clock_probe_one_sbus_dev(sbus, sdev)) - return 1; - } - } +static struct of_device_id clock_match[] = { + { + .name = "eeprom", + }, + { + .name = "rtc", + }, + {}, +}; - return 0; -} -#endif +static struct of_platform_driver clock_driver = { + .name = "clock", + .match_table = clock_match, + .probe = clock_probe, +}; -void __init clock_probe(void) +static int __init clock_init(void) { - static int invoked; - unsigned long flags; - - if (invoked) - return; - invoked = 1; - if (this_is_starfire) { xtime.tv_sec = starfire_get_time(); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - return; + return 0; } if (tlb_type == hypervisor) { xtime.tv_sec = hypervisor_get_time(); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - return; - } - - /* Check FHC Central then EBUSs then ISA bridges then SBUSs. - * That way we handle the presence of multiple properly. - * - * As a special case, machines with Central must provide the - * timer chip there. - */ - if (!clock_probe_central() && -#ifdef CONFIG_PCI - !clock_probe_ebus() && - !clock_probe_isa() && -#endif -#ifdef CONFIG_SBUS - !clock_probe_sbus() -#endif - ) { - printk(KERN_WARNING "No clock chip found.\n"); - return; - } - - local_irq_save(flags); - - if (mstk48t02_regs != NULL) { - /* Report a low battery voltage condition. */ - if (has_low_battery()) - prom_printf("NVRAM: Low battery voltage!\n"); - - /* Kick start the clock if it is completely stopped. */ - if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) - kick_start_clock(); + return 0; } - set_system_time(); - - local_irq_restore(flags); + return of_register_driver(&clock_driver, &of_bus_type); } +/* Must be after subsys_initcall() so that busses are probed. Must + * be before device_initcall() because things like the RTC driver + * need to see the clock registers. + */ +fs_initcall(clock_init); + /* This is gets the master TICK_INT timer going. */ static unsigned long sparc64_init_timers(void) { -- cgit v1.1