diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/arch.c | 496 | ||||
-rw-r--r-- | arch/arm/kernel/arch.h | 58 | ||||
-rw-r--r-- | arch/arm/kernel/armksyms.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/arthur.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/bios32.c | 55 | ||||
-rw-r--r-- | arch/arm/kernel/debug-armv.S | 13 | ||||
-rw-r--r-- | arch/arm/kernel/dec21285.c | 37 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/head-armv.S | 165 | ||||
-rw-r--r-- | arch/arm/kernel/irq.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 145 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 45 |
12 files changed, 476 insertions, 553 deletions
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c index e9cca7748..717ba4ca9 100644 --- a/arch/arm/kernel/arch.c +++ b/arch/arm/kernel/arch.c @@ -1,45 +1,39 @@ /* * linux/arch/arm/kernel/arch.c * - * Architecture specifics + * Architecture specific fixups. This is where any + * parameters in the params struct are fixed up, or + * any additional architecture specific information + * is pulled from the params struct. */ #include <linux/config.h> #include <linux/tty.h> #include <linux/init.h> +#include <asm/dec21285.h> #include <asm/elf.h> #include <asm/setup.h> #include <asm/system.h> #include "arch.h" -extern unsigned int system_rev; -extern unsigned int system_serial_low; -extern unsigned int system_serial_high; - unsigned int vram_size; -#ifdef CONFIG_ARCH_ACORN -unsigned int memc_ctrl_reg; -unsigned int number_mfm_drives; -#endif extern void setup_initrd(unsigned int start, unsigned int size); extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz); -/* - * Architecture specific fixups. This is where any - * parameters in the params struct are fixed up, or - * any additional architecture specific information - * is pulled from the params struct. - */ +#ifdef CONFIG_ARCH_ACORN + +unsigned int memc_ctrl_reg; +unsigned int number_mfm_drives; + static void __init fixup_acorn(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { -#ifdef CONFIG_ARCH_ACORN - int i; - if (machine_is_riscpc()) { + int i; + /* * RiscPC can't handle half-word loads and stores */ @@ -69,9 +63,36 @@ fixup_acorn(struct machine_desc *desc, struct param_struct *params, } memc_ctrl_reg = params->u1.s.memc_control_reg; number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; -#endif } +#ifdef CONFIG_ARCH_RPC +MACHINE_START(RISCPC, "Acorn-RiscPC") + MAINTAINER("Russell King") + BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) + BOOT_PARAMS(0x10000100) + DISABLE_PARPORT(0) + DISABLE_PARPORT(1) + FIXUP(fixup_acorn) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_ARC +MACHINE_START(ARCHIMEDES, "Acorn-Archimedes") + MAINTAINER("Dave Gilbert") + BOOT_PARAMS(0x0207c000) + FIXUP(fixup_acorn) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_A5K +MACHINE_START(A5K, "Acorn-A5000") + MAINTAINER("Russell King") + BOOT_PARAMS(0x0207c000) + FIXUP(fixup_acorn) +MACHINE_END +#endif +#endif + +#ifdef CONFIG_ARCH_EBSA285 + static void __init fixup_ebsa285(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) @@ -82,6 +103,16 @@ fixup_ebsa285(struct machine_desc *desc, struct param_struct *params, ORIG_VIDEO_LINES = params->u1.s.video_num_rows; } +MACHINE_START(EBSA285, "EBSA285") + MAINTAINER("Russell King") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) + VIDEO(0x000a0000, 0x000bffff) + FIXUP(fixup_ebsa285) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_NETWINDER /* * Older NeTTroms either do not provide a parameters * page, or they don't supply correct information in @@ -105,6 +136,18 @@ fixup_netwinder(struct machine_desc *desc, struct param_struct *params, } } +MACHINE_START(NETWINDER, "Rebel-NetWinder") + MAINTAINER("Russell King/Rebel.com") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) + VIDEO(0x000a0000, 0x000bffff) + DISABLE_PARPORT(0) + DISABLE_PARPORT(2) + FIXUP(fixup_netwinder) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_CATS /* * CATS uses soft-reboot by default, since * hard reboots fail on early boards. @@ -118,11 +161,20 @@ fixup_cats(struct machine_desc *desc, struct param_struct *params, ORIG_Y = 24; } +MACHINE_START(CATS, "Chalice-CATS") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + SOFT_REBOOT + FIXUP(fixup_cats) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_CO285 + static void __init fixup_coebsa285(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { -#if 0 extern unsigned long boot_memory_end; extern char boot_command_line[]; @@ -131,242 +183,228 @@ fixup_coebsa285(struct machine_desc *desc, struct param_struct *params, mi->bank[0].size = boot_memory_end; *cmdline = boot_command_line; -#endif } +MACHINE_START(CO285, "co-EBSA285") + MAINTAINER("Mark van Doesburg") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0x7cf00000) + FIXUP(fixup_coebsa285) +MACHINE_END +#endif + +#ifdef CONFIG_ARCH_SA1100 + +extern void select_sa1100_io_desc(void); +#define SET_BANK(__nr,__start,__size) \ + mi->bank[__nr].start = (__start), \ + mi->bank[__nr].size = (__size) static void __init fixup_sa1100(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { -#ifdef CONFIG_ARCH_SA1100 - int i; - extern struct mem_desc { - unsigned long phys_start; - unsigned long length; - } mem_desc[]; - extern unsigned int mem_desc_size; - - for( i = 0; i < mem_desc_size; i++ ) { - if( i >= NR_BANKS ) { - printk( __FUNCTION__ - ": mem_desc too large for meminfo structure\n"); - break; - } - mi->bank[i].start = mem_desc[i].phys_start; - mi->bank[i].size = mem_desc[i].length; + select_sa1100_io_desc(); + + if (machine_is_assabet()) { + SET_BANK( 0, 0xc0000000, 32*1024*1024 ); + mi->nr_banks = 1; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( 0xc0800000, 3*1024*1024 ); } - mi->nr_banks = i; - -#if defined(CONFIG_SA1100_BRUTUS) - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 ); -#elif defined(CONFIG_SA1100_EMPEG) - ROOT_DEV = MKDEV( 3, 1 ); /* /dev/hda1 */ - setup_ramdisk( 1, 0, 0, 4096 ); - setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); -#elif defined(CONFIG_SA1100_THINCLIENT) - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk( 1, 0, 0, 8192 ); - setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); -#elif defined(CONFIG_SA1100_TIFON) - ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0); - setup_ramdisk(1, 0, 0, 4096); - setup_initrd( 0xd0000000 + 0x1100004, 0x140000 ); -#elif defined(CONFIG_SA1100_VICTOR) - ROOT_DEV = MKDEV( 60, 2 ); - - /* Get command line parameters passed from the loader (if any) */ - if( *((char*)0xc0000000) ) - strcpy( default_command_line, ((char *)0xc0000000) ); - - /* power off if any problem */ - strcat( default_command_line, " panic=1" ); -#elif defined(CONFIG_SA1100_LART) - ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); - setup_ramdisk(1, 0, 0, 8192); - setup_initrd(0xc0400000, 0x00400000); -#endif -#endif -} -#define NO_PARAMS 0 -#define NO_VIDEO 0, 0 + else if (machine_is_brutus()) { + SET_BANK( 0, 0xc0000000, 4*1024*1024 ); + SET_BANK( 1, 0xc8000000, 4*1024*1024 ); + SET_BANK( 2, 0xd0000000, 4*1024*1024 ); + SET_BANK( 3, 0xd8000000, 4*1024*1024 ); + mi->nr_banks = 4; -/* - * This is the list of all architectures supported by - * this kernel. This should be integrated with the list - * in head-armv.S. - */ -static struct machine_desc machine_desc[] __attribute__ ((__section__ (".arch.info"))) = { -#ifdef CONFIG_ARCH_EBSA110 - { - MACH_TYPE_EBSA110, - "EBSA110", /* RMK */ - 0x00000400, - NO_VIDEO, - 1, 0, 1, 0, 1, - NULL - }, + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 ); + } + + else if (machine_is_empeg()) { + SET_BANK( 0, 0xc0000000, 4*1024*1024 ); + SET_BANK( 1, 0xc8000000, 4*1024*1024 ); + mi->nr_banks = 2; + + ROOT_DEV = MKDEV( 3, 1 ); /* /dev/hda1 */ + setup_ramdisk( 1, 0, 0, 4096 ); + setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); + } + + else if (machine_is_lart()) { + /* + * Note that LART is a special case - it doesn't use physical + * address line A23 on the DRAM, so we effectively have 4 * 8MB + * in two SA1100 banks. + */ + SET_BANK( 0, 0xc0000000, 8*1024*1024 ); + SET_BANK( 1, 0xc1000000, 8*1024*1024 ); + SET_BANK( 2, 0xc8000000, 8*1024*1024 ); + SET_BANK( 3, 0xc9000000, 8*1024*1024 ); + mi->nr_banks = 4; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk(1, 0, 0, 8192); + setup_initrd(0xc0400000, 4*1024*1024); + } + + else if (machine_is_thinclient()) { + SET_BANK( 0, 0xc0000000, 16*1024*1024 ); + mi->nr_banks = 1; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); + } + + else if (machine_is_tifon()) { + SET_BANK( 0, 0xc0000000, 16*1024*1024 ); + SET_BANK( 1, 0xc8000000, 16*1024*1024 ); + mi->nr_banks = 2; + + ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0); + setup_ramdisk(1, 0, 0, 4096); + setup_initrd( 0xd0000000 + 0x1100004, 0x140000 ); + } + + else if (machine_is_victor()) { + SET_BANK( 0, 0xc0000000, 4*1024*1024 ); + mi->nr_banks = 1; + + ROOT_DEV = MKDEV( 60, 2 ); + + /* Get command line parameters passed from the loader (if any) */ + if( *((char*)0xc0000000) ) + strcpy( *cmdline, ((char *)0xc0000000) ); + + /* power off if any problem */ + strcat( *cmdline, " panic=1" ); + } + +} + +#ifdef CONFIG_SA1100_ASSABET +MACHINE_START(ASSABET, "Intel-Assabet") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_RPC - { - MACH_TYPE_RISCPC, - "Acorn-RiscPC", /* RMK */ - 0x10000100, - NO_VIDEO, - 1, 1, 0, 0, 0, - fixup_acorn - }, +#ifdef CONFIG_SA1100_BITSY +MACHINE_START(BITSY, "Compaq Bitsy") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_NEXUSPCI - { - MACH_TYPE_NEXUSPCI, - "FTV/PCI", /* Philip Blundell */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +#ifdef CONFIG_SA1100_BRUTUS +MACHINE_START(BRUTUS, "Intel Brutus (SA1100 eval board)") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_EBSA285 - { - MACH_TYPE_EBSA285, - "EBSA285", /* RMK */ - 0x00000100, - 0x000a0000, 0x000bffff, - 0, 0, 0, 0, 0, - fixup_ebsa285 - }, +#ifdef CONFIG_SA1100_EMPEG +MACHINE_START(EMPEG, "empeg MP3 Car Audio Player") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_NETWINDER - { - MACH_TYPE_NETWINDER, - "Rebel-NetWinder", /* RMK */ - 0x00000100, - 0x000a0000, 0x000bffff, - 1, 0, 1, 0, 0, - fixup_netwinder - }, +#ifdef CONFIG_SA1100_ITSY +MACHINE_START(ITSY, "Compaq Itsy") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100 + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_CATS - { - MACH_TYPE_CATS, - "Chalice-CATS", /* Philip Blundell */ - NO_PARAMS, - 0x000a0000, 0x000bffff, - 0, 0, 0, 0, 1, - fixup_cats - }, +#ifdef CONFIG_SA1100_LART +MACHINE_START(LART, "LART") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_TBOX - { - MACH_TYPE_TBOX, - "unknown-TBOX", /* Philip Blundell */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +#ifdef CONFIG_SA1100_PLEB +MACHINE_START(PLEB, "PLEB") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_CO285 - { - MACH_TYPE_CO285, - "co-EBSA285", /* Mark van Doesburg */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_coebsa285 - }, +#ifdef CONFIG_SA1100_THINCLIENT +MACHINE_START(THINCLIENT, "ADS ThinClient") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_CLPS7110 - { - MACH_TYPE_CLPS7110, - "CL-PS7110", /* Werner Almesberger */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +#ifdef CONFIG_SA1100_TIFON +MACHINE_START(TIFON, "Tifon") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_ARC - { - MACH_TYPE_ARCHIMEDES, - "Acorn-Archimedes",/* RMK/DAG */ - 0x0207c000, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_acorn - }, +#ifdef CONFIG_SA1100_VICTOR +MACHINE_START(VICTOR, "VisuAide Victor") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END #endif -#ifdef CONFIG_ARCH_A5K - { - MACH_TYPE_A5K, - "Acorn-A5000", /* RMK/PB */ - 0x0207c000, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_acorn - }, +#endif + +#ifdef CONFIG_ARCH_EBSA110 +MACHINE_START(EBSA110, "EBSA110") + MAINTAINER("Russell King") + BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000) + BOOT_PARAMS(0x00000400) + DISABLE_PARPORT(0) + DISABLE_PARPORT(2) + SOFT_REBOOT +MACHINE_END +#endif +#ifdef CONFIG_ARCH_NEXUSPCI +MACHINE_START(NEXUSPCI, "FTV/PCI") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x40000000, 0x10000000, 0xe0000000) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_TBOX +MACHINE_START(TBOX, "unknown-TBOX") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x80000000, 0x00400000, 0xe0000000) +MACHINE_END +#endif +#ifdef CONFIG_ARCH_CLPS7110 +MACHINE_START(CLPS7110, "CL-PS7110") + MAINTAINER("Werner Almesberger") +MACHINE_END #endif #ifdef CONFIG_ARCH_ETOILE - { - MACH_TYPE_ETOILE, - "Etoile", /* Alex de Vries */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +MACHINE_START(ETOILE, "Etoile") + MAINTAINER("Alex de Vries") +MACHINE_END #endif #ifdef CONFIG_ARCH_LACIE_NAS - { - MACH_TYPE_LACIE_NAS, - "LaCie_NAS", /* Benjamin Herrenschmidt */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +MACHINE_START(LACIE_NAS, "LaCie_NAS") + MAINTAINER("Benjamin Herrenschmidt") +MACHINE_END #endif #ifdef CONFIG_ARCH_CLPS7500 - { - MACH_TYPE_CLPS7500, - "CL-PS7500", /* Philip Blundell */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - }, +MACHINE_START(CLPS7500, "CL-PS7500") + MAINTAINER("Philip Blundell") + BOOT_MEM(0x10000000, 0x03000000, 0xe0000000) +MACHINE_END #endif #ifdef CONFIG_ARCH_SHARK - { - MACH_TYPE_SHARK, - "Shark", /* Alexander Schulz */ - NO_PARAMS, - 0x06000000, 0x06000000+0x001fffff, - 0, 0, 0, 0, 0, - NULL - }, -#endif -#ifdef CONFIG_ARCH_SA1100 - { - MACH_TYPE_SA1100, - "SA1100-based", /* Nicolas Pitre */ - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - fixup_sa1100 - }, +MACHINE_START(SHARK, "Shark") + MAINTAINER("Alexander Schulz") + BOOT_MEM(0x08000000, 0x40000000, 0xe0000000) + VIDEO(0x06000000, 0x061fffff) +MACHINE_END #endif #ifdef CONFIG_ARCH_PERSONAL_SERVER - { - MACH_TYPE_PERSONAL_SERVER, - "Compaq Personal Server", - NO_PARAMS, - NO_VIDEO, - 0, 0, 0, 0, 0, - NULL - } +MACHINE_START(PERSONAL_SERVER, "Compaq Personal Server") + MAINTAINER("Jamey Hicks / George France") + BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000) + BOOT_PARAMS(0x00000100) +MACHINE_END #endif -}; diff --git a/arch/arm/kernel/arch.h b/arch/arm/kernel/arch.h index b7635b11e..91de77772 100644 --- a/arch/arm/kernel/arch.h +++ b/arch/arm/kernel/arch.h @@ -1,9 +1,27 @@ +/* + * The size of struct machine_desc + * (for assembler code) + */ +#define SIZEOF_MACHINE_DESC 40 + +#ifndef __ASSEMBLY__ + struct machine_desc { + /* + * Note! The first four elements are used + * by assembler code in head-armv.S + */ unsigned int nr; /* architecture number */ + unsigned int phys_ram; /* start of physical ram */ + unsigned int phys_io; /* start of physical io */ + unsigned int virt_io; /* start of virtual io */ + const char *name; /* architecture name */ unsigned int param_offset; /* parameter page */ + unsigned int video_start; /* start of video RAM */ unsigned int video_end; /* end of video RAM */ + unsigned int reserve_lp0 :1; /* never has lp0 */ unsigned int reserve_lp1 :1; /* never has lp1 */ unsigned int reserve_lp2 :1; /* never has lp2 */ @@ -13,3 +31,43 @@ struct machine_desc { struct param_struct *, char **, struct meminfo *); }; + +/* + * Set of macros to define architecture features + */ +#define MACHINE_START(_type,_name) \ +const struct machine_desc __mach_desc_##_type \ + __attribute__((__section__(".arch.info"))) = { \ + nr: MACH_TYPE_##_type##, \ + name: _name, + +#define MAINTAINER(n) + +#define BOOT_MEM(_pram,_pio,_vio) \ + phys_ram: _pram, \ + phys_io: _pio, \ + virt_io: _vio, + +#define BOOT_PARAMS(_params) \ + param_offset: _params, + +#define VIDEO(_start,_end) \ + video_start: _start, \ + video_end: _end, + +#define DISABLE_PARPORT(_n) \ + reserve_lp##_n##: 1, + +#define BROKEN_HLT \ + broken_hlt: 1, + +#define SOFT_REBOOT \ + soft_reboot: 1, + +#define FIXUP(_func) \ + fixup: _func, + +#define MACHINE_END \ +}; + +#endif diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 02a4f6cf0..ffd0f1b5e 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -101,6 +101,7 @@ EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(system_rev); EXPORT_SYMBOL(system_serial_low); EXPORT_SYMBOL(system_serial_high); +EXPORT_SYMBOL(mem_fclk_21285); EXPORT_SYMBOL(__bug); EXPORT_SYMBOL(__readwrite_bug); EXPORT_SYMBOL(enable_irq); diff --git a/arch/arm/kernel/arthur.c b/arch/arm/kernel/arthur.c index 77c7d7396..8a8a5510d 100644 --- a/arch/arm/kernel/arthur.c +++ b/arch/arm/kernel/arthur.c @@ -59,11 +59,7 @@ static struct exec_domain arthur_exec_domain = { PER_RISCOS, PER_RISCOS, arthur_to_linux_signals, linux_to_arthur_signals, -#ifdef MODULE - &__this_module, /* No usage counter. */ -#else - NULL, -#endif + THIS_MODULE, NULL /* Nothing after this in the list. */ }; diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index c4ccd64e3..835bce140 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -21,7 +21,7 @@ int have_isa_bridge; extern void hw_init(void); -void pcibios_report_device_errors(void) +void pcibios_report_device_errors(int warn) { struct pci_dev *dev; @@ -34,8 +34,11 @@ void pcibios_report_device_errors(void) continue; pci_write_config_word(dev, PCI_STATUS, status & 0xf900); - printk(KERN_DEBUG "PCI: %02X:%02X: status %04X on %s\n", - dev->bus->number, dev->devfn, status, dev->name); + + if (warn) + printk(KERN_DEBUG "PCI: %02X:%02X: status %04X " + "on %s\n", dev->bus->number, dev->devfn, + status, dev->name); } } @@ -48,10 +51,6 @@ void pcibios_report_device_errors(void) * - (0x48) enable all memory requests from ISA to be channeled to PCI * - (0x42) disable ping-pong (as per errata) * - (0x40) enable PCI packet retry - * - (0x44) Route INTA to IRQ11 - * - (0x83) don't use CPU park enable, park on last master, disable GAT bit - * - (0x80) default rotating priorities - * - (0x81) rotate bank 4 */ static void __init pci_fixup_83c553(struct pci_dev *dev) { @@ -64,10 +63,26 @@ static void __init pci_fixup_83c553(struct pci_dev *dev) pci_write_config_byte(dev, 0x48, 0xff); pci_write_config_byte(dev, 0x42, 0x00); pci_write_config_byte(dev, 0x40, 0x22); - pci_write_config_word(dev, 0x44, 0xb000); - pci_write_config_byte(dev, 0x83, 0x02); + + /* + * We used to set the arbiter to "park on last master" + * (bit 1 set), but unfortunately the CyberPro does not + * park the bus. We must therefore park on CPU. + */ + pci_write_config_byte(dev, 0x83, 0x00); + + /* + * Rotate priorities of each PCI request + */ pci_write_config_byte(dev, 0x80, 0xe0); pci_write_config_byte(dev, 0x81, 0x01); + + /* + * Route INTA input to IRQ 11, and set + * IRQ11 to be level sensitive. + */ + pci_write_config_word(dev, 0x44, 0xb000); + outb(0x08, 0x4d1); } static void __init pci_fixup_unassign(struct pci_dev *dev) @@ -77,6 +92,23 @@ static void __init pci_fixup_unassign(struct pci_dev *dev) } /* + * Prevent the PCI layer from seeing the resources + * allocated to this device. These resources are + * of no consequence to the PCI layer (they are + * handled elsewhere). + */ +static void __init pci_fixup_disable(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + dev->resource[i].start = 0; + dev->resource[i].end = 0; + dev->resource[i].flags = 0; + } +} + +/* * PCI IDE controllers use non-standard I/O port * decoding, respect it. */ @@ -100,6 +132,10 @@ static void __init pci_fixup_ide_bases(struct pci_dev *dev) struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, + PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, + pci_fixup_disable + }, { + PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553 }, { @@ -339,6 +375,7 @@ static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin) case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000): case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010): + case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000): return IRQ_NETWINDER_VGA; default: diff --git a/arch/arm/kernel/debug-armv.S b/arch/arm/kernel/debug-armv.S index 5802dac70..ce7f2f94c 100644 --- a/arch/arm/kernel/debug-armv.S +++ b/arch/arm/kernel/debug-armv.S @@ -68,7 +68,10 @@ #ifndef CONFIG_DEBUG_DC21285_PORT /* For NetWinder debugging */ .macro addruart,rx - mov \rx, #0xff000000 + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x7c000000 @ physical + movne \rx, #0xff000000 @ virtual orr \rx, \rx, #0x000003f8 .endm @@ -133,7 +136,10 @@ #elif defined(CONFIG_ARCH_SA1100) .macro addruart,rx - mov \rx, #0xf8000000 + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x80000000 @ physical base address + movne \rx, #0xf8000000 @ virtual address add \rx, \rx, #0x00050000 @ Ser3 @add \rx, \rx, #0x00010000 @ Ser1 .endm @@ -171,7 +177,7 @@ ENTRY(printhex4) ENTRY(printhex2) mov r1, #2 -printhex: ldr r2, =hexbuf +printhex: adr r2, hexbuf add r3, r2, r1 mov r1, #0 strb r1, [r3] @@ -209,5 +215,4 @@ ENTRY(printch) mov r0, #0 b 1b - .bss hexbuf: .space 16 diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index 64c5861f0..bc8a951e2 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -23,18 +23,28 @@ #define MAX_SLOTS 21 extern int setup_arm_irq(int, struct irqaction *); -extern void pcibios_report_device_errors(void); +extern void pcibios_report_device_errors(int warn); static unsigned long -dc21285_base_address(struct pci_dev *dev, int where) +dc21285_base_address(struct pci_dev *dev) { unsigned long addr = 0; unsigned int devfn = dev->devfn; - if (dev->bus->number != 0) + if (dev->bus->number == 0) { + if (PCI_SLOT(devfn) == 0) + /* + * For devfn 0, point at the 21285 + */ + addr = ARMCSR_BASE; + else { + devfn -= 1 << 3; + + if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) + addr = PCICFG0_BASE | 0xc00000 | (devfn << 8); + } + } else addr = PCICFG1_BASE | (dev->bus->number << 16) | (devfn << 8); - else if (devfn < PCI_DEVFN(MAX_SLOTS, 0)) - addr = PCICFG0_BASE | 0xc00000 | (devfn << 8); return addr; } @@ -42,7 +52,7 @@ dc21285_base_address(struct pci_dev *dev, int where) static int dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); u8 v; if (addr) @@ -59,7 +69,7 @@ dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value) static int dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); u16 v; if (addr) @@ -76,7 +86,7 @@ dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value) static int dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); u32 v; if (addr) @@ -93,7 +103,7 @@ dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value) static int dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); if (addr) asm("str%?b %0, [%1, %2]" @@ -105,7 +115,7 @@ dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value) static int dc21285_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); if (addr) asm("str%?h %0, [%1, %2]" @@ -117,7 +127,7 @@ dc21285_write_config_word(struct pci_dev *dev, int where, u16 value) static int dc21285_write_config_dword(struct pci_dev *dev, int where, u32 value) { - unsigned long addr = dc21285_base_address(dev, where); + unsigned long addr = dc21285_base_address(dev); if (addr) asm("str%? %0, [%1, %2]" @@ -147,6 +157,9 @@ dc21285_error(int irq, void *dev_id, struct pt_regs *regs) unsigned long irqstatus = *CSR_IRQ_RAWSTATUS; int warn = time_after_eq(jiffies, next_warn); + if (machine_is_netwinder()) + warn = 0; + ctrl |= SA110_CNTL_DISCARDTIMER; if (warn) { @@ -193,7 +206,7 @@ dc21285_error(int irq, void *dev_id, struct pt_regs *regs) if (warn) printk("pc=[<%08lX>]\n", instruction_pointer(regs)); - pcibios_report_device_errors(); + pcibios_report_device_errors(warn); *CSR_PCICMD = cmd; *CSR_SA110_CNTL = ctrl; diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 97dfef0c1..97fcfc522 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -6,7 +6,7 @@ #define S_OFF 8 .macro get_softirq, rd -#ifdef __SMP__ +#ifdef CONFIG_SMP #error SMP not supported #else ldr \rd, __softirq_state diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S index 27a280b8b..956d9ccd2 100644 --- a/arch/arm/kernel/head-armv.S +++ b/arch/arm/kernel/head-armv.S @@ -12,6 +12,8 @@ #include <asm/hardware.h> #include <asm/dec21285.h> +#include "arch.h" + #if (TEXTADDR & 0xffff) != 0x8000 #error TEXTADDR must start at 0xXXXX8000 #endif @@ -231,6 +233,13 @@ __create_page_tables: * Generally, only serious errors cause this. */ __error: +#ifdef CONFIG_DEBUG_LL + mov r8, r0 @ preserve r0 + adr r0, err_str + bl printascii + mov r0, r8 + bl printch +#endif #ifdef CONFIG_ARCH_RPC /* * Turn the screen red on a error - RiscPC only. @@ -247,7 +256,10 @@ __error: 1: mov r0, r0 b 1b - +#ifdef CONFIG_DEBUG_LL +err_str: .asciz "\nError: " + .align +#endif /* * Read processor ID register (CP#15, CR0), and determine @@ -262,9 +274,9 @@ __error: __lookup_processor_type: adr r5, 2f ldmia r5, {r7, r9, r10} - sub r5, r5, r9 + sub r5, r5, r10 add r7, r7, r5 - add r10, r10, r5 + add r10, r9, r5 mrc p15, 0, r9, c0, c0 @ get processor id 1: ldmia r10, {r5, r6, r8} @ value, mask, mmuflags eor r5, r5, r9 @@ -277,8 +289,10 @@ __lookup_processor_type: mov pc, lr 2: .long __proc_info_end - .long 2b .long __proc_info_begin + .long 2b + .long __arch_info_begin + .long __arch_info_end /* * Lookup machine architecture @@ -290,135 +304,18 @@ __lookup_processor_type: * r7 = byte offset into page tables for IO */ __lookup_architecture_type: - cmp r1, #(__arch_types_end - __arch_types_start) / 16 - bge 1f - adr r4, __arch_types_start - add r4, r4, r1, lsl #4 - ldmia r4, {r4, r5, r6, r7} - mov r7, r7, lsr #18 + adr r4, 2b + ldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3 + sub r5, r4, r5 + add r4, r6, r5 + add r7, r7, r5 +1: ldr r5, [r4] + teq r5, r1 + beq 2f + add r4, r4, #SIZEOF_MACHINE_DESC + cmp r4, r7 + blt 1b + mov r7, #0 mov pc, lr -1: mov r7, #0 +2: ldmib r4, {r5, r6, r7} mov pc, lr - -/* - * Machine parameters. Each machine requires 4 words, which are: - * - * word0: unused - * word1: physical start address of RAM - * word2: physical start address of IO - * word3: virtual start address of IO - * - * The IO mappings entered here are used to set up mappings - * required for debugging information to be shown to the user. - * paging_init() does the real page table initialisation. - */ - .type __arch_types_start, #object - @ 0x00 - DEC EBSA110 -__arch_types_start: - .long 0 - .long 0 - .long 0xe0000000 - .long 0xe0000000 - - @ 0x01 - Acorn RiscPC - .long 0 - .long 0x10000000 - .long 0x03000000 - .long 0xe0000000 - - @ 0x02 - Unused - .long 0 - .long 0 - .long 0xe0000000 - .long 0xe0000000 - - @ 0x03 - NexusPCI - .long 0 - .long 0x40000000 - .long 0x10000000 - .long 0xe0000000 - - @ 0x04 - DEC EBSA285 - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE - .long 0xfe000000 - - @ 0x05 - Rebel.com NetWinder - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE - .long 0xfe000000 - - @ 0x06 - CATS - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE - .long 0xfe000000 - - @ 0x07 - tbox - .long 0 - .long 0x80000000 - .long 0x00400000 @ Uart - .long 0xe0000000 - - @ 0x08 - DEC EBSA285 as co-processor - .long 0 - .long 0 - .long DC21285_ARMCSR_BASE @ Physical I/O base address - .long 0x7cf00000 @ Virtual I/O base address - - @ 0x09 - CL-PS7110 - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0a - Acorn Archimedes - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0b - Acorn A5000 - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0c - Etoile - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0d - LaCie_NAS - .long 0 - .long 0 - .long 0 - .long 0 - - @ 0x0e - CL-PS7500 - .long 0 - .long 0x10000000 - .long 0x03000000 - .long 0xe0000000 - - @ 0x0f - Digital Shark (DNARD) - .long 0 - .long 0x08000000 - .long 0x40000000 - .long 0xe0000000 - - @ 0x10 - SA1100 - .long 0 - .long 0xc0000000 - .long 0x80000000 - .long 0xf8000000 - - /* - * Don't add anything here unless you have an - * architecture number allocated - see - * Documentation/arm/README - */ -__arch_types_end: diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 699cea4ab..1b26ced94 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -118,10 +118,8 @@ void enable_irq(unsigned int irq) cliIF(); irq_desc[irq].probing = 0; irq_desc[irq].triggered = 0; - if (!irq_desc[irq].noautoenable) { - irq_desc[irq].enabled = 1; - irq_desc[irq].unmask(irq); - } + irq_desc[irq].enabled = 1; + irq_desc[irq].unmask(irq); spin_unlock_irqrestore(&irq_controller_lock, flags); } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index f04b422b4..ec67dcbd0 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -5,15 +5,14 @@ */ #include <linux/config.h> #include <linux/kernel.h> -#include <linux/mm.h> #include <linux/stddef.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/utsname.h> #include <linux/blk.h> #include <linux/console.h> -#include <linux/init.h> #include <linux/bootmem.h> +#include <linux/init.h> #include <asm/elf.h> #include <asm/hardware.h> @@ -33,6 +32,7 @@ #endif extern void paging_init(struct meminfo *); +extern void bootmem_init(struct meminfo *); extern void reboot_setup(char *str); extern void disable_hlt(void); extern int root_mountflags; @@ -43,6 +43,7 @@ unsigned int __machine_arch_type; unsigned int system_rev; unsigned int system_serial_low; unsigned int system_serial_high; +unsigned int mem_fclk_21285 = 50000000; unsigned int elf_hwcap; #ifdef MULTI_CPU @@ -199,7 +200,8 @@ parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from) if (to != command_line) to -= 1; - /* If the user specifies memory size, we + /* + * If the user specifies memory size, we * blow away any automatically generated * size. */ @@ -256,137 +258,6 @@ void __init setup_initrd(unsigned int start, unsigned int size) #endif } -#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x)) - -#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT) -#define V_PFN_UP(x) O_PFN_UP(__pa(x)) - -#define PFN_SIZE(x) ((x) >> PAGE_SHIFT) -#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \ - (((unsigned long)(s)) & PAGE_MASK)) - -/* - * FIXME: These can be removed when Ingo's cleanup patch goes in - */ -#define free_bootmem(s,sz) free_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT) -#define reserve_bootmem(s,sz) reserve_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT) - -static unsigned int __init -find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages) -{ - unsigned int start_pfn, bank, bootmap_pfn; - - start_pfn = V_PFN_UP(&_end); - bootmap_pfn = 0; - - /* - * FIXME: We really want to avoid allocating the bootmap - * over the top of the initrd. - */ -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) { - if (__pa(initrd_end) > mi->end) { - printk ("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx) - disabling initrd\n", - __pa(initrd_end), mi->end); - initrd_start = 0; - initrd_end = 0; - } - } -#endif - - for (bank = 0; bank < mi->nr_banks; bank ++) { - unsigned int start, end; - - if (mi->bank[bank].size == 0) - continue; - - start = O_PFN_UP(mi->bank[bank].start); - end = O_PFN_DOWN(mi->bank[bank].size + - mi->bank[bank].start); - - if (end < start_pfn) - continue; - - if (start < start_pfn) - start = start_pfn; - - if (end <= start) - continue; - - if (end - start >= bootmap_pages) { - bootmap_pfn = start; - break; - } - } - - if (bootmap_pfn == 0) - BUG(); - - return bootmap_pfn; -} - -/* - * Initialise the bootmem allocator. - */ -static void __init setup_bootmem(struct meminfo *mi) -{ - unsigned int end_pfn, start_pfn, bootmap_pages, bootmap_pfn; - unsigned int i; - - /* - * Calculate the physical address of the top of memory. - */ - mi->end = 0; - for (i = 0; i < mi->nr_banks; i++) { - unsigned long end; - - if (mi->bank[i].size != 0) { - end = mi->bank[i].start + mi->bank[i].size; - if (mi->end < end) - mi->end = end; - } - } - - start_pfn = O_PFN_UP(PHYS_OFFSET); - end_pfn = O_PFN_DOWN(mi->end); - bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); - bootmap_pfn = find_bootmap_pfn(mi, bootmap_pages); - - /* - * Initialise the boot-time allocator - */ - init_bootmem_start(bootmap_pfn, start_pfn, end_pfn); - - /* - * Register all available RAM with the bootmem allocator. - */ - for (i = 0; i < mi->nr_banks; i++) - if (mi->bank[i].size) - free_bootmem(O_PFN_UP(mi->bank[i].start), - PFN_SIZE(mi->bank[i].size)); - - /* - * Register the reserved regions with bootmem - */ - reserve_bootmem(bootmap_pfn, bootmap_pages); - reserve_bootmem(V_PFN_DOWN(&_stext), PFN_RANGE(&_stext, &_end)); - -#ifdef CONFIG_CPU_32 - /* - * Reserve the page tables. These are already in use. - */ - reserve_bootmem(V_PFN_DOWN(swapper_pg_dir), - PFN_SIZE(PTRS_PER_PGD * sizeof(void *))); -#endif -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) - reserve_bootmem(V_PFN_DOWN(initrd_start), - PFN_RANGE(initrd_start, initrd_end)); -#endif -} - static void __init request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) { @@ -487,6 +358,9 @@ void __init setup_arch(char **cmdline_p) system_serial_low = params->u1.s.system_serial_low; system_serial_high = params->u1.s.system_serial_high; + if (params->u1.s.mem_fclk_21285 > 0) + mem_fclk_21285 = params->u1.s.mem_fclk_21285; + setup_ramdisk((params->u1.s.flags & FLAG_RDLOAD) == 0, (params->u1.s.flags & FLAG_RDPROMPT) == 0, params->u1.s.rd_start, @@ -518,9 +392,8 @@ void __init setup_arch(char **cmdline_p) memcpy(saved_command_line, from, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; parse_cmdline(&meminfo, cmdline_p, from); - setup_bootmem(&meminfo); + bootmem_init(&meminfo); request_standard_resources(&meminfo, mdesc); - paging_init(&meminfo); #ifdef CONFIG_VT diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 0fcad67c0..c79b323a9 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -30,6 +30,7 @@ extern int setup_arm_irq(int, struct irqaction *); extern void setup_timer(void); +extern rwlock_t xtime_lock; extern volatile unsigned long lost_ticks; /* change this if you have some constant time drift */ @@ -59,7 +60,8 @@ static unsigned long dummy_gettimeoffset(void) } /* - * hook for getting the time offset + * hook for getting the time offset. Note that it is + * always called with interrupts disabled. */ unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset; @@ -175,29 +177,33 @@ static void do_leds(void) void do_gettimeofday(struct timeval *tv) { unsigned long flags; + unsigned long usec, sec; - save_flags_cli (flags); - *tv = xtime; - tv->tv_usec += gettimeoffset(); + read_lock_irqsave(&xtime_lock, flags); + usec = gettimeoffset(); + { + unsigned long lost = lost_ticks; - /* - * xtime is atomically updated in timer_bh. lost_ticks is - * nonzero if the timer bottom half hasnt executed yet. - */ - if (lost_ticks) - tv->tv_usec += USECS_PER_JIFFY; - - restore_flags(flags); - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; + if (lost) + usec += lost * USECS_PER_JIFFY; } + sec = xtime.tv_sec; + usec += xtime.tv_usec; + read_unlock_irqrestore(&xtime_lock, flags); + + /* usec may have gone up a lot: be safe */ + while (usec >= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; } void do_settimeofday(struct timeval *tv) { - cli (); + write_lock_irq(&xtime_lock); /* This is revolting. We need to set the xtime.tv_usec * correctly. However, the value in this location is * is value at the last tick. @@ -205,8 +211,9 @@ void do_settimeofday(struct timeval *tv) * would have done, and then undo it! */ tv->tv_usec -= gettimeoffset(); + tv->tv_usec -= lost_ticks * USECS_PER_JIFFY; - if (tv->tv_usec < 0) { + while (tv->tv_usec < 0) { tv->tv_usec += 1000000; tv->tv_sec--; } @@ -216,7 +223,7 @@ void do_settimeofday(struct timeval *tv) time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - sti(); + write_unlock_irq(&xtime_lock); } static struct irqaction timer_irq = { |