diff options
Diffstat (limited to 'arch/sparc/kernel')
26 files changed, 544 insertions, 1344 deletions
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 6e03a2a7863c..2d6582095099 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -13,15 +13,13 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ time.o windows.o cpu.o devices.o \ tadpole.o tick14.o ptrace.o \ unaligned.o una_asm.o muldiv.o \ - prom.o of_device.o devres.o + prom.o of_device.o devres.o dma.o devres-y = ../../../kernel/irq/devres.o obj-$(CONFIG_PCI) += pcic.o -obj-$(CONFIG_SUN4) += sun4setup.o obj-$(CONFIG_SMP) += trampoline.o smp.o sun4m_smp.o sun4d_smp.o obj-$(CONFIG_SUN_AUXIO) += auxio.o -obj-$(CONFIG_PCI) += ebus.o obj-$(CONFIG_SUN_PM) += apc.o pmc.o obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o obj-$(CONFIG_SPARC_LED) += led.o diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 5267d48fb2c6..4dd1ba752ce6 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c @@ -12,9 +12,10 @@ #include <linux/miscdevice.h> #include <linux/smp_lock.h> #include <linux/pm.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/io.h> -#include <asm/sbus.h> #include <asm/oplib.h> #include <asm/uaccess.h> #include <asm/auxio.h> @@ -29,11 +30,10 @@ #define APC_OBPNAME "power-management" #define APC_DEVNAME "apc" -volatile static u8 __iomem *regs; -static int apc_regsize; +static u8 __iomem *regs; static int apc_no_idle __initdata = 0; -#define apc_readb(offs) (sbus_readb(regs+offs)) +#define apc_readb(offs) (sbus_readb(regs+offs)) #define apc_writeb(val, offs) (sbus_writeb(val, regs+offs)) /* Specify "apc=noidle" on the kernel command line to @@ -69,9 +69,9 @@ static void apc_swift_idle(void) #endif } -static inline void apc_free(void) +static inline void apc_free(struct of_device *op) { - sbus_iounmap(regs, apc_regsize); + of_iounmap(&op->resource[0], regs, resource_size(&op->resource[0])); } static int apc_open(struct inode *inode, struct file *f) @@ -153,52 +153,56 @@ static const struct file_operations apc_fops = { static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops }; -static int __init apc_probe(void) +static int __devinit apc_probe(struct of_device *op, + const struct of_device_id *match) { - struct sbus_bus *sbus = NULL; - struct sbus_dev *sdev = NULL; - int iTmp = 0; - - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, APC_OBPNAME)) { - goto sbus_done; - } - } - } + int err; -sbus_done: - if (!sdev) { - return -ENODEV; - } - - apc_regsize = sdev->reg_addrs[0].reg_size; - regs = sbus_ioremap(&sdev->resource[0], 0, - apc_regsize, APC_OBPNAME); - if(!regs) { + regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), APC_OBPNAME); + if (!regs) { printk(KERN_ERR "%s: unable to map registers\n", APC_DEVNAME); return -ENODEV; } - iTmp = misc_register(&apc_miscdev); - if (iTmp != 0) { + err = misc_register(&apc_miscdev); + if (err) { printk(KERN_ERR "%s: unable to register device\n", APC_DEVNAME); - apc_free(); + apc_free(op); return -ENODEV; } /* Assign power management IDLE handler */ - if(!apc_no_idle) + if (!apc_no_idle) pm_idle = apc_swift_idle; printk(KERN_INFO "%s: power management initialized%s\n", - APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); + APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); + return 0; } +static struct of_device_id __initdata apc_match[] = { + { + .name = APC_OBPNAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, apc_match); + +static struct of_platform_driver apc_driver = { + .name = "apc", + .match_table = apc_match, + .probe = apc_probe, +}; + +static int __init apc_init(void) +{ + return of_register_driver(&apc_driver, &of_bus_type); +} + /* This driver is not critical to the boot process * and is easiest to ioremap when SBus is already * initialized, so we install ourselves thusly: */ -__initcall(apc_probe); - +__initcall(apc_init); diff --git a/arch/sparc/kernel/auxio.c b/arch/sparc/kernel/auxio.c index baf4ed3fb0f3..09c857215a52 100644 --- a/arch/sparc/kernel/auxio.c +++ b/arch/sparc/kernel/auxio.c @@ -6,6 +6,8 @@ #include <linux/stddef.h> #include <linux/init.h> #include <linux/spinlock.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/oplib.h> #include <asm/io.h> #include <asm/auxio.h> @@ -59,7 +61,7 @@ void __init auxio_probe(void) r.flags = auxregs[0].which_io & 0xF; r.start = auxregs[0].phys_addr; r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1; - auxio_register = sbus_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); + auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); /* Fix the address on sun4m and sun4c. */ if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || sparc_cpu_model == sun4c) @@ -128,7 +130,7 @@ void __init auxio_power_probe(void) r.flags = regs.which_io & 0xF; r.start = regs.phys_addr; r.end = regs.phys_addr + regs.reg_size - 1; - auxio_power_register = (unsigned char *) sbus_ioremap(&r, 0, + auxio_power_register = (unsigned char *) of_ioremap(&r, 0, regs.reg_size, "auxpower"); /* Display a quick message on the console. */ diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index b240b8863fd0..ad656b044b8c 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -143,7 +143,7 @@ void __init device_scan(void) #endif clock_stop_probe(); - if (ARCH_SUN4C_SUN4) + if (ARCH_SUN4C) sun4c_probe_memerr_reg(); return; diff --git a/arch/sparc/kernel/dma.c b/arch/sparc/kernel/dma.c new file mode 100644 index 000000000000..ebc8403b035e --- /dev/null +++ b/arch/sparc/kernel/dma.c @@ -0,0 +1,227 @@ +/* dma.c: PCI and SBUS DMA accessors for 32-bit sparc. + * + * Copyright (C) 2008 David S. Miller <davem@davemloft.net> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/scatterlist.h> +#include <linux/mm.h> + +#ifdef CONFIG_PCI +#include <linux/pci.h> +#endif + +#include "dma.h" + +int dma_supported(struct device *dev, u64 mask) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_dma_supported(to_pci_dev(dev), mask); +#endif + return 0; +} +EXPORT_SYMBOL(dma_supported); + +int dma_set_mask(struct device *dev, u64 dma_mask) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_set_dma_mask(to_pci_dev(dev), dma_mask); +#endif + return -EOPNOTSUPP; +} +EXPORT_SYMBOL(dma_set_mask); + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); +#endif + return sbus_alloc_consistent(dev, size, dma_handle); +} +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_coherent(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t dma_handle) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_free_consistent(to_pci_dev(dev), size, + cpu_addr, dma_handle); + return; + } +#endif + sbus_free_consistent(dev, size, cpu_addr, dma_handle); +} +EXPORT_SYMBOL(dma_free_coherent); + +dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_map_single(to_pci_dev(dev), cpu_addr, + size, (int)direction); +#endif + return sbus_map_single(dev, cpu_addr, size, (int)direction); +} +EXPORT_SYMBOL(dma_map_single); + +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, + enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_unmap_single(to_pci_dev(dev), dma_addr, + size, (int)direction); + return; + } +#endif + sbus_unmap_single(dev, dma_addr, size, (int)direction); +} +EXPORT_SYMBOL(dma_unmap_single); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_map_page(to_pci_dev(dev), page, offset, + size, (int)direction); +#endif + return sbus_map_single(dev, page_address(page) + offset, + size, (int)direction); +} +EXPORT_SYMBOL(dma_map_page); + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_unmap_page(to_pci_dev(dev), dma_address, + size, (int)direction); + return; + } +#endif + sbus_unmap_single(dev, dma_address, size, (int)direction); +} +EXPORT_SYMBOL(dma_unmap_page); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) + return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); +#endif + return sbus_map_sg(dev, sg, nents, direction); +} +EXPORT_SYMBOL(dma_map_sg); + +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_unmap_sg(to_pci_dev(dev), sg, nents, (int)direction); + return; + } +#endif + sbus_unmap_sg(dev, sg, nents, (int)direction); +} +EXPORT_SYMBOL(dma_unmap_sg); + +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, + size, (int)direction); + return; + } +#endif + sbus_dma_sync_single_for_cpu(dev, dma_handle, size, (int) direction); +} +EXPORT_SYMBOL(dma_sync_single_for_cpu); + +void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, + size, (int)direction); + return; + } +#endif + sbus_dma_sync_single_for_device(dev, dma_handle, size, (int) direction); +} +EXPORT_SYMBOL(dma_sync_single_for_device); + +void dma_sync_single_range_for_cpu(struct device *dev, + dma_addr_t dma_handle, + unsigned long offset, + size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); +} +EXPORT_SYMBOL(dma_sync_single_range_for_cpu); + +void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + dma_sync_single_for_device(dev, dma_handle+offset, size, direction); +} +EXPORT_SYMBOL(dma_sync_single_range_for_device); + +void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, + nelems, (int)direction); + return; + } +#endif + BUG(); +} +EXPORT_SYMBOL(dma_sync_sg_for_cpu); + +void dma_sync_sg_for_device(struct device *dev, + struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ +#ifdef CONFIG_PCI + if (dev->bus == &pci_bus_type) { + pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, + nelems, (int)direction); + return; + } +#endif + BUG(); +} +EXPORT_SYMBOL(dma_sync_sg_for_device); + +int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return (dma_addr == DMA_ERROR_CODE); +} +EXPORT_SYMBOL(dma_mapping_error); + +int dma_get_cache_alignment(void) +{ + return 32; +} +EXPORT_SYMBOL(dma_get_cache_alignment); diff --git a/arch/sparc/kernel/dma.h b/arch/sparc/kernel/dma.h new file mode 100644 index 000000000000..f8d8951adb53 --- /dev/null +++ b/arch/sparc/kernel/dma.h @@ -0,0 +1,14 @@ +void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp); +void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba); +dma_addr_t sbus_map_single(struct device *dev, void *va, + size_t len, int direction); +void sbus_unmap_single(struct device *dev, dma_addr_t ba, + size_t n, int direction); +int sbus_map_sg(struct device *dev, struct scatterlist *sg, + int n, int direction); +void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, + int n, int direction); +void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, + size_t size, int direction); +void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, + size_t size, int direction); diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c deleted file mode 100644 index 97294232259c..000000000000 --- a/arch/sparc/kernel/ebus.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * ebus.c: PCI to EBus bridge device. - * - * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) - * - * Adopted for sparc by V. Roganov and G. Raiko. - * Fixes for different platforms by Pete Zaitcev. - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/string.h> - -#include <asm/system.h> -#include <asm/page.h> -#include <asm/pbm.h> -#include <asm/ebus.h> -#include <asm/io.h> -#include <asm/oplib.h> -#include <asm/prom.h> -#include <asm/bpp.h> - -struct linux_ebus *ebus_chain = NULL; - -/* We are together with pcic.c under CONFIG_PCI. */ -extern unsigned int pcic_pin_to_irq(unsigned int, const char *name); - -/* - * IRQ Blacklist - * Here we list PROMs and systems that are known to supply crap as IRQ numbers. - */ -struct ebus_device_irq { - char *name; - unsigned int pin; -}; - -struct ebus_system_entry { - char *esname; - struct ebus_device_irq *ipt; -}; - -static struct ebus_device_irq je1_1[] = { - { "8042", 3 }, - { "SUNW,CS4231", 0 }, - { "parallel", 0 }, - { "se", 2 }, - { NULL, 0 } -}; - -/* - * Gleb's JE1 supplied reasonable pin numbers, but mine did not (OBP 2.32). - * Blacklist the sucker... Note that Gleb's system will work. - */ -static struct ebus_system_entry ebus_blacklist[] = { - { "SUNW,JavaEngine1", je1_1 }, - { NULL, NULL } -}; - -static struct ebus_device_irq *ebus_blackp = NULL; - -/* - */ -static inline unsigned long ebus_alloc(size_t size) -{ - return (unsigned long)kmalloc(size, GFP_ATOMIC); -} - -/* - */ -static int __init ebus_blacklist_irq(const char *name) -{ - struct ebus_device_irq *dp; - - if ((dp = ebus_blackp) != NULL) { - for (; dp->name != NULL; dp++) { - if (strcmp(name, dp->name) == 0) { - return pcic_pin_to_irq(dp->pin, name); - } - } - } - return 0; -} - -static void __init fill_ebus_child(struct device_node *dp, - struct linux_ebus_child *dev) -{ - const int *regs; - const int *irqs; - int i, len; - - dev->prom_node = dp; - regs = of_get_property(dp, "reg", &len); - if (!regs) - len = 0; - dev->num_addrs = len / sizeof(regs[0]); - - for (i = 0; i < dev->num_addrs; i++) { - if (regs[i] >= dev->parent->num_addrs) { - prom_printf("UGH: property for %s was %d, need < %d\n", - dev->prom_node->name, len, - dev->parent->num_addrs); - panic(__func__); - } - - /* XXX resource */ - dev->resource[i].start = - dev->parent->resource[regs[i]].start; - } - - for (i = 0; i < PROMINTR_MAX; i++) - dev->irqs[i] = PCI_IRQ_NONE; - - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { - dev->num_irqs = 1; - } else { - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { - dev->num_irqs = 0; - dev->irqs[0] = 0; - if (dev->parent->num_irqs != 0) { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[0]; - } - } else { - dev->num_irqs = len / sizeof(irqs[0]); - if (irqs[0] == 0 || irqs[0] >= 8) { - /* - * XXX Zero is a valid pin number... - * This works as long as Ebus is not wired - * to INTA#. - */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_node->name, irqs[0]); - dev->num_irqs = 0; - dev->irqs[0] = 0; - } else { - dev->irqs[0] = - pcic_pin_to_irq(irqs[0], - dev->prom_node->name); - } - } - } -} - -static void __init fill_ebus_device(struct device_node *dp, - struct linux_ebus_device *dev) -{ - const struct linux_prom_registers *regs; - struct linux_ebus_child *child; - struct dev_archdata *sd; - const int *irqs; - int i, n, len; - unsigned long baseaddr; - - dev->prom_node = dp; - - regs = of_get_property(dp, "reg", &len); - if (!regs) - len = 0; - if (len % sizeof(struct linux_prom_registers)) { - prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", - dev->prom_node->name, len, - (int)sizeof(struct linux_prom_registers)); - panic(__func__); - } - dev->num_addrs = len / sizeof(struct linux_prom_registers); - - for (i = 0; i < dev->num_addrs; i++) { - /* - * XXX Collect JE-1 PROM - * - * Example - JS-E with 3.11: - * /ebus - * regs - * 0x00000000, 0x0, 0x00000000, 0x0, 0x00000000, - * 0x82000010, 0x0, 0xf0000000, 0x0, 0x01000000, - * 0x82000014, 0x0, 0x38800000, 0x0, 0x00800000, - * ranges - * 0x00, 0x00000000, 0x02000010, 0x0, 0x0, 0x01000000, - * 0x01, 0x01000000, 0x02000014, 0x0, 0x0, 0x00800000, - * /ebus/8042 - * regs - * 0x00000001, 0x00300060, 0x00000008, - * 0x00000001, 0x00300060, 0x00000008, - */ - n = regs[i].which_io; - if (n >= 4) { - /* XXX This is copied from old JE-1 by Gleb. */ - n = (regs[i].which_io - 0x10) >> 2; - } else { - ; - } - -/* - * XXX Now as we have regions, why don't we make an on-demand allocation... - */ - dev->resource[i].start = 0; - if ((baseaddr = dev->bus->self->resource[n].start + - regs[i].phys_addr) != 0) { - /* dev->resource[i].name = dev->prom_name; */ - if ((baseaddr = (unsigned long) ioremap(baseaddr, - regs[i].reg_size)) == 0) { - panic("ebus: unable to remap dev %s", - dev->prom_node->name); - } - } - dev->resource[i].start = baseaddr; /* XXX Unaligned */ - } - - for (i = 0; i < PROMINTR_MAX; i++) - dev->irqs[i] = PCI_IRQ_NONE; - - if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { - dev->num_irqs = 1; - } else { - irqs = of_get_property(dp, "interrupts", &len); - if (!irqs) { - dev->num_irqs = 0; - if ((dev->irqs[0] = dev->bus->self->irq) != 0) { - dev->num_irqs = 1; -/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ - } - } else { - dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ - if (irqs[0] == 0 || irqs[0] >= 8) { - /* See above for the parent. XXX */ - printk("EBUS: %s got bad irq %d from PROM\n", - dev->prom_node->name, irqs[0]); - dev->num_irqs = 0; - dev->irqs[0] = 0; - } else { - dev->irqs[0] = - pcic_pin_to_irq(irqs[0], - dev->prom_node->name); - } - } - } - - sd = &dev->ofdev.dev.archdata; - sd->prom_node = dp; - sd->op = &dev->ofdev; - sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; - - dev->ofdev.node = dp; - dev->ofdev.dev.parent = &dev->bus->ofdev.dev; - dev->ofdev.dev.bus = &ebus_bus_type; - sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node); - - /* Register with core */ - if (of_device_register(&dev->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - if ((dp = dp->child) != NULL) { - dev->children = (struct linux_ebus_child *) - ebus_alloc(sizeof(struct linux_ebus_child)); - - child = dev->children; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child); - - while ((dp = dp->sibling) != NULL) { - child->next = (struct linux_ebus_child *) - ebus_alloc(sizeof(struct linux_ebus_child)); - - child = child->next; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child); - } - } -} - -void __init ebus_init(void) -{ - const struct linux_prom_pci_registers *regs; - struct linux_pbm_info *pbm; - struct linux_ebus_device *dev; - struct linux_ebus *ebus; - struct ebus_system_entry *sp; - struct pci_dev *pdev; - struct pcidev_cookie *cookie; - struct device_node *dp; - struct resource *p; - unsigned short pci_command; - int len, reg, nreg; - int num_ebus = 0; - - dp = of_find_node_by_path("/"); - for (sp = ebus_blacklist; sp->esname != NULL; sp++) { - if (strcmp(dp->name, sp->esname) == 0) { - ebus_blackp = sp->ipt; - break; - } - } - - pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL); - if (!pdev) - return; - - cookie = pdev->sysdata; - dp = cookie->prom_node; - - ebus_chain = ebus = (struct linux_ebus *) - ebus_alloc(sizeof(struct linux_ebus)); - ebus->next = NULL; - - while (dp) { - struct device_node *nd; - - ebus->prom_node = dp; - ebus->self = pdev; - ebus->parent = pbm = cookie->pbm; - - /* Enable BUS Master. */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - pci_command |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, pci_command); - - regs = of_get_property(dp, "reg", &len); - if (!regs) { - prom_printf("%s: can't find reg property\n", - __func__); - prom_halt(); - } - nreg = len / sizeof(struct linux_prom_pci_registers); - - p = &ebus->self->resource[0]; - for (reg = 0; reg < nreg; reg++) { - if (!(regs[reg].which_io & 0x03000000)) - continue; - - (p++)->start = regs[reg].phys_lo; - } - - ebus->ofdev.node = dp; - ebus->ofdev.dev.parent = &pdev->dev; - ebus->ofdev.dev.bus = &ebus_bus_type; - sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus); - - /* Register with core */ - if (of_device_register(&ebus->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - - nd = dp->child; - if (!nd) - goto next_ebus; - - ebus->devices = (struct linux_ebus_device *) - ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = ebus->devices; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(nd, dev); - - while ((nd = nd->sibling) != NULL) { - dev->next = (struct linux_ebus_device *) - ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = dev->next; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(nd, dev); - } - - next_ebus: - pdev = pci_get_device(PCI_VENDOR_ID_SUN, - PCI_DEVICE_ID_SUN_EBUS, pdev); - if (!pdev) - break; - - cookie = pdev->sysdata; - dp = cookie->prom_node; - - ebus->next = (struct linux_ebus *) - ebus_alloc(sizeof(struct linux_ebus)); - ebus = ebus->next; - ebus->next = NULL; - ++num_ebus; - } - if (pdev) - pci_dev_put(pdev); -} diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index e8cdf715a546..68689facaaae 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -20,11 +20,7 @@ #include <asm/memreg.h> #include <asm/page.h> #include <asm/pgtable.h> -#ifdef CONFIG_SUN4 -#include <asm/pgtsun4.h> -#else #include <asm/pgtsun4c.h> -#endif #include <asm/winmacro.h> #include <asm/signal.h> #include <asm/obio.h> @@ -775,11 +771,7 @@ vac_linesize_patch_32: subcc %l7, 32, %l7 * Ugly, but we cant use hardware flushing on the sun4 and we'd require * two instructions (Anton) */ -#ifdef CONFIG_SUN4 -vac_hwflush_patch1_on: nop -#else vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 -#endif vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG @@ -798,42 +790,10 @@ vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG ! %l7 = 1 for textfault ! We want error in %l5, vaddr in %l6 sun4c_fault: -#ifdef CONFIG_SUN4 - sethi %hi(sun4c_memerr_reg), %l4 - ld [%l4+%lo(sun4c_memerr_reg)], %l4 ! memerr ctrl reg addr - ld [%l4], %l6 ! memerr ctrl reg - ld [%l4 + 4], %l5 ! memerr vaddr reg - andcc %l6, 0x80, %g0 ! check for error type - st %g0, [%l4 + 4] ! clear the error - be 0f ! normal error - sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr - - call prom_halt ! something weird happened - ! what exactly did happen? - ! what should we do here? - -0: or %l4, %lo(AC_BUS_ERROR), %l4 ! bus err reg addr - lduba [%l4] ASI_CONTROL, %l6 ! bus err reg - - cmp %l7, 1 ! text fault? - be 1f ! yes - nop - - ld [%l1], %l4 ! load instruction that caused fault - srl %l4, 21, %l4 - andcc %l4, 1, %g0 ! store instruction? - - be 1f ! no - sethi %hi(SUN4C_SYNC_BADWRITE), %l4 ! yep - ! %lo(SUN4C_SYNC_BADWRITE) = 0 - or %l4, %l6, %l6 ! set write bit to emulate sun4c -1: -#else sethi %hi(AC_SYNC_ERR), %l4 add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 lda [%l6] ASI_CONTROL, %l5 ! Address lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit -#endif andn %l5, 0xfff, %l5 ! Encode all info into l7 srl %l6, 14, %l4 @@ -880,12 +840,7 @@ sun4c_fault: or %l4, %lo(swapper_pg_dir), %l4 sll %l6, 2, %l6 ld [%l4 + %l6], %l4 -#ifdef CONFIG_SUN4 - sethi %hi(PAGE_MASK), %l6 - andcc %l4, %l6, %g0 -#else andcc %l4, PAGE_MASK, %g0 -#endif be sun4c_fault_fromuser lduXa [%l5] ASI_SEGMAP, %l4 @@ -937,11 +892,7 @@ invalid_segment_patch1: ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr ! Flush segment from the cache. -#ifdef CONFIG_SUN4 - sethi %hi((128 * 1024)), %l7 -#else sethi %hi((64 * 1024)), %l7 -#endif 9: vac_hwflush_patch1: vac_linesize_patch: @@ -1029,12 +980,7 @@ invalid_segment_patch2: or %l4, %lo(swapper_pg_dir), %l4 sll %l3, 2, %l3 ld [%l4 + %l3], %l4 -#ifndef CONFIG_SUN4 and %l4, PAGE_MASK, %l4 -#else - sethi %hi(PAGE_MASK), %l6 - and %l4, %l6, %l4 -#endif srl %l5, (PAGE_SHIFT - 2), %l6 and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 50d9a16af795..2d325fd84579 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -63,15 +63,9 @@ cputypvar_sun4m: .align 4 -#ifndef CONFIG_SUN4 sun4_notsup: - .asciz "Sparc-Linux sun4 needs a specially compiled kernel, turn CONFIG_SUN4 on.\n\n" + .asciz "Sparc-Linux sun4 support does no longer exist.\n\n" .align 4 -#else -sun4cdm_notsup: - .asciz "Kernel compiled with CONFIG_SUN4 cannot run on SUN4C/SUN4M/SUN4D\nTurn CONFIG_SUN4 off.\n\n" - .align 4 -#endif sun4e_notsup: .asciz "Sparc-Linux sun4e support does not exist\n\n" @@ -780,15 +774,6 @@ execute_in_high_mem: nop found_version: -#ifdef CONFIG_SUN4 -/* For people who try sun4 kernels, even if Configure.help advises them. */ - ld [%g7 + 0x68], %o1 - set sun4cdm_notsup, %o0 - call %o1 - nop - b halt_me - nop -#endif /* Get the machine type via the mysterious romvec node operations. */ add %g7, 0x1c, %l1 @@ -1150,15 +1135,6 @@ sun4c_continue_boot: nop sun4_init: -#ifdef CONFIG_SUN4 -/* There, happy now Adrian? */ - set cputypval, %o2 ! Let everyone know we - set ' ', %o0 ! are a "sun4 " architecture - stb %o0, [%o2 + 0x4] - - b got_prop - nop -#else sethi %hi(SUN4_PROM_VECTOR+0x84), %o1 ld [%o1 + %lo(SUN4_PROM_VECTOR+0x84)], %o1 set sun4_notsup, %o0 @@ -1170,7 +1146,7 @@ sun4_init: nop 1: ba 1b ! Cannot exit into KMON nop -#endif + no_sun4e_here: ld [%g7 + 0x68], %o1 set sun4e_notsup, %o0 diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c index fc511f3c4c18..223a6582e1e2 100644 --- a/arch/sparc/kernel/idprom.c +++ b/arch/sparc/kernel/idprom.c @@ -12,10 +12,6 @@ #include <asm/oplib.h> #include <asm/idprom.h> #include <asm/machines.h> /* Fun with Sun released architectures. */ -#ifdef CONFIG_SUN4 -#include <asm/sun4paddr.h> -extern void sun4setup(void); -#endif struct idprom *idprom; static struct idprom idprom_buffer; @@ -101,7 +97,4 @@ void __init idprom_init(void) idprom->id_ethaddr[0], idprom->id_ethaddr[1], idprom->id_ethaddr[2], idprom->id_ethaddr[3], idprom->id_ethaddr[4], idprom->id_ethaddr[5]); -#ifdef CONFIG_SUN4 - sun4setup(); -#endif } diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 2a8a847764d8..4f025b36934b 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -42,10 +42,13 @@ #include <asm/vaddrs.h> #include <asm/oplib.h> #include <asm/prom.h> -#include <asm/sbus.h> #include <asm/page.h> #include <asm/pgalloc.h> #include <asm/dma.h> +#include <asm/iommu.h> +#include <asm/io-unit.h> + +#include "dma.h" #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ @@ -139,15 +142,6 @@ void iounmap(volatile void __iomem *virtual) } } -/* - */ -void __iomem *sbus_ioremap(struct resource *phyres, unsigned long offset, - unsigned long size, char *name) -{ - return _sparc_alloc_io(phyres->flags & 0xF, - phyres->start + offset, size, name); -} - void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name) { @@ -164,13 +158,6 @@ void of_iounmap(struct resource *res, void __iomem *base, unsigned long size) EXPORT_SYMBOL(of_iounmap); /* - */ -void sbus_iounmap(volatile void __iomem *addr, unsigned long size) -{ - iounmap(addr); -} - -/* * Meat of mapping */ static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, @@ -246,63 +233,19 @@ static void _sparc_free_io(struct resource *res) #ifdef CONFIG_SBUS -void sbus_set_sbus64(struct sbus_dev *sdev, int x) +void sbus_set_sbus64(struct device *dev, int x) { printk("sbus_set_sbus64: unsupported\n"); } -extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); -void __init sbus_fill_device_irq(struct sbus_dev *sdev) -{ - struct linux_prom_irqs irqs[PROMINTR_MAX]; - int len; - - len = prom_getproperty(sdev->prom_node, "intr", - (char *)irqs, sizeof(irqs)); - if (len != -1) { - sdev->num_irqs = len / 8; - if (sdev->num_irqs == 0) { - sdev->irqs[0] = 0; - } else if (sparc_cpu_model == sun4d) { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = - sun4d_build_irq(sdev, irqs[len].pri); - } else { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = irqs[len].pri; - } - } else { - int interrupts[PROMINTR_MAX]; - - /* No "intr" node found-- check for "interrupts" node. - * This node contains SBus interrupt levels, not IPLs - * as in "intr", and no vector values. We convert - * SBus interrupt levels to PILs (platform specific). - */ - len = prom_getproperty(sdev->prom_node, "interrupts", - (char *)interrupts, sizeof(interrupts)); - if (len == -1) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - sdev->num_irqs = len / sizeof(int); - for (len = 0; len < sdev->num_irqs; len++) { - sdev->irqs[len] = - sbint_to_irq(sdev, interrupts[len]); - } - } - } -} - /* * Allocate a chunk of memory suitable for DMA. * Typically devices use them for control blocks. * CPU may access them without any explicit flushing. - * - * XXX Some clever people know that sdev is not used and supply NULL. Watch. */ -void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) +void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp) { + struct of_device *op = to_of_device(dev); unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; unsigned long va; struct resource *res; @@ -336,13 +279,10 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) * XXX That's where sdev would be used. Currently we load * all iommu tables with the same translations. */ - if (mmu_map_dma_area(dma_addrp, va, res->start, len_total) != 0) + if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) goto err_noiommu; - /* Set the resource name, if known. */ - if (sdev) { - res->name = sdev->prom_name; - } + res->name = op->node->name; return (void *)(unsigned long)res->start; @@ -356,7 +296,7 @@ err_nopages: return NULL; } -void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) +void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba) { struct resource *res; struct page *pgv; @@ -383,8 +323,8 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) kfree(res); /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ - pgv = mmu_translate_dvma(ba); - mmu_unmap_dma_area(ba, n); + pgv = virt_to_page(p); + mmu_unmap_dma_area(dev, ba, n); __free_pages(pgv, get_order(n)); } @@ -394,7 +334,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) * CPU view of this memory may be inconsistent with * a device view and explicit flushing is necessary. */ -dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int direction) +dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int direction) { /* XXX why are some lengths signed, others unsigned? */ if (len <= 0) { @@ -404,17 +344,17 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int dire if (len > 256*1024) { /* __get_free_pages() limit */ return 0; } - return mmu_get_scsi_one(va, len, sdev->bus); + return mmu_get_scsi_one(dev, va, len); } -void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t ba, size_t n, int direction) +void sbus_unmap_single(struct device *dev, dma_addr_t ba, size_t n, int direction) { - mmu_release_scsi_one(ba, n, sdev->bus); + mmu_release_scsi_one(dev, ba, n); } -int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) +int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction) { - mmu_get_scsi_sgl(sg, n, sdev->bus); + mmu_get_scsi_sgl(dev, sg, n); /* * XXX sparc64 can return a partial length here. sun4c should do this @@ -423,145 +363,28 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direct return n; } -void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) -{ - mmu_release_scsi_sgl(sg, n, sdev->bus); -} - -/* - */ -void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction) -{ -#if 0 - unsigned long va; - struct resource *res; - - /* We do not need the resource, just print a message if invalid. */ - res = _sparc_find_resource(&_sparc_dvma, ba); - if (res == NULL) - panic("sbus_dma_sync_single: 0x%x\n", ba); - - va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */ - /* - * XXX This bogosity will be fixed with the iommu rewrite coming soon - * to a kernel near you. - Anton - */ - /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ -#endif -} - -void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction) +void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direction) { -#if 0 - unsigned long va; - struct resource *res; - - /* We do not need the resource, just print a message if invalid. */ - res = _sparc_find_resource(&_sparc_dvma, ba); - if (res == NULL) - panic("sbus_dma_sync_single: 0x%x\n", ba); - - va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */ - /* - * XXX This bogosity will be fixed with the iommu rewrite coming soon - * to a kernel near you. - Anton - */ - /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ -#endif + mmu_release_scsi_sgl(dev, sg, n); } -void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) +void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size, int direction) { - printk("sbus_dma_sync_sg_for_cpu: not implemented yet\n"); } -void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) +void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t size, int direction) { - printk("sbus_dma_sync_sg_for_device: not implemented yet\n"); -} - -/* Support code for sbus_init(). */ -/* - * XXX This functions appears to be a distorted version of - * prom_sbus_ranges_init(), with all sun4d stuff cut away. - * Ask DaveM what is going on here, how is sun4d supposed to work... XXX - */ -/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ -void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) -{ - int parent_node = pn->node; - - if (sparc_cpu_model == sun4d) { - struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; - int num_iounit_ranges, len; - - len = prom_getproperty(parent_node, "ranges", - (char *) iounit_ranges, - sizeof (iounit_ranges)); - if (len != -1) { - num_iounit_ranges = - (len / sizeof(struct linux_prom_ranges)); - prom_adjust_ranges(sbus->sbus_ranges, - sbus->num_sbus_ranges, - iounit_ranges, num_iounit_ranges); - } - } } -void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) -{ -#ifndef CONFIG_SUN4 - struct device_node *parent = dp->parent; - - if (sparc_cpu_model != sun4d && - parent != NULL && - !strcmp(parent->name, "iommu")) { - extern void iommu_init(int iommu_node, struct sbus_bus *sbus); - - iommu_init(parent->node, sbus); - } - - if (sparc_cpu_model == sun4d) { - extern void iounit_init(int sbi_node, int iounit_node, - struct sbus_bus *sbus); - - iounit_init(dp->node, parent->node, sbus); - } -#endif -} - -void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) -{ - if (sparc_cpu_model == sun4d) { - struct device_node *parent = dp->parent; - - sbus->devid = of_getintprop_default(parent, "device-id", 0); - sbus->board = of_getintprop_default(parent, "board#", 0); - } -} - -int __init sbus_arch_preinit(void) +static int __init sparc_register_ioport(void) { register_proc_sparc_ioport(); -#ifdef CONFIG_SUN4 - { - extern void sun4_dvma_init(void); - sun4_dvma_init(); - } - return 1; -#else return 0; -#endif } -void __init sbus_arch_postinit(void) -{ - if (sparc_cpu_model == sun4d) { - extern void sun4d_init_sbi_irq(void); - sun4d_init_sbi_irq(); - } -} +arch_initcall(sparc_register_ioport); + #endif /* CONFIG_SBUS */ #ifdef CONFIG_PCI diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index c481d45f97b7..c88af7efc335 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -29,15 +29,38 @@ struct of_device *of_find_device_by_node(struct device_node *dp) } EXPORT_SYMBOL(of_find_device_by_node); -#ifdef CONFIG_PCI -struct bus_type ebus_bus_type; -EXPORT_SYMBOL(ebus_bus_type); -#endif +unsigned int irq_of_parse_and_map(struct device_node *node, int index) +{ + struct of_device *op = of_find_device_by_node(node); + + if (!op || index >= op->num_irqs) + return 0; + + return op->irqs[index]; +} +EXPORT_SYMBOL(irq_of_parse_and_map); + +/* Take the archdata values for IOMMU, STC, and HOSTDATA found in + * BUS and propagate to all child of_device objects. + */ +void of_propagate_archdata(struct of_device *bus) +{ + struct dev_archdata *bus_sd = &bus->dev.archdata; + struct device_node *bus_dp = bus->node; + struct device_node *dp; + + for (dp = bus_dp->child; dp; dp = dp->sibling) { + struct of_device *op = of_find_device_by_node(dp); -#ifdef CONFIG_SBUS -struct bus_type sbus_bus_type; -EXPORT_SYMBOL(sbus_bus_type); -#endif + op->dev.archdata.iommu = bus_sd->iommu; + op->dev.archdata.stc = bus_sd->stc; + op->dev.archdata.host_controller = bus_sd->host_controller; + op->dev.archdata.numa_node = bus_sd->numa_node; + + if (dp->child) + of_propagate_archdata(op); + } +} struct bus_type of_platform_bus_type; EXPORT_SYMBOL(of_platform_bus_type); @@ -327,6 +350,27 @@ static int __init build_one_resource(struct device_node *parent, return 1; } +static int __init use_1to1_mapping(struct device_node *pp) +{ + /* If we have a ranges property in the parent, use it. */ + if (of_find_property(pp, "ranges", NULL) != NULL) + return 0; + + /* Some SBUS devices use intermediate nodes to express + * hierarchy within the device itself. These aren't + * real bus nodes, and don't have a 'ranges' property. + * But, we should still pass the translation work up + * to the SBUS itself. + */ + if (!strcmp(pp->name, "dma") || + !strcmp(pp->name, "espdma") || + !strcmp(pp->name, "ledma") || + !strcmp(pp->name, "lebuffer")) + return 0; + + return 1; +} + static int of_resource_verbose; static void __init build_device_resources(struct of_device *op, @@ -373,10 +417,7 @@ static void __init build_device_resources(struct of_device *op, flags = bus->get_flags(reg, 0); - /* If the immediate parent has no ranges property to apply, - * just use a 1<->1 mapping. - */ - if (of_find_property(pp, "ranges", NULL) == NULL) { + if (use_1to1_mapping(pp)) { result = of_read_addr(addr, na); goto build_res; } @@ -565,15 +606,6 @@ static int __init of_bus_driver_init(void) int err; err = of_bus_type_init(&of_platform_bus_type, "of"); -#ifdef CONFIG_PCI - if (!err) - err = of_bus_type_init(&ebus_bus_type, "ebus"); -#endif -#ifdef CONFIG_SBUS - if (!err) - err = of_bus_type_init(&sbus_bus_type, "sbus"); -#endif - if (!err) scan_of_devices(); diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index a6a6f9823370..e5950b03df13 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -17,8 +17,6 @@ #include <linux/slab.h> #include <linux/jiffies.h> -#include <asm/ebus.h> -#include <asm/sbus.h> /* for sanity check... */ #include <asm/swift.h> /* for cache flushing. */ #include <asm/io.h> @@ -430,7 +428,6 @@ static int __init pcic_init(void) pcic_pbm_scan_bus(pcic); - ebus_init(); return 0; } @@ -493,10 +490,6 @@ static void pcic_map_pci_device(struct linux_pcic *pcic, * do ioremap() before accessing PC-style I/O, * we supply virtual, ready to access address. * - * Ebus devices do not come here even if - * CheerIO makes a similar conversion. - * See ebus.c for details. - * * Note that request_region() * works for these devices. * @@ -677,7 +670,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) } /* - * pcic_pin_to_irq() is exported to ebus.c. + * pcic_pin_to_irq() is exported to bus probing code */ unsigned int pcic_pin_to_irq(unsigned int pin, const char *name) diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 7eca8871ff47..814eb3ce039b 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c @@ -10,9 +10,10 @@ #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/pm.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/io.h> -#include <asm/sbus.h> #include <asm/oplib.h> #include <asm/uaccess.h> #include <asm/auxio.h> @@ -30,10 +31,9 @@ #define PMC_IDLE_REG 0x00 #define PMC_IDLE_ON 0x01 -volatile static u8 __iomem *regs; -static int pmc_regsize; +static u8 __iomem *regs; -#define pmc_readb(offs) (sbus_readb(regs+offs)) +#define pmc_readb(offs) (sbus_readb(regs+offs)) #define pmc_writeb(val, offs) (sbus_writeb(val, regs+offs)) /* @@ -53,31 +53,11 @@ void pmc_swift_idle(void) #endif } -static inline void pmc_free(void) +static int __devinit pmc_probe(struct of_device *op, + const struct of_device_id *match) { - sbus_iounmap(regs, pmc_regsize); -} - -static int __init pmc_probe(void) -{ - struct sbus_bus *sbus = NULL; - struct sbus_dev *sdev = NULL; - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, PMC_OBPNAME)) { - goto sbus_done; - } - } - } - -sbus_done: - if (!sdev) { - return -ENODEV; - } - - pmc_regsize = sdev->reg_addrs[0].reg_size; - regs = sbus_ioremap(&sdev->resource[0], 0, - pmc_regsize, PMC_OBPNAME); + regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), PMC_OBPNAME); if (!regs) { printk(KERN_ERR "%s: unable to map registers\n", PMC_DEVNAME); return -ENODEV; @@ -92,8 +72,27 @@ sbus_done: return 0; } +static struct of_device_id __initdata pmc_match[] = { + { + .name = PMC_OBPNAME, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, pmc_match); + +static struct of_platform_driver pmc_driver = { + .name = "pmc", + .match_table = pmc_match, + .probe = pmc_probe, +}; + +static int __init pmc_init(void) +{ + return of_register_driver(&pmc_driver, &of_bus_type); +} + /* This driver is not critical to the boot process * and is easiest to ioremap when SBus is already * initialized, so we install ourselves thusly: */ -__initcall(pmc_probe); +__initcall(pmc_init); diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 4bb430940a61..e8c43ffe317e 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -75,7 +75,7 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ for (;;) { - if (ARCH_SUN4C_SUN4) { + if (ARCH_SUN4C) { static int count = HZ; static unsigned long last_jiffies; static unsigned long last_faults; diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index cd4fb79aa3a8..eee5efcfe50e 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -54,6 +54,9 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); +DEFINE_MUTEX(of_set_property_mutex); +EXPORT_SYMBOL(of_set_property_mutex); + int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; @@ -77,7 +80,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *old_val = prop->value; int ret; + mutex_lock(&of_set_property_mutex); ret = prom_setprop(dp->node, (char *) name, val, len); + mutex_unlock(&of_set_property_mutex); + err = -EINVAL; if (ret >= 0) { prop->value = new_val; @@ -436,7 +442,6 @@ static void __init of_console_init(void) switch (prom_vers) { case PROM_V0: - case PROM_SUN4: skip = 0; switch (*romvec->pv_stdout) { case PROMDEV_SCREEN: diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 9e451b21202e..8d5fbce1635b 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -224,12 +224,6 @@ void __init setup_arch(char **cmdline_p) if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; } if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; } -#ifdef CONFIG_SUN4 - if (sparc_cpu_model != sun4) { - prom_printf("This kernel is for Sun4 architecture only.\n"); - prom_halt(); - } -#endif printk("ARCH: "); switch(sparc_cpu_model) { case sun4: @@ -263,7 +257,7 @@ void __init setup_arch(char **cmdline_p) boot_flags_init(*cmdline_p); idprom_init(); - if (ARCH_SUN4C_SUN4) + if (ARCH_SUN4C) sun4c_probe_vac(); load_mmu(); diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index b23cea5ca5d1..b0dfff848653 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -38,17 +38,12 @@ #include <asm/idprom.h> #include <asm/head.h> #include <asm/smp.h> -#include <asm/mostek.h> #include <asm/ptrace.h> #include <asm/uaccess.h> #include <asm/checksum.h> #ifdef CONFIG_SBUS -#include <asm/sbus.h> #include <asm/dma.h> #endif -#ifdef CONFIG_PCI -#include <asm/ebus.h> -#endif #include <asm/io-unit.h> #include <asm/bug.h> @@ -127,16 +122,11 @@ EXPORT_SYMBOL(phys_cpu_present_map); EXPORT_SYMBOL(__udelay); EXPORT_SYMBOL(__ndelay); EXPORT_SYMBOL(rtc_lock); -EXPORT_SYMBOL(mostek_lock); -EXPORT_SYMBOL(mstk48t02_regs); #ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(set_auxio); EXPORT_SYMBOL(get_auxio); #endif EXPORT_SYMBOL(io_remap_pfn_range); - /* P3: iounit_xxx may be needed, sun4d users */ -/* EXPORT_SYMBOL(iounit_map_dma_init); */ -/* EXPORT_SYMBOL(iounit_map_dma_page); */ #ifndef CONFIG_SMP EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32)); @@ -153,24 +143,9 @@ EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one)); EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); #ifdef CONFIG_SBUS -EXPORT_SYMBOL(sbus_root); -EXPORT_SYMBOL(dma_chain); EXPORT_SYMBOL(sbus_set_sbus64); -EXPORT_SYMBOL(sbus_alloc_consistent); -EXPORT_SYMBOL(sbus_free_consistent); -EXPORT_SYMBOL(sbus_map_single); -EXPORT_SYMBOL(sbus_unmap_single); -EXPORT_SYMBOL(sbus_map_sg); -EXPORT_SYMBOL(sbus_unmap_sg); -EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_single_for_device); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); -EXPORT_SYMBOL(sbus_iounmap); -EXPORT_SYMBOL(sbus_ioremap); #endif #ifdef CONFIG_PCI -EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(insb); EXPORT_SYMBOL(outsb); EXPORT_SYMBOL(insw); diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 340fc395fe2d..722d2516f284 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -18,6 +18,8 @@ #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/init.h> +#include <linux/of.h> +#include <linux/of_device.h> #include "irq.h" #include <asm/ptrace.h> @@ -31,10 +33,8 @@ #include <asm/traps.h> #include <asm/irq.h> #include <asm/io.h> -#include <asm/sun4paddr.h> #include <asm/idprom.h> #include <asm/machines.h> -#include <asm/sbus.h> #if 0 static struct resource sun4c_timer_eb = { "sun4c_timer" }; @@ -66,18 +66,6 @@ static struct resource sun4c_intr_eb = { "sun4c_intr" }; */ unsigned char *interrupt_enable = NULL; -static int sun4c_pil_map[] = { 0, 1, 2, 3, 5, 7, 8, 9 }; - -static unsigned int sun4c_sbint_to_irq(struct sbus_dev *sdev, - unsigned int sbint) -{ - if (sbint >= sizeof(sun4c_pil_map)) { - printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); - BUG(); - } - return sun4c_pil_map[sbint]; -} - static void sun4c_disable_irq(unsigned int irq_nr) { unsigned long flags; @@ -141,22 +129,10 @@ static void sun4c_enable_irq(unsigned int irq_nr) volatile struct sun4c_timer_info *sun4c_timers; -#ifdef CONFIG_SUN4 -/* This is an ugly hack to work around the - current timer code, and make it work with - the sun4/260 intersil - */ -volatile struct sun4c_timer_info sun4_timer; -#endif - static void sun4c_clear_clock_irq(void) { volatile unsigned int clear_intr; -#ifdef CONFIG_SUN4 - if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) - clear_intr = sun4_timer.timer_limit10; - else -#endif + clear_intr = sun4c_timers->timer_limit10; } @@ -177,11 +153,6 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn) /* Map the Timer chip, this is implemented in hardware inside * the cache chip on the sun4c. */ -#ifdef CONFIG_SUN4 - if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) - sun4c_timers = &sun4_timer; - else -#endif sun4c_timers = ioremap(SUN_TIMER_PHYSADDR, sizeof(struct sun4c_timer_info)); @@ -217,33 +188,26 @@ void __init sun4c_init_IRQ(void) { struct linux_prom_registers int_regs[2]; int ie_node; - - if (ARCH_SUN4) { - interrupt_enable = (char *) - ioremap(sun4_ie_physaddr, PAGE_SIZE); - } else { - struct resource phyres; - - ie_node = prom_searchsiblings (prom_getchild(prom_root_node), - "interrupt-enable"); - if(ie_node == 0) - panic("Cannot find /interrupt-enable node"); - - /* Depending on the "address" property is bad news... */ - interrupt_enable = NULL; - if (prom_getproperty(ie_node, "reg", (char *) int_regs, - sizeof(int_regs)) != -1) { - memset(&phyres, 0, sizeof(struct resource)); - phyres.flags = int_regs[0].which_io; - phyres.start = int_regs[0].phys_addr; - interrupt_enable = (char *) sbus_ioremap(&phyres, 0, - int_regs[0].reg_size, "sun4c_intr"); - } + struct resource phyres; + + ie_node = prom_searchsiblings (prom_getchild(prom_root_node), + "interrupt-enable"); + if(ie_node == 0) + panic("Cannot find /interrupt-enable node"); + + /* Depending on the "address" property is bad news... */ + interrupt_enable = NULL; + if (prom_getproperty(ie_node, "reg", (char *) int_regs, + sizeof(int_regs)) != -1) { + memset(&phyres, 0, sizeof(struct resource)); + phyres.flags = int_regs[0].which_io; + phyres.start = int_regs[0].phys_addr; + interrupt_enable = (char *) of_ioremap(&phyres, 0, + int_regs[0].reg_size, "sun4c_intr"); } if (!interrupt_enable) panic("Cannot map interrupt_enable"); - BTFIXUPSET_CALL(sbint_to_irq, sun4c_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 1290b5998f83..c4a2bfb750a4 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -19,6 +19,8 @@ #include <linux/smp.h> #include <linux/spinlock.h> #include <linux/seq_file.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/ptrace.h> #include <asm/processor.h> @@ -34,7 +36,6 @@ #include <asm/io.h> #include <asm/pgalloc.h> #include <asm/pgtable.h> -#include <asm/sbus.h> #include <asm/sbi.h> #include <asm/cacheflush.h> #include <asm/irq_regs.h> @@ -257,26 +258,6 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs) set_irq_regs(old_regs); } -unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq) -{ - int sbusl = pil_to_sbus[irq]; - - if (sbusl) - return ((sdev->bus->board + 1) << 5) + (sbusl << 2) + sdev->slot; - else - return irq; -} - -static unsigned int sun4d_sbint_to_irq(struct sbus_dev *sdev, - unsigned int sbint) -{ - if (sbint >= sizeof(sbus_to_pil)) { - printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); - BUG(); - } - return sun4d_build_irq(sdev, sbus_to_pil[sbint]); -} - int sun4d_request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void *dev_id) @@ -409,47 +390,55 @@ static void sun4d_set_udt(int cpu) /* Setup IRQ distribution scheme. */ void __init sun4d_distribute_irqs(void) { + struct device_node *dp; + #ifdef DISTRIBUTE_IRQS - struct sbus_bus *sbus; - unsigned long sbus_serving_map; + cpumask_t sbus_serving_map; sbus_serving_map = cpu_present_map; - for_each_sbus(sbus) { - if ((sbus->board * 2) == boot_cpu_id && (cpu_present_map & (1 << (sbus->board * 2 + 1)))) - sbus_tid[sbus->board] = (sbus->board * 2 + 1); - else if (cpu_present_map & (1 << (sbus->board * 2))) - sbus_tid[sbus->board] = (sbus->board * 2); - else if (cpu_present_map & (1 << (sbus->board * 2 + 1))) - sbus_tid[sbus->board] = (sbus->board * 2 + 1); + for_each_node_by_name(dp, "sbi") { + int board = of_getintprop_default(dp, "board#", 0); + + if ((board * 2) == boot_cpu_id && cpu_isset(board * 2 + 1, cpu_present_map)) + sbus_tid[board] = (board * 2 + 1); + else if (cpu_isset(board * 2, cpu_present_map)) + sbus_tid[board] = (board * 2); + else if (cpu_isset(board * 2 + 1, cpu_present_map)) + sbus_tid[board] = (board * 2 + 1); else - sbus_tid[sbus->board] = 0xff; - if (sbus_tid[sbus->board] != 0xff) - sbus_serving_map &= ~(1 << sbus_tid[sbus->board]); + sbus_tid[board] = 0xff; + if (sbus_tid[board] != 0xff) + cpu_clear(sbus_tid[board], sbus_serving_map); } - for_each_sbus(sbus) - if (sbus_tid[sbus->board] == 0xff) { + for_each_node_by_name(dp, "sbi") { + int board = of_getintprop_default(dp, "board#", 0); + if (sbus_tid[board] == 0xff) { int i = 31; - if (!sbus_serving_map) + if (cpus_empty(sbus_serving_map)) sbus_serving_map = cpu_present_map; - while (!(sbus_serving_map & (1 << i))) + while (cpu_isset(i, sbus_serving_map)) i--; - sbus_tid[sbus->board] = i; - sbus_serving_map &= ~(1 << i); + sbus_tid[board] = i; + cpu_clear(i, sbus_serving_map); } - for_each_sbus(sbus) { - printk("sbus%d IRQs directed to CPU%d\n", sbus->board, sbus_tid[sbus->board]); - set_sbi_tid(sbus->devid, sbus_tid[sbus->board] << 3); + } + for_each_node_by_name(dp, "sbi") { + int devid = of_getintprop_default(dp, "device-id", 0); + int board = of_getintprop_default(dp, "board#", 0); + printk("sbus%d IRQs directed to CPU%d\n", board, sbus_tid[board]); + set_sbi_tid(devid, sbus_tid[board] << 3); } #else - struct sbus_bus *sbus; int cpuid = cpu_logical_map(1); if (cpuid == -1) cpuid = cpu_logical_map(0); - for_each_sbus(sbus) { - sbus_tid[sbus->board] = cpuid; - set_sbi_tid(sbus->devid, cpuid << 3); + for_each_node_by_name(dp, "sbi") { + int devid = of_getintprop_default(dp, "device-id", 0); + int board = of_getintprop_default(dp, "board#", 0); + sbus_tid[board] = cpuid; + set_sbi_tid(devid, cpuid << 3); } printk("All sbus IRQs directed to CPU%d\n", cpuid); #endif @@ -487,7 +476,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) r.start = CSR_BASE(0)+BW_TIMER_LIMIT; #endif r.flags = 0xf; - sun4d_timers = (struct sun4d_timer_regs *) sbus_ioremap(&r, 0, + sun4d_timers = (struct sun4d_timer_regs *) of_ioremap(&r, 0, PAGE_SIZE, "user timer"); sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); @@ -541,29 +530,34 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) void __init sun4d_init_sbi_irq(void) { - struct sbus_bus *sbus; - unsigned mask; + struct device_node *dp; nsbi = 0; - for_each_sbus(sbus) + for_each_node_by_name(dp, "sbi") nsbi++; sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); if (!sbus_actions) { prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); prom_halt(); } - for_each_sbus(sbus) { + for_each_node_by_name(dp, "sbi") { + int devid = of_getintprop_default(dp, "device-id", 0); + int board = of_getintprop_default(dp, "board#", 0); + unsigned int mask; + #ifdef CONFIG_SMP - extern unsigned char boot_cpu_id; + { + extern unsigned char boot_cpu_id; - set_sbi_tid(sbus->devid, boot_cpu_id << 3); - sbus_tid[sbus->board] = boot_cpu_id; + set_sbi_tid(devid, boot_cpu_id << 3); + sbus_tid[board] = boot_cpu_id; + } #endif /* Get rid of pending irqs from PROM */ - mask = acquire_sbi(sbus->devid, 0xffffffff); + mask = acquire_sbi(devid, 0xffffffff); if (mask) { - printk ("Clearing pending IRQs %08x on SBI %d\n", mask, sbus->board); - release_sbi(sbus->devid, mask); + printk ("Clearing pending IRQs %08x on SBI %d\n", mask, board); + release_sbi(devid, mask); } } } @@ -572,7 +566,6 @@ void __init sun4d_init_IRQ(void) { local_irq_disable(); - BTFIXUPSET_CALL(sbint_to_irq, sun4d_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 69596402a500..72fa8daab60b 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -30,7 +30,6 @@ #include <asm/pgalloc.h> #include <asm/pgtable.h> #include <asm/oplib.h> -#include <asm/sbus.h> #include <asm/sbi.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 94e02de960ea..3481feca3354 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -20,6 +20,8 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/ioport.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <asm/ptrace.h> #include <asm/processor.h> @@ -35,7 +37,6 @@ #include <asm/smp.h> #include <asm/irq.h> #include <asm/io.h> -#include <asm/sbus.h> #include <asm/cacheflush.h> #include "irq.h" @@ -152,18 +153,6 @@ static unsigned long irq_mask[] = { SUN4M_INT_SBUS(6) /* 14 irq 13 */ }; -static int sun4m_pil_map[] = { 0, 2, 3, 5, 7, 9, 11, 13 }; - -static unsigned int sun4m_sbint_to_irq(struct sbus_dev *sdev, - unsigned int sbint) -{ - if (sbint >= sizeof(sun4m_pil_map)) { - printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); - BUG(); - } - return sun4m_pil_map[sbint] | 0x30; -} - static unsigned long sun4m_get_irqmask(unsigned int irq) { unsigned long mask; @@ -339,13 +328,13 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) /* Map the per-cpu Counter registers. */ r.flags = cnt_regs[0].which_io; r.start = cnt_regs[0].phys_addr; - sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0, + sun4m_timers = (struct sun4m_timer_regs *) of_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt"); /* Map the system Counter register. */ /* XXX Here we expect consequent calls to yeld adjusent maps. */ r.flags = cnt_regs[4].which_io; r.start = cnt_regs[4].phys_addr; - sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); + of_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4m_timers->l10_cur_count; @@ -423,13 +412,13 @@ void __init sun4m_init_IRQ(void) /* Map the interrupt registers for all possible cpus. */ r.flags = int_regs[0].which_io; r.start = int_regs[0].phys_addr; - sun4m_interrupts = (struct sun4m_intregs *) sbus_ioremap(&r, 0, + sun4m_interrupts = (struct sun4m_intregs *) of_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); /* Map the system interrupt control registers. */ r.flags = int_regs[4].which_io; r.start = int_regs[4].phys_addr; - sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); + of_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); sun4m_interrupts->set = ~SUN4M_INT_MASKALL; for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) @@ -447,7 +436,6 @@ void __init sun4m_init_IRQ(void) &sun4m_interrupts->undirected_target; sun4m_interrupts->undirected_target = 0; } - BTFIXUPSET_CALL(sbint_to_irq, sun4m_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); diff --git a/arch/sparc/kernel/sun4setup.c b/arch/sparc/kernel/sun4setup.c deleted file mode 100644 index 229a52f55f16..000000000000 --- a/arch/sparc/kernel/sun4setup.c +++ /dev/null @@ -1,75 +0,0 @@ -/* sun4setup.c: Setup the hardware address of various items in the sun4 - * architecture. Called from idprom_init - * - * Copyright (C) 1998 Chris G. Davis (cdavis@cois.on.ca) - */ - -#include <asm/page.h> -#include <asm/oplib.h> -#include <asm/idprom.h> -#include <asm/sun4paddr.h> -#include <asm/machines.h> - -int sun4_memreg_physaddr; -int sun4_ie_physaddr; -int sun4_clock_physaddr; -int sun4_timer_physaddr; -int sun4_eth_physaddr; -int sun4_si_physaddr; -int sun4_bwtwo_physaddr; -int sun4_zs0_physaddr; -int sun4_zs1_physaddr; -int sun4_dma_physaddr; -int sun4_esp_physaddr; -int sun4_ie_physaddr; - -void __init sun4setup(void) -{ - printk("Sun4 Hardware Setup v1.0 18/May/98 Chris Davis (cdavis@cois.on.ca). "); - /* - setup standard sun4 info - */ - sun4_ie_physaddr=SUN4_IE_PHYSADDR; - - /* - setup model specific info - */ - switch(idprom->id_machtype) { - case (SM_SUN4 | SM_4_260 ): - printk("Setup for a SUN4/260\n"); - sun4_memreg_physaddr=SUN4_200_MEMREG_PHYSADDR; - sun4_clock_physaddr=SUN4_200_CLOCK_PHYSADDR; - sun4_timer_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_eth_physaddr=SUN4_200_ETH_PHYSADDR; - sun4_si_physaddr=SUN4_200_SI_PHYSADDR; - sun4_bwtwo_physaddr=SUN4_200_BWTWO_PHYSADDR; - sun4_dma_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_esp_physaddr=SUN4_UNUSED_PHYSADDR; - break; - case (SM_SUN4 | SM_4_330 ): - printk("Setup for a SUN4/330\n"); - sun4_memreg_physaddr=SUN4_300_MEMREG_PHYSADDR; - sun4_clock_physaddr=SUN4_300_CLOCK_PHYSADDR; - sun4_timer_physaddr=SUN4_300_TIMER_PHYSADDR; - sun4_eth_physaddr=SUN4_300_ETH_PHYSADDR; - sun4_si_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_bwtwo_physaddr=SUN4_300_BWTWO_PHYSADDR; - sun4_dma_physaddr=SUN4_300_DMA_PHYSADDR; - sun4_esp_physaddr=SUN4_300_ESP_PHYSADDR; - break; - case (SM_SUN4 | SM_4_470 ): - printk("Setup for a SUN4/470\n"); - sun4_memreg_physaddr=SUN4_400_MEMREG_PHYSADDR; - sun4_clock_physaddr=SUN4_400_CLOCK_PHYSADDR; - sun4_timer_physaddr=SUN4_400_TIMER_PHYSADDR; - sun4_eth_physaddr=SUN4_400_ETH_PHYSADDR; - sun4_si_physaddr=SUN4_UNUSED_PHYSADDR; - sun4_bwtwo_physaddr=SUN4_400_BWTWO_PHYSADDR; - sun4_dma_physaddr=SUN4_400_DMA_PHYSADDR; - sun4_esp_physaddr=SUN4_400_ESP_PHYSADDR; - break; - default: - ; - } -} - diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 4d73421559c3..03035c852a43 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -53,7 +53,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi /* See asm-sparc/uaccess.h */ if (len > TASK_SIZE - PAGE_SIZE) return -ENOMEM; - if (ARCH_SUN4C_SUN4 && len > 0x20000000) + if (ARCH_SUN4C && len > 0x20000000) return -ENOMEM; if (!addr) addr = TASK_UNMAPPED_BASE; @@ -65,7 +65,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { /* At this point: (!vmm || addr < vmm->vm_end). */ - if (ARCH_SUN4C_SUN4 && addr < 0xe0000000 && 0x20000000 - len < addr) { + if (ARCH_SUN4C && addr < 0xe0000000 && 0x20000000 - len < addr) { addr = PAGE_OFFSET; vmm = find_vma(current->mm, PAGE_OFFSET); } @@ -81,7 +81,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi asmlinkage unsigned long sparc_brk(unsigned long brk) { - if(ARCH_SUN4C_SUN4) { + if(ARCH_SUN4C) { if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000)) return current->mm->brk; } @@ -221,7 +221,7 @@ out: int sparc_mmap_check(unsigned long addr, unsigned long len) { - if (ARCH_SUN4C_SUN4 && + if (ARCH_SUN4C && (len > 0x20000000 || (addr < 0xe0000000 && addr + len > 0x20000000))) return -EINVAL; diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index 707bfda86570..77a4f3aeec67 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c @@ -20,7 +20,6 @@ #include <asm/oplib.h> #include <asm/timer.h> -#include <asm/mostek.h> #include <asm/system.h> #include <asm/irq.h> #include <asm/io.h> diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 0762f5db1924..698c45059fa5 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -23,22 +23,24 @@ #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/time.h> +#include <linux/rtc.h> +#include <linux/rtc/m48t59.h> #include <linux/timex.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/ioport.h> #include <linux/profile.h> +#include <linux/of.h> #include <linux/of_device.h> +#include <linux/platform_device.h> #include <asm/oplib.h> #include <asm/timer.h> -#include <asm/mostek.h> #include <asm/system.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/idprom.h> #include <asm/machines.h> -#include <asm/sun4paddr.h> #include <asm/page.h> #include <asm/pcic.h> #include <asm/irq_regs.h> @@ -46,34 +48,9 @@ #include "irq.h" DEFINE_SPINLOCK(rtc_lock); -static enum sparc_clock_type sp_clock_typ; -DEFINE_SPINLOCK(mostek_lock); -void __iomem *mstk48t02_regs = NULL; -static struct mostek48t08 __iomem *mstk48t08_regs = NULL; static int set_rtc_mmss(unsigned long); static int sbus_do_settimeofday(struct timespec *tv); -#ifdef CONFIG_SUN4 -struct intersil *intersil_clock; -#define intersil_cmd(intersil_reg, intsil_cmd) intersil_reg->int_cmd_reg = \ - (intsil_cmd) - -#define intersil_intr(intersil_reg, intsil_cmd) intersil_reg->int_intr_reg = \ - (intsil_cmd) - -#define intersil_start(intersil_reg) intersil_cmd(intersil_reg, \ - ( INTERSIL_START | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\ - INTERSIL_INTR_ENABLE)) - -#define intersil_stop(intersil_reg) intersil_cmd(intersil_reg, \ - ( INTERSIL_STOP | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\ - INTERSIL_INTR_ENABLE)) - -#define intersil_read_intr(intersil_reg, towhere) towhere = \ - intersil_reg->int_intr_reg - -#endif - unsigned long profile_pc(struct pt_regs *regs) { extern char __copy_user_begin[], __copy_user_end[]; @@ -116,15 +93,7 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) /* Protect counter clear so that do_gettimeoffset works */ write_seqlock(&xtime_lock); -#ifdef CONFIG_SUN4 - if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) || - (idprom->id_machtype == (SM_SUN4 | SM_4_110))) { - int temp; - intersil_read_intr(intersil_clock, temp); - /* re-enable the irq */ - enable_pil_irq(10); - } -#endif + clear_clock_irq(); do_timer(1); @@ -147,157 +116,56 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) return IRQ_HANDLED; } -/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ -static void __devinit kick_start_clock(void) +static unsigned char mostek_read_byte(struct device *dev, u32 ofs) { - struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; - unsigned char sec; - int i, count; - - prom_printf("CLOCK: Clock was stopped. Kick start "); - - spin_lock_irq(&mostek_lock); - - /* Turn on the kick start bit to start the oscillator. */ - regs->creg |= MSTK_CREG_WRITE; - regs->sec &= ~MSTK_STOP; - regs->hour |= MSTK_KICK_START; - regs->creg &= ~MSTK_CREG_WRITE; - - spin_unlock_irq(&mostek_lock); - - /* Delay to allow the clock oscillator to start. */ - sec = MSTK_REG_SEC(regs); - for (i = 0; i < 3; i++) { - while (sec == MSTK_REG_SEC(regs)) - for (count = 0; count < 100000; count++) - /* nothing */ ; - prom_printf("."); - sec = regs->sec; - } - prom_printf("\n"); - - spin_lock_irq(&mostek_lock); - - /* Turn off kick start and set a "valid" time and date. */ - regs->creg |= MSTK_CREG_WRITE; - regs->hour &= ~MSTK_KICK_START; - MSTK_SET_REG_SEC(regs,0); - MSTK_SET_REG_MIN(regs,0); - MSTK_SET_REG_HOUR(regs,0); - MSTK_SET_REG_DOW(regs,5); - MSTK_SET_REG_DOM(regs,1); - MSTK_SET_REG_MONTH(regs,8); - MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); - regs->creg &= ~MSTK_CREG_WRITE; - - spin_unlock_irq(&mostek_lock); - - /* Ensure the kick start bit is off. If it isn't, turn it off. */ - while (regs->hour & MSTK_KICK_START) { - prom_printf("CLOCK: Kick start still on!\n"); - - spin_lock_irq(&mostek_lock); - regs->creg |= MSTK_CREG_WRITE; - regs->hour &= ~MSTK_KICK_START; - regs->creg &= ~MSTK_CREG_WRITE; - spin_unlock_irq(&mostek_lock); + struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; + void __iomem *regs = pdata->ioaddr; + unsigned char val = readb(regs + ofs); + + /* the year 0 is 1968 */ + if (ofs == pdata->offset + M48T59_YEAR) { + val += 0x68; + if ((val & 0xf) > 9) + val += 6; } - - prom_printf("CLOCK: Kick start procedure successful.\n"); -} - -/* Return nonzero if the clock chip battery is low. */ -static inline int has_low_battery(void) -{ - struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; - unsigned char data1, data2; - - spin_lock_irq(&mostek_lock); - data1 = regs->eeprom[0]; /* Read some data. */ - regs->eeprom[0] = ~data1; /* Write back the complement. */ - data2 = regs->eeprom[0]; /* Read back the complement. */ - regs->eeprom[0] = data1; /* Restore the original value. */ - spin_unlock_irq(&mostek_lock); - - return (data1 == data2); /* Was the write blocked? */ + return val; } -static void __devinit mostek_set_system_time(void) +static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) { - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - - mregs = (struct mostek48t02 *)mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - spin_lock_irq(&mostek_lock); - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - mregs->creg &= ~MSTK_CREG_READ; - spin_unlock_irq(&mostek_lock); + struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; + void __iomem *regs = pdata->ioaddr; + + if (ofs == pdata->offset + M48T59_YEAR) { + if (val < 0x68) + val += 0x32; + else + val -= 0x68; + if ((val & 0xf) > 9) + val += 6; + if ((val & 0xf0) > 0x9A) + val += 0x60; + } + writeb(val, regs + ofs); } -/* Probe for the real time clock chip on Sun4 */ -static inline void sun4_clock_probe(void) -{ -#ifdef CONFIG_SUN4 - int temp; - struct resource r; - - memset(&r, 0, sizeof(r)); - if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) { - sp_clock_typ = MSTK48T02; - r.start = sun4_clock_physaddr; - mstk48t02_regs = sbus_ioremap(&r, 0, - sizeof(struct mostek48t02), NULL); - mstk48t08_regs = NULL; /* To catch weirdness */ - intersil_clock = NULL; /* just in case */ - - /* Kick start the clock if it is completely stopped. */ - if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) - kick_start_clock(); - } else if( idprom->id_machtype == (SM_SUN4 | SM_4_260)) { - /* intersil setup code */ - printk("Clock: INTERSIL at %8x ",sun4_clock_physaddr); - sp_clock_typ = INTERSIL; - r.start = sun4_clock_physaddr; - intersil_clock = (struct intersil *) - sbus_ioremap(&r, 0, sizeof(*intersil_clock), "intersil"); - mstk48t02_regs = 0; /* just be sure */ - mstk48t08_regs = NULL; /* ditto */ - /* initialise the clock */ - - intersil_intr(intersil_clock,INTERSIL_INT_100HZ); - - intersil_start(intersil_clock); - - intersil_read_intr(intersil_clock, temp); - while (!(temp & 0x80)) - intersil_read_intr(intersil_clock, temp); - - intersil_read_intr(intersil_clock, temp); - while (!(temp & 0x80)) - intersil_read_intr(intersil_clock, temp); - - intersil_stop(intersil_clock); +static struct m48t59_plat_data m48t59_data = { + .read_byte = mostek_read_byte, + .write_byte = mostek_write_byte, +}; - } -#endif -} +/* resource is set at runtime */ +static struct platform_device m48t59_rtc = { + .name = "rtc-m48t59", + .id = 0, + .num_resources = 1, + .dev = { + .platform_data = &m48t59_data, + }, +}; -#ifndef CONFIG_SUN4 static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; @@ -306,38 +174,26 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id if (!model) return -ENODEV; + m48t59_rtc.resource = &op->resource[0]; if (!strcmp(model, "mk48t02")) { - sp_clock_typ = MSTK48T02; - /* Map the clock register io area read-only */ - mstk48t02_regs = of_ioremap(&op->resource[0], 0, - sizeof(struct mostek48t02), - "mk48t02"); - mstk48t08_regs = NULL; /* To catch weirdness */ + m48t59_data.ioaddr = of_ioremap(&op->resource[0], 0, + 2048, "rtc-m48t59"); + m48t59_data.type = M48T59RTC_TYPE_M48T02; } else if (!strcmp(model, "mk48t08")) { - sp_clock_typ = MSTK48T08; - mstk48t08_regs = of_ioremap(&op->resource[0], 0, - sizeof(struct mostek48t08), - "mk48t08"); - - mstk48t02_regs = &mstk48t08_regs->regs; + m48t59_data.ioaddr = of_ioremap(&op->resource[0], 0, + 8192, "rtc-m48t59"); + m48t59_data.type = M48T59RTC_TYPE_M48T08; } else return -ENODEV; - /* Report a low battery voltage condition. */ - if (has_low_battery()) - printk(KERN_CRIT "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(); - - mostek_set_system_time(); + if (platform_device_register(&m48t59_rtc) < 0) + printk(KERN_ERR "Registering RTC device failed\n"); return 0; } -static struct of_device_id clock_match[] = { +static struct of_device_id __initdata clock_match[] = { { .name = "eeprom", }, @@ -348,7 +204,7 @@ static struct of_platform_driver clock_driver = { .match_table = clock_match, .probe = clock_probe, .driver = { - .name = "clock", + .name = "rtc", }, }; @@ -364,7 +220,6 @@ static int __init clock_init(void) * need to see the clock registers. */ fs_initcall(clock_init); -#endif /* !CONFIG_SUN4 */ static void __init sbus_time_init(void) { @@ -372,51 +227,8 @@ static void __init sbus_time_init(void) BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); - if (ARCH_SUN4) - sun4_clock_probe(); - sparc_init_timers(timer_interrupt); -#ifdef CONFIG_SUN4 - if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { - mostek_set_system_time(); - } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { - /* initialise the intersil on sun4 */ - unsigned int year, mon, day, hour, min, sec; - int temp; - struct intersil *iregs; - - iregs=intersil_clock; - if(!iregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - intersil_intr(intersil_clock,INTERSIL_INT_100HZ); - disable_pil_irq(10); - intersil_stop(iregs); - intersil_read_intr(intersil_clock, temp); - - temp = iregs->clk.int_csec; - - sec = iregs->clk.int_sec; - min = iregs->clk.int_min; - hour = iregs->clk.int_hour; - day = iregs->clk.int_day; - mon = iregs->clk.int_month; - year = MSTK_CVT_YEAR(iregs->clk.int_year); - - enable_pil_irq(10); - intersil_start(iregs); - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec); - } -#endif - /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */ local_irq_enable(); } @@ -522,80 +334,12 @@ static int sbus_do_settimeofday(struct timespec *tv) return 0; } -/* - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you won't notice until after reboot! - */ -static int set_rtc_mmss(unsigned long nowtime) +static int set_rtc_mmss(unsigned long secs) { - int real_seconds, real_minutes, mostek_minutes; - struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; - unsigned long flags; -#ifdef CONFIG_SUN4 - struct intersil *iregs = intersil_clock; - int temp; -#endif - - /* Not having a register set can lead to trouble. */ - if (!regs) { -#ifdef CONFIG_SUN4 - if(!iregs) - return -1; - else { - temp = iregs->clk.int_csec; - - mostek_minutes = iregs->clk.int_min; - - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - mostek_minutes) < 30) { - intersil_stop(iregs); - iregs->clk.int_sec=real_seconds; - iregs->clk.int_min=real_minutes; - intersil_start(iregs); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - mostek_minutes, real_minutes); - return -1; - } - - return 0; - } -#endif - } + struct rtc_device *rtc = rtc_class_open("rtc0"); - spin_lock_irqsave(&mostek_lock, flags); - /* Read the current RTC minutes. */ - regs->creg |= MSTK_CREG_READ; - mostek_minutes = MSTK_REG_MIN(regs); - regs->creg &= ~MSTK_CREG_READ; + if (rtc) + return rtc_set_mmss(rtc, secs); - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - mostek_minutes) < 30) { - regs->creg |= MSTK_CREG_WRITE; - MSTK_SET_REG_SEC(regs,real_seconds); - MSTK_SET_REG_MIN(regs,real_minutes); - regs->creg &= ~MSTK_CREG_WRITE; - spin_unlock_irqrestore(&mostek_lock, flags); - return 0; - } else { - spin_unlock_irqrestore(&mostek_lock, flags); - return -1; - } + return -1; } |