diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 11 | ||||
-rw-r--r-- | arch/arm/kernel/arch.c | 53 | ||||
-rw-r--r-- | arch/arm/kernel/bios32.c | 141 | ||||
-rw-r--r-- | arch/arm/kernel/bios32.h | 5 | ||||
-rw-r--r-- | arch/arm/kernel/calls.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/debug-armv.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/dec21285.c | 280 | ||||
-rw-r--r-- | arch/arm/kernel/dma-a5k.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/dma-rpc.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/ecard.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 87 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/hw-footbridge.c | 26 | ||||
-rw-r--r-- | arch/arm/kernel/hw-sa1100.c | 135 | ||||
-rw-r--r-- | arch/arm/kernel/ioport.c | 36 | ||||
-rw-r--r-- | arch/arm/kernel/irq.c | 35 | ||||
-rw-r--r-- | arch/arm/kernel/leds-ebsa110.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/leds-footbridge.c | 19 | ||||
-rw-r--r-- | arch/arm/kernel/leds-sa1100.c | 333 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 22 | ||||
-rw-r--r-- | arch/arm/kernel/semaphore.c | 75 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 24 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 34 |
25 files changed, 1022 insertions, 328 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index a129ca2f6..7662f42ef 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -17,22 +17,23 @@ O_OBJS_a5k = dma-a5k.o O_OBJS_rpc = dma-rpc.o O_OBJS_ebsa110 = dma-dummy.o O_OBJS_footbridge = dma.o dma-footbridge.o $(ISA_DMA_OBJS) hw-footbridge.o isa.o +O_OBJS_clps7500 = dma-dummy.o O_OBJS_nexuspci = dma-dummy.o -O_OBJS_sa1100 = dma-dummy.o fiq.o +O_OBJS_sa1100 = dma-dummy.o hw-sa1100.o O_OBJS_l7200 = dma-dummy.o fiq.o O_TARGET := kernel.o # Object file lists. -obj-y := arch.o $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o \ - semaphore.o setup.o signal.o sys_arm.o time.o traps.o \ - $(O_OBJS_$(MACHINE)) +obj-y := arch.o $(ENTRY_OBJ) irq.o process.o ptrace.o \ + semaphore.o setup.o signal.o sys_arm.o time.o \ + traps.o $(O_OBJS_$(MACHINE)) obj-m := obj-n := obj- := -export-objs := armksyms.o dma.o ecard.o hw-footbridge.o leds-$(MACHINE).o +export-objs := armksyms.o dma.o ecard.o hw-footbridge.o hw-sa1100.o leds-$(MACHINE).o obj-$(CONFIG_ARCH_ACORN) += dma.o ecard.o fiq.o time-acorn.o obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c index 717ba4ca9..8b67943ce 100644 --- a/arch/arm/kernel/arch.c +++ b/arch/arm/kernel/arch.c @@ -55,6 +55,7 @@ fixup_acorn(struct machine_desc *desc, struct param_struct *params, for (i = 0; i < 4; i++) { mi->bank[i].start = PHYS_OFFSET + (i << 26); + mi->bank[i].node = 0; mi->bank[i].size = params->u1.s.pages_in_bank[i] * params->u1.s.page_size; @@ -122,6 +123,17 @@ static void __init fixup_netwinder(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) { +#ifdef CONFIG_ISAPNP + extern int isapnp_disable; + + /* + * We must not use the kernels ISAPnP code + * on the NetWinder - it will reset the settings + * for the WaveArtist chip and render it inoperable. + */ + isapnp_disable = 1; +#endif + if (params->u1.s.nr_pages != 0x2000 && params->u1.s.nr_pages != 0x4000) { printk(KERN_WARNING "Warning: bad NeTTrom parameters " @@ -181,6 +193,7 @@ fixup_coebsa285(struct machine_desc *desc, struct param_struct *params, mi->nr_banks = 1; mi->bank[0].start = PHYS_OFFSET; mi->bank[0].size = boot_memory_end; + mi->bank[0].node = 0; *cmdline = boot_command_line; } @@ -197,7 +210,8 @@ MACHINE_END extern void select_sa1100_io_desc(void); #define SET_BANK(__nr,__start,__size) \ mi->bank[__nr].start = (__start), \ - mi->bank[__nr].size = (__size) + mi->bank[__nr].size = (__size), \ + mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) static void __init fixup_sa1100(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi) @@ -252,7 +266,7 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params, setup_initrd(0xc0400000, 4*1024*1024); } - else if (machine_is_thinclient()) { + else if (machine_is_thinclient() || machine_is_graphicsclient()) { SET_BANK( 0, 0xc0000000, 16*1024*1024 ); mi->nr_banks = 1; @@ -312,6 +326,12 @@ MACHINE_START(EMPEG, "empeg MP3 Car Audio Player") FIXUP(fixup_sa1100) MACHINE_END #endif +#ifdef CONFIG_SA1100_GRAPHICSCLIENT +MACHINE_START(GRAPHICSCLIENT, "ADS GraphicsClient") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END +#endif #ifdef CONFIG_SA1100_ITSY MACHINE_START(ITSY, "Compaq Itsy") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) @@ -349,6 +369,35 @@ MACHINE_START(VICTOR, "VisuAide Victor") FIXUP(fixup_sa1100) MACHINE_END #endif +#ifdef CONFIG_SA1100_XP860 +MACHINE_START(XP860, "XP860") + BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + FIXUP(fixup_sa1100) +MACHINE_END +#endif +#endif + +#ifdef CONFIG_ARCH_L7200 + +static void __init +fixup_l7200(struct machine_desc *desc, struct param_struct *params, + char **cmdline, struct meminfo *mi) +{ + mi->nr_banks = 1; + mi->bank[0].start = PHYS_OFFSET; + mi->bank[0].size = (32*1024*1024); + mi->bank[0].node = 0; + + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xf1000000), 0x00162b0d); +} + +MACHINE_START(L7200, "LinkUp Systems L7200SDB") + MAINTAINER("Steve Hill") + BOOT_MEM(0xf0000000, 0x80040000, 0xd0000000) + FIXUP(fixup_l7200) +MACHINE_END #endif #ifdef CONFIG_ARCH_EBSA110 diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 0d2e68846..2fbda24be 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -21,65 +21,94 @@ int have_isa_bridge; extern void hw_init(void); -void pcibios_report_device_errors(int warn) +void pcibios_report_status(u_int status_mask, int warn) { struct pci_dev *dev; pci_for_each_dev(dev) { u16 status; + /* + * ignore host bridge - we handle + * that separately + */ + if (dev->bus->number == 0 && dev->devfn == 0) + continue; + pci_read_config_word(dev, PCI_STATUS, &status); - if ((status & 0xf900) == 0) + status &= status_mask; + if (status == 0) continue; - pci_write_config_word(dev, PCI_STATUS, status & 0xf900); + /* clear the status errors */ + pci_write_config_word(dev, PCI_STATUS, status); if (warn) - printk(KERN_DEBUG "PCI: %02X:%02X: status %04X " - "on %s\n", dev->bus->number, dev->devfn, - status, dev->name); + printk("(%02x:%02x.%d: %04X) ", dev->bus->number, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), + status); } } /* * We don't use this to fix the device, but initialisation of it. - * It's not the correct use for this, but it works. The actions we - * take are: - * - enable only IO - * - set memory region to start at zero - * - (0x48) enable all memory requests from ISA to be channeled to PCI - * - (0x42) disable ping-pong (as per errata) - * - (0x40) enable PCI packet retry + * It's not the correct use for this, but it works. + * Note that the arbiter/ISA bridge appears to be buggy, specifically in + * the following area: + * 1. park on CPU + * 2. ISA bridge ping-pong + * 3. ISA bridge master handling of target RETRY + * + * Bug 3 is responsible for the sound DMA grinding to a halt. We now + * live with bug 2. */ static void __init pci_fixup_83c553(struct pci_dev *dev) { + /* + * Set memory region to start at address 0, and enable IO + */ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_SPACE_MEMORY); pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO); dev->resource[0].end -= dev->resource[0].start; dev->resource[0].start = 0; + /* + * All memory requests from ISA to be channelled to PCI + */ pci_write_config_byte(dev, 0x48, 0xff); - pci_write_config_byte(dev, 0x42, 0x00); + + /* + * Enable ping-pong on bus master to ISA bridge transactions. + * This improves the sound DMA substantially. The fixed + * priority arbiter also helps (see below). + */ + pci_write_config_byte(dev, 0x42, 0x01); + + /* + * Enable PCI retry + */ pci_write_config_byte(dev, 0x40, 0x22); /* - * 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. + * 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. Unfortunately, this + * may trigger yet another bug in the 553. */ - pci_write_config_byte(dev, 0x83, 0x00); + pci_write_config_byte(dev, 0x83, 0x02); /* - * Rotate priorities of each PCI request + * Make the ISA DMA request lowest priority, and disable + * rotating priorities completely. */ - pci_write_config_byte(dev, 0x80, 0xe0); - pci_write_config_byte(dev, 0x81, 0x01); + pci_write_config_byte(dev, 0x80, 0x11); + pci_write_config_byte(dev, 0x81, 0x00); /* - * Route INTA input to IRQ 11, and set - * IRQ11 to be level sensitive. + * Route INTA input to IRQ 11, and set IRQ11 to be level + * sensitive. */ pci_write_config_word(dev, 0x44, 0xb000); outb(0x08, 0x4d1); @@ -193,8 +222,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); } -/* - * Called after each bus is probed, but before its children +/** + * pcibios_fixup_bus - Called after each bus is probed, but before its children * are examined. */ void __init pcibios_fixup_bus(struct pci_bus *bus) @@ -209,6 +238,8 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) else BUG(); + busdata->max_lat = 255; + /* * Walk the devices on this bus, working out what we can * and can't support. @@ -216,6 +247,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) for (walk = walk->next; walk != &bus->devices; walk = walk->next) { struct pci_dev *dev = pci_dev_b(walk); u16 status; + u8 max_lat, min_gnt; pci_read_config_word(dev, PCI_STATUS, &status); @@ -227,6 +259,17 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) busdata->features &= ~PCI_COMMAND_FAST_BACK; /* + * If we encounter a CyberPro 2000, then we disable + * SERR and PERR reporting - this chip doesn't drive the + * parity line correctly. + */ +#if 1 /* !testing */ + if (dev->vendor == PCI_VENDOR_ID_INTERG && + dev->device == PCI_DEVICE_ID_INTERG_2000) + busdata->features &= ~(PCI_COMMAND_SERR | + PCI_COMMAND_PARITY); +#endif + /* * Calculate the maximum devsel latency. */ if (busdata->maxdevsel < (status & PCI_STATUS_DEVSEL_MASK)) @@ -240,6 +283,16 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA || dev->class >> 8 == PCI_CLASS_BRIDGE_EISA) have_isa_bridge = !0; + + /* + * Calculate the maximum latency on this bus. Note + * that we ignore any device which reports its max + * latency is the same as its use. + */ + pci_read_config_byte(dev, PCI_MAX_LAT, &max_lat); + pci_read_config_byte(dev, PCI_MIN_GNT, &min_gnt); + if (max_lat && max_lat != min_gnt && max_lat < busdata->max_lat) + busdata->max_lat = max_lat; } /* @@ -249,6 +302,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) for (walk = walk->next; walk != &bus->devices; walk = walk->next) { struct pci_dev *dev = pci_dev_b(walk); u16 cmd; + u8 min_gnt, latency; /* * architecture specific hacks. I don't really want @@ -263,11 +317,27 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) pci_write_config_dword(dev, 0x40, 0x80000000); /* - * Set latency timer to 32, and a cache line size to 32 bytes. + * Calculate this masters latency timer value. + * This is rather primitive - it does not take + * account of the number of masters in a system + * wanting to use the bus. + */ + pci_read_config_byte(dev, PCI_MIN_GNT, &min_gnt); + if (min_gnt) { + if (min_gnt > busdata->max_lat) + min_gnt = busdata->max_lat; + + latency = (int)min_gnt * 25 / 3; + } else + latency = 32; /* 1us */ + + pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); + + /* + * Set the cache line size to 32 bytes. * Also, set system error enable, parity error enable. * Disable ROM. */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32); pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8); pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -520,15 +590,6 @@ void __init pcibios_init(void) pci_assign_unassigned_resources(); pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq); pci_set_bus_ranges(); - -#ifdef CONFIG_FOOTBRIDGE - /* - * Initialise any other hardware after we've got the PCI bus - * initialised. We may need the PCI bus to talk to this other - * hardware. - */ - hw_init(); -#endif } char * __init pcibios_setup(char *str) @@ -544,10 +605,18 @@ void pcibios_align_resource(void *data, struct resource *res, unsigned long size { } +/** + * pcibios_set_master - Setup device for bus mastering. + * @dev: PCI device to be setup + */ void pcibios_set_master(struct pci_dev *dev) { } +/** + * pcibios_enable_device - Enable I/O and memory. + * @dev: PCI device to be enabled + */ int pcibios_enable_device(struct pci_dev *dev) { u16 cmd, old_cmd; diff --git a/arch/arm/kernel/bios32.h b/arch/arm/kernel/bios32.h index 525af165b..421ec6a79 100644 --- a/arch/arm/kernel/bios32.h +++ b/arch/arm/kernel/bios32.h @@ -10,6 +10,11 @@ struct arm_bus_sysdata { * Maximum devsel for this bus. */ u16 maxdevsel; + /* + * The maximum latency that devices on this + * bus can withstand. + */ + u8 max_lat; }; struct arm_pci_sysdata { diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index eec058522..0db6d0fde 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -119,7 +119,7 @@ .long SYMBOL_NAME(sys_newlstat) .long SYMBOL_NAME(sys_newfstat) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_uname */ -/* 110 */ .long SYMBOL_NAME(sys_iopl) +/* 110 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_iopl */ .long SYMBOL_NAME(sys_vhangup) .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_syscall) /* call a syscall */ diff --git a/arch/arm/kernel/debug-armv.S b/arch/arm/kernel/debug-armv.S index 8054f8756..da81b3b05 100644 --- a/arch/arm/kernel/debug-armv.S +++ b/arch/arm/kernel/debug-armv.S @@ -64,7 +64,7 @@ beq 1001b .endm -#elif defined(CONFIG_HOST_FOOTBRIDGE) || defined(CONFIG_ADDIN_FOOTBRIDGE) +#elif defined(CONFIG_FOOTBRIDGE) #ifndef CONFIG_DEBUG_DC21285_PORT /* For NetWinder debugging */ .macro addruart,rx diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index bc8a951e2..7fb43c68a 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -1,9 +1,8 @@ /* * arch/arm/kernel/dec21285.c: PCI functions for DC21285 * - * Copyright (C) 1998-1999 Russell King, Phil Blundell + * Copyright (C) 1998-2000 Russell King, Phil Blundell */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/pci.h> @@ -23,7 +22,8 @@ #define MAX_SLOTS 21 extern int setup_arm_irq(int, struct irqaction *); -extern void pcibios_report_device_errors(int warn); +extern void pcibios_report_status(u_int status_mask, int warn); +extern void register_isa_ports(unsigned int, unsigned int, unsigned int); static unsigned long dc21285_base_address(struct pci_dev *dev) @@ -145,86 +145,125 @@ static struct pci_ops dc21285_ops = { dc21285_write_config_dword, }; +static struct timer_list serr_timer; +static struct timer_list perr_timer; + +static void dc21285_enable_error(unsigned long __data) +{ + switch (__data) { + case IRQ_PCI_SERR: + del_timer(&serr_timer); + break; + + case IRQ_PCI_PERR: + del_timer(&perr_timer); + break; + } + + enable_irq(__data); +} + /* * Warn on PCI errors. */ -static void -dc21285_error(int irq, void *dev_id, struct pt_regs *regs) +static void dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs) { - static unsigned long next_warn; - unsigned long cmd = *CSR_PCICMD & 0x0000ffff; - unsigned long ctrl = (*CSR_SA110_CNTL) & 0xffffde07; - unsigned long irqstatus = *CSR_IRQ_RAWSTATUS; - int warn = time_after_eq(jiffies, next_warn); + unsigned int cmd; + unsigned int status; - if (machine_is_netwinder()) - warn = 0; + cmd = *CSR_PCICMD; + status = cmd >> 16; + cmd = cmd & 0xffff; - ctrl |= SA110_CNTL_DISCARDTIMER; + if (status & PCI_STATUS_REC_MASTER_ABORT) { + printk(KERN_DEBUG "PCI: master abort: "); + pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT, 1); + printk("\n"); - if (warn) { - next_warn = jiffies + HZ; - printk(KERN_DEBUG "PCI: "); + cmd |= PCI_STATUS_REC_MASTER_ABORT << 16; } - if (irqstatus & (1 << 31)) { - if (warn) - printk("parity error "); - cmd |= 1 << 31; - } + if (status & PCI_STATUS_REC_TARGET_ABORT) { + printk(KERN_DEBUG "PCI: target abort: "); + pcibios_report_status(PCI_STATUS_SIG_TARGET_ABORT, 1); + printk("\n"); - if (irqstatus & (1 << 30)) { - if (warn) - printk("target abort "); - cmd |= 1 << 28; + cmd |= PCI_STATUS_REC_TARGET_ABORT << 16; } - if (irqstatus & (1 << 29)) { - if (warn) - printk("master abort "); - cmd |= 1 << 29; - } + *CSR_PCICMD = cmd; +} - if (irqstatus & (1 << 28)) { - if (warn) - printk("data parity error "); - cmd |= 1 << 24; - } +static void dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct timer_list *timer = dev_id; + unsigned int cntl; - if (irqstatus & (1 << 27)) { - if (warn) - printk("discard timer expired "); - ctrl &= ~SA110_CNTL_DISCARDTIMER; - } + printk(KERN_DEBUG "PCI: system error received: "); + pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1); + printk("\n"); - if (irqstatus & (1 << 23)) { - if (warn) - printk("system error "); - ctrl |= SA110_CNTL_RXSERR; - } + cntl = *CSR_SA110_CNTL & 0xffffdf07; + *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; + + /* + * back off this interrupt + */ + disable_irq(irq); + timer->expires = jiffies + HZ; + add_timer(timer); +} - if (warn) - printk("pc=[<%08lX>]\n", instruction_pointer(regs)); +static void dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(KERN_DEBUG "PCI: discard timer expired\n"); + *CSR_SA110_CNTL &= 0xffffde07; +} + +static void dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int cmd; - pcibios_report_device_errors(warn); + printk(KERN_DEBUG "PCI: data parity error detected: "); + pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1); + printk("\n"); - *CSR_PCICMD = cmd; - *CSR_SA110_CNTL = ctrl; + cmd = *CSR_PCICMD & 0xffff; + *CSR_PCICMD = cmd | 1 << 24; } -static struct irqaction dc21285_error_action = { - dc21285_error, SA_INTERRUPT, 0, "PCI error", NULL, NULL -}; +static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct timer_list *timer = dev_id; + unsigned int cmd; + + printk(KERN_DEBUG "PCI: parity error detected: "); + pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1); + printk("\n"); + + cmd = *CSR_PCICMD & 0xffff; + *CSR_PCICMD = cmd | 1 << 31; + + /* + * back off this interrupt + */ + disable_irq(irq); + timer->expires = jiffies + HZ; + add_timer(timer); +} void __init dc21285_init(void) { - static struct resource csrmem, csrio; - struct arm_pci_sysdata sysdata; unsigned long cntl; - unsigned int mem_size, pci_cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + unsigned int mem_size; + unsigned int pci_cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; - int i; + int cfn_mode; + /* + * These registers need to be set up whether we're the + * central function or not. + */ mem_size = (unsigned int)high_memory - PAGE_OFFSET; *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000; *CSR_SDRAMBASEOFFSET = 0; @@ -233,60 +272,93 @@ void __init dc21285_init(void) *CSR_CSRBASEOFFSET = 0; *CSR_PCIADDR_EXTN = 0; -#ifdef CONFIG_HOST_FOOTBRIDGE - - csrio.flags = IORESOURCE_IO; - csrio.name = "DC21285"; - csrmem.flags = IORESOURCE_MEM; - csrmem.name = "DC21285"; - - allocate_resource(&ioport_resource, &csrio, 128, - 0xff00, 0xffff, 128, NULL, NULL); - allocate_resource(&iomem_resource, &csrmem, 128, - 0xf4000000, 0xf8000000, 128, NULL, NULL); - - /* - * Map our SDRAM at a known address in PCI space, just in case - * the firmware had other ideas. Using a nonzero base is - * necessary, since some VGA cards forcefully use PCI addresses - * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). - */ - *CSR_PCICACHELINESIZE = 0x00002008; - *CSR_PCICSRBASE = csrmem.start; - *CSR_PCICSRIOBASE = csrio.start; - *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); - *CSR_PCIROMBASE = 0; - *CSR_PCICMD = pci_cmd | + cfn_mode = __footbridge_cfn_mode(); + + printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX in " + "%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ? + "central function" : "addin"); + + if (cfn_mode) { + static struct resource csrmem, csrio; + struct arm_pci_sysdata sysdata; + int i; + + csrio.flags = IORESOURCE_IO; + csrio.name = "DC21285"; + csrmem.flags = IORESOURCE_MEM; + csrmem.name = "DC21285"; + + allocate_resource(&ioport_resource, &csrio, 128, + 0xff00, 0xffff, 128, NULL, NULL); + allocate_resource(&iomem_resource, &csrmem, 128, + 0xf4000000, 0xf8000000, 128, NULL, NULL); + + /* + * Map our SDRAM at a known address in PCI space, just in case + * the firmware had other ideas. Using a nonzero base is + * necessary, since some VGA cards forcefully use PCI addresses + * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards). + */ + *CSR_PCICACHELINESIZE = 0x00002008; + *CSR_PCICSRBASE = csrmem.start; + *CSR_PCICSRIOBASE = csrio.start; + *CSR_PCISDRAMBASE = virt_to_bus((void *)PAGE_OFFSET); + *CSR_PCIROMBASE = 0; + *CSR_PCICMD = pci_cmd | (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24); -#endif - printk(KERN_DEBUG "PCI: DC21285 footbridge, revision %02lX\n", - *CSR_CLASSREV & 0xff); + for (i = 0; i < MAX_NR_BUS; i++) { + sysdata.bus[i].features = PCI_COMMAND_FAST_BACK | + PCI_COMMAND_SERR | + PCI_COMMAND_PARITY; + sysdata.bus[i].maxdevsel = PCI_STATUS_DEVSEL_FAST; + } - for (i = 0; i < MAX_NR_BUS; i++) { - sysdata.bus[i].features = PCI_COMMAND_FAST_BACK | - PCI_COMMAND_SERR | - PCI_COMMAND_PARITY; - sysdata.bus[i].maxdevsel = PCI_STATUS_DEVSEL_FAST; + pci_scan_bus(0, &dc21285_ops, &sysdata); + + pci_cmd |= sysdata.bus[0].features; + + printk("PCI: Fast back to back transfers %sabled\n", + (sysdata.bus[0].features & PCI_COMMAND_FAST_BACK) ? + "en" : "dis"); + + /* + * Clear any existing errors - we aren't + * interested in historical data... + */ + cntl = *CSR_SA110_CNTL & 0xffffde07; + *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; + *CSR_PCICMD = pci_cmd | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24; + } else { + /* + * If we are not compiled to accept "add-in" mode, then + * we are using a constant virt_to_bus translation which + * can not hope to cater for the way the host BIOS has + * set up the machine. + */ + panic("PCI: this kernel is compiled for central " + "function mode only"); } - pci_scan_bus(0, &dc21285_ops, &sysdata); + /* + * Initialise PCI error IRQ after we've finished probing + */ + request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT, "PCI abort", NULL); + request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT, "Discard timer", NULL); + request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT, "PCI data parity", NULL); - pci_cmd |= sysdata.bus[0].features; + init_timer(&serr_timer); + init_timer(&perr_timer); - printk("Fast back to back PCI transfers %sabled\n", - (sysdata.bus[0].features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); + serr_timer.data = IRQ_PCI_SERR; + serr_timer.function = dc21285_enable_error; + perr_timer.data = IRQ_PCI_PERR; + perr_timer.function = dc21285_enable_error; - /* - * Clear any existing errors - we aren't - * interested in historical data... - */ - cntl = *CSR_SA110_CNTL & 0xffffde07; - *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR; - *CSR_PCICMD = pci_cmd | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24; + request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT, + "PCI system error", &serr_timer); + request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT, + "PCI parity error", &perr_timer); - /* - * Initialise PCI error IRQ after we've finished probing - */ - setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action); + register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0); } diff --git a/arch/arm/kernel/dma-a5k.c b/arch/arm/kernel/dma-a5k.c index 84740b6d2..d79013af2 100644 --- a/arch/arm/kernel/dma-a5k.c +++ b/arch/arm/kernel/dma-a5k.c @@ -15,7 +15,9 @@ #include "dma.h" -static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL }; +static struct fiq_handler fh = { + name: "floppydma" +}; int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id) { diff --git a/arch/arm/kernel/dma-rpc.c b/arch/arm/kernel/dma-rpc.c index ad9afac30..e1b54233b 100644 --- a/arch/arm/kernel/dma-rpc.c +++ b/arch/arm/kernel/dma-rpc.c @@ -20,7 +20,9 @@ #include "dma.h" -static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL }; +static struct fiq_handler fh = { + name: "floppydma" +}; #if 0 typedef enum { diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index c7d1da3e1..61eb422b2 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -52,6 +52,10 @@ #define oldlatch_init() #endif +#ifndef CONFIG_ARCH_RPC +#define HAVE_EXPMASK +#endif + enum req { req_readbytes, req_reset diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index bffe289ce..5d4f216b6 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -32,7 +32,7 @@ .text -#define PF_TRACESYS 0x20 +#define PT_TRACESYS 0x00000002 @ Bad Abort numbers @ ----------------- @@ -233,14 +233,12 @@ irq_prio_ebsa110: .macro irq_prio_table .endm -#elif defined(CONFIG_HOST_FOOTBRIDGE) || defined(CONFIG_ADDIN_FOOTBRIDGE) +#elif defined(CONFIG_FOOTBRIDGE) #include <asm/dec21285.h> .macro disable_fiq .endm - .equ irq_mask_pci_err_high, IRQ_MASK_PCI_ERR & 0xff000000 - .equ irq_mask_pci_err_low, IRQ_MASK_PCI_ERR & 0x00ffffff .equ dc21285_high, ARMCSR_BASE & 0xff000000 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff @@ -311,10 +309,24 @@ irq_prio_ebsa110: movne \irqnr, #IRQ_CONTX bne 1001f - tst \irqstat, #irq_mask_pci_err_high - tsteq \irqstat, #irq_mask_pci_err_low - movne \irqnr, #IRQ_PCI_ERR + tst \irqstat, #IRQ_MASK_PCI_ABORT + movne \irqnr, #IRQ_PCI_ABORT bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_SERR + movne \irqnr, #IRQ_PCI_SERR + bne 1001f + + tst \irqstat, #IRQ_MASK_DISCARD_TIMER + movne \irqnr, #IRQ_DISCARD_TIMER + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_DPERR + movne \irqnr, #IRQ_PCI_DPERR + bne 1001f + + tst \irqstat, #IRQ_MASK_PCI_PERR + movne \irqnr, #IRQ_PCI_PERR 1001: .endm @@ -389,12 +401,25 @@ ENTRY(soft_irq_mask) ldr \irqnr, [r4, #4] @ ICMR = 0xfa050004 ands \irqstat, \irqstat, \irqnr mov \irqnr, #0 - beq 1002f -1001: tst \irqstat, #1 - addeq \irqnr, \irqnr, #1 - moveq \irqstat, \irqstat, lsr #1 - beq 1001b -1002: + beq 1001f + tst \irqstat, #0xff + moveq \irqstat, \irqstat, lsr #8 + addeq \irqnr, \irqnr, #8 + tsteq \irqstat, #0xff + moveq \irqstat, \irqstat, lsr #8 + addeq \irqnr, \irqnr, #8 + tsteq \irqstat, #0xff + moveq \irqstat, \irqstat, lsr #8 + addeq \irqnr, \irqnr, #8 + tst \irqstat, #0x0f + moveq \irqstat, \irqstat, lsr #4 + addeq \irqnr, \irqnr, #4 + tst \irqstat, #0x03 + moveq \irqstat, \irqstat, lsr #2 + addeq \irqnr, \irqnr, #2 + tst \irqstat, #0x01 + addeqs \irqnr, \irqnr, #1 +1001: .endm .macro irq_prio_table @@ -441,7 +466,8 @@ ENTRY(soft_irq_mask) .macro restore_user_regs ldr r0, [sp, #S_PSR] @ Get calling cpsr - msr cpsr_c, #I_BIT | MODE_SVC @ disable IRQs + mov ip, #I_BIT | MODE_SVC + msr cpsr_c, ip @ disable IRQs msr spsr, r0 @ save in spsr_svc ldmia sp, {r0 - lr}^ @ Get calling r0 - lr mov r0, r0 @@ -592,9 +618,10 @@ __dabt_svc: sub sp, sp, #S_FRAME_SIZE bl cpu_data_abort #endif msr cpsr_c, r9 - mov r3, sp + mov r2, sp bl SYMBOL_NAME(do_DataAbort) - msr cpsr_c, #I_BIT | MODE_SVC + mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 ldr r0, [sp, #S_PSR] msr spsr, r0 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr @@ -636,7 +663,8 @@ __und_svc: sub sp, sp, #S_FRAME_SIZE mov r1, sp @ struct pt_regs *regs bl SYMBOL_NAME(do_undefinstr) -1: msr cpsr_c, #I_BIT | MODE_SVC +1: mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 ldr lr, [sp, #S_PSR] @ Get SVC cpsr msr spsr, lr ldmia sp, {r0 - pc}^ @ Restore SVC registers @@ -675,8 +703,9 @@ __dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go #else bl cpu_data_abort #endif - msr cpsr_c, #MODE_SVC @ Enable interrupts - mov r3, sp + mov r2, #MODE_SVC + msr cpsr_c, r2 @ Enable interrupts + mov r2, sp adrsvc al, lr, ret_from_sys_call b SYMBOL_NAME(do_DataAbort) @@ -720,9 +749,10 @@ call_fpe: get_current_task r10 add r10, r10, #TSS_FPESAVE @ r10 = workspace ldr pc, [r4] @ Call FP module USR entry point -fpundefinstr: mov r0, lr +fpundefinstr: mov r0, #MODE_SVC + msr cpsr_c, r0 @ Enable interrupts + mov r0, lr mov r1, sp - msr cpsr_c, #MODE_SVC @ Enable interrupts adrsvc al, lr, ret_from_sys_call b SYMBOL_NAME(do_undefinstr) @@ -736,7 +766,8 @@ __pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr alignment_trap r4, r7, __temp_abt zero_fp - msr cpsr_c, #MODE_SVC @ Enable interrupts + mov r0, #MODE_SVC + msr cpsr_c, r0 @ Enable interrupts mov r0, r5 @ address (pc) mov r1, sp @ regs bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler @@ -816,7 +847,8 @@ vector_IRQ: @ @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] @@ -856,7 +888,8 @@ vector_data: @ @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] @@ -897,7 +930,8 @@ vector_prefetch: @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode ands lr, lr, #15 ldreq lr, .LCtab_pabt @@ -924,7 +958,8 @@ vector_undefinstr: @ @ now branch to the relevent MODE handling routine @ - msr spsr_c, #I_BIT | MODE_SVC @ switch to SVC_32 mode + mov r13, #I_BIT | MODE_SVC + msr spsr_c, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 97fcfc522..b4fbfe628 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -94,9 +94,9 @@ vector_swi: save_user_regs bcs 2f get_current_task ip - ldr ip, [ip, #TSK_FLAGS] @ check for syscall tracing + ldr ip, [ip, #TSK_PTRACE] @ check for syscall tracing adr tbl, SYMBOL_NAME(sys_call_table) - tst ip, #PF_TRACESYS + tst ip, #PT_TRACESYS ldreq pc, [tbl, scno, lsl #2] @ call sys routine ldr tip, [sp, #S_IP + S_OFF] @ save old IP diff --git a/arch/arm/kernel/hw-footbridge.c b/arch/arm/kernel/hw-footbridge.c index f47e169c5..08aac078e 100644 --- a/arch/arm/kernel/hw-footbridge.c +++ b/arch/arm/kernel/hw-footbridge.c @@ -662,12 +662,13 @@ static void __init cats_hw_init(void) #endif -void __init hw_init(void) +/* + * Initialise any other hardware after we've got the PCI bus + * initialised. We may need the PCI bus to talk to this other + * hardware. + */ +static int __init hw_init(void) { - extern void register_isa_ports(unsigned int, unsigned int, - unsigned int); - register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0); - #ifdef CONFIG_ARCH_NETWINDER /* * this ought to have a better home... @@ -678,7 +679,6 @@ void __init hw_init(void) */ if (machine_is_netwinder()) { unsigned long flags; - extern int isapnp_disable; wb977_init(); cpld_init(); @@ -687,21 +687,13 @@ void __init hw_init(void) spin_lock_irqsave(&gpio_lock, flags); gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS); spin_unlock_irqrestore(&gpio_lock, flags); - -#ifdef CONFIG_ISAPNP - /* - * We must not use the kernels ISAPnP code - * on the NetWinder - it will reset the settings - * for the WaveArtist chip and render it inoperable. - */ - isapnp_disable = 1; -#endif } #endif #ifdef CONFIG_ARCH_CATS if (machine_is_cats()) cats_hw_init(); #endif - - leds_event(led_start); + return 0; } + +__initcall(hw_init); diff --git a/arch/arm/kernel/hw-sa1100.c b/arch/arm/kernel/hw-sa1100.c new file mode 100644 index 000000000..539bb721b --- /dev/null +++ b/arch/arm/kernel/hw-sa1100.c @@ -0,0 +1,135 @@ +/* + * arch/arm/kernel/hw-sa1100.c + * + * SA1100-dependent machine specifics + * + * Copyright (C) 2000 Nicolas Pitre <nico@cam.org> + * + * This will certainly contain more stuff with time... like power management, + * special hardware autodetection, etc. + * + */ +#include <linux/config.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> + +#include <asm/delay.h> +#include <asm/hardware.h> + + +/* + * SA1100 GPIO edge detection for IRQs: + * IRQs are generated on Falling-Edge, Rising-Edge, or both. + * This must be called *before* the appropriate IRQ is registered. + * Use this instead of directly setting GRER/GFER. + */ + +int GPIO_IRQ_rising_edge; +int GPIO_IRQ_falling_edge; + +void set_GPIO_IRQ_edge( int gpio_mask, int edge ) +{ + if( edge & GPIO_FALLING_EDGE ) + GPIO_IRQ_falling_edge |= gpio_mask; + else + GPIO_IRQ_falling_edge &= ~gpio_mask; + if( edge & GPIO_RISING_EDGE ) + GPIO_IRQ_rising_edge |= gpio_mask; + else + GPIO_IRQ_rising_edge &= ~gpio_mask; +} + +EXPORT_SYMBOL(set_GPIO_IRQ_edge); + + +#ifdef CONFIG_SA1100_ASSABET + +unsigned long BCR_value = BCR_DB1110; +unsigned long SCR_value = SCR_INIT; +EXPORT_SYMBOL(BCR_value); +EXPORT_SYMBOL(SCR_value); + +/* + * Read System Configuration "Register" + * (taken from "Intel StrongARM SA-1110 Microprocessor Development Board + * User's Guide", section 4.4.1) + * + * This same scan is performed in arch/arm/boot/compressed/head-sa1100.S + * to set up the serial port for decompression status messages. We + * repeat it here because the kernel may not be loaded as a zImage, and + * also because it's a hassle to communicate the SCR value to the kernel + * from the decompressor. + */ + +void __init get_assabet_scr(void) +{ + unsigned long flags, scr, i; + + save_flags_cli(flags); + GPDR |= 0x3fc; /* Configure GPIO 9:2 as outputs */ + GPSR = 0x3fc; /* Write 0xFF to GPIO 9:2 */ + GPDR &= ~(0x3fc); /* Configure GPIO 9:2 as inputs */ + for(i = 100; i--; scr = GPLR); /* Read GPIO 9:2 */ + GPDR |= 0x3fc; /* restore correct pin direction */ + restore_flags(flags); + scr &= 0x3fc; /* save as system configuration byte. */ + + SCR_value = scr; +} + +#endif /* CONFIG_SA1100_ASSABET */ + + +#ifdef CONFIG_SA1111 + +void __init sa1111_init(void){ + unsigned long id=SKID; + + if((id & SKID_ID_MASK) == SKID_SA1111_ID) + printk(KERN_INFO "SA-1111 Microprocessor Companion Chip: " + "silicon revision %x, metal revision %x\n", + (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK)); + else { + printk(KERN_ERR "Could not detect SA-1111!\n"); + return; + } + + /* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: + * (SA-1110 Developer's Manual, section 9.1.2.1) + */ + GAFR |= GPIO_GPIO27; + GPDR |= GPIO_GPIO27; + TUCR = TUCR_3_6864MHz; + + /* Now, set up the PLL and RCLK in the SA-1111: */ + SKCR = SKCR_PLL_BYPASS | SKCR_RDYEN | SKCR_OE_EN; + udelay(100); + SKCR = SKCR_PLL_BYPASS | SKCR_RCLKEN | SKCR_RDYEN | SKCR_OE_EN; + + /* SA-1111 Register Access Bus should now be available. Clocks for + * any other SA-1111 functional blocks must be enabled separately + * using the SKPCR. + */ +} + +#endif + + +static void __init hw_sa1100_init(void) +{ + if( machine_is_assabet() ){ + if(machine_has_neponset()){ +#ifdef CONFIG_ASSABET_NEPONSET + LEDS = WHOAMI; + sa1111_init(); +#else + printk( "Warning: Neponset detected but full support " + "hasn't been configured in the kernel\n" ); +#endif + } + } +} + +module_init(hw_sa1100_init); diff --git a/arch/arm/kernel/ioport.c b/arch/arm/kernel/ioport.c deleted file mode 100644 index 07a52ba8e..000000000 --- a/arch/arm/kernel/ioport.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * linux/arch/arm/kernel/ioport.c - * - * IO permission support for ARM. - */ - -#include <linux/config.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/ioport.h> -#include <linux/mm.h> - -#include <asm/pgtable.h> -#include <asm/uaccess.h> - -#ifdef CONFIG_CPU_32 -asmlinkage int sys_iopl(unsigned long turn_on) -{ - if (turn_on && !capable(CAP_SYS_RAWIO)) - return -EPERM; - - /* - * We only support an on_off approach - */ - modify_domain(DOMAIN_IO, turn_on ? DOMAIN_MANAGER : DOMAIN_CLIENT); - - return 0; -} -#else -asmlinkage int sys_iopl(unsigned long turn_on) -{ - return -ENOSYS; -} -#endif diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 1b26ced94..7a761b7c6 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -15,7 +15,7 @@ * IRQ's are in fact implemented a bit like signal handlers for the kernel. * Naturally it's not a 1:1 relation, but there are similarities. */ -#include <linux/config.h> /* for CONFIG_DEBUG_ERRORS */ +#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/kernel_stat.h> @@ -33,13 +33,6 @@ #include <asm/io.h> #include <asm/system.h> -#ifndef SMP -#define irq_enter(cpu, irq) (++local_irq_count[cpu]) -#define irq_exit(cpu, irq) (--local_irq_count[cpu]) -#else -#error SMP not supported -#endif - #ifndef cliIF #define cliIF() #endif @@ -85,6 +78,7 @@ struct irqdesc { }; static struct irqdesc irq_desc[NR_IRQS]; +static volatile unsigned long irq_err_count; /* * Get architecture specific interrupt handlers @@ -133,8 +127,8 @@ int get_irq_list(char *buf) action = irq_desc[i].action; if (!action) continue; - p += sprintf(p, "%3d: %10u %s", - i, kstat_irqs(i), action->name); + p += sprintf(p, "%3d: %10u ", i, kstat_irqs(i)); + p += sprintf(p, " %s", action->name); for (action = action->next; action; action = action->next) { p += sprintf(p, ", %s", action->name); } @@ -144,6 +138,7 @@ int get_irq_list(char *buf) #ifdef CONFIG_ARCH_ACORN p += get_fiq_list(p); #endif + p += sprintf(p, "Err: %10lu\n", irq_err_count); return p - buf; } @@ -181,10 +176,17 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) { struct irqdesc * desc; struct irqaction * action; - int status, cpu; + int cpu; irq = fixup_irq(irq); + /* + * Some hardware gives randomly wrong interrupts. Rather + * than crashing, do something sensible. + */ + if (irq >= NR_IRQS) + goto bad_irq; + desc = irq_desc + irq; spin_lock(&irq_controller_lock); @@ -197,10 +199,11 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) desc->triggered = 1; /* Return with this interrupt masked if no action */ - status = 0; action = desc->action; if (action) { + int status = 0; + if (desc->nomask) { spin_lock(&irq_controller_lock); desc->unmask(irq); @@ -237,9 +240,15 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) if (softirq_state[cpu].active & softirq_state[cpu].mask) do_softirq(); + return; + +bad_irq: + irq_err_count += 1; + printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); + return; } -#if defined(CONFIG_ARCH_ACORN) +#ifdef CONFIG_ARCH_ACORN void do_ecard_IRQ(int irq, struct pt_regs *regs) { struct irqdesc * desc; diff --git a/arch/arm/kernel/leds-ebsa110.c b/arch/arm/kernel/leds-ebsa110.c index eb286347b..7b2c886ef 100644 --- a/arch/arm/kernel/leds-ebsa110.c +++ b/arch/arm/kernel/leds-ebsa110.c @@ -13,7 +13,7 @@ #include <asm/leds.h> #include <asm/system.h> -void ebsa110_leds_event(led_event_t ledevt) +static void ebsa110_leds_event(led_event_t ledevt) { unsigned long flags; diff --git a/arch/arm/kernel/leds-footbridge.c b/arch/arm/kernel/leds-footbridge.c index 05f232f57..4fa2237eb 100644 --- a/arch/arm/kernel/leds-footbridge.c +++ b/arch/arm/kernel/leds-footbridge.c @@ -46,7 +46,7 @@ static void ebsa285_leds_event(led_event_t evt) switch (evt) { case led_start: hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN; -#ifndef CONFIG_LEDS_IDLE +#ifndef CONFIG_LEDS_CPU hw_led_state |= XBUS_LED_AMBER; #endif led_state |= LED_STATE_ENABLED; @@ -223,11 +223,12 @@ static void dummy_leds_event(led_event_t evt) { } -static void __init -init_leds_event(led_event_t evt) -{ - leds_event = dummy_leds_event; +void (*leds_event)(led_event_t) = dummy_leds_event; + +EXPORT_SYMBOL(leds_event); +static int __init leds_init(void) +{ #ifdef CONFIG_FOOTBRIDGE if (machine_is_ebsa285() || machine_is_co285()) leds_event = ebsa285_leds_event; @@ -237,9 +238,9 @@ init_leds_event(led_event_t evt) leds_event = netwinder_leds_event; #endif - leds_event(evt); -} + leds_event(led_start); -void (*leds_event)(led_event_t) = init_leds_event; + return 0; +} -EXPORT_SYMBOL(leds_event); +__initcall(leds_init); diff --git a/arch/arm/kernel/leds-sa1100.c b/arch/arm/kernel/leds-sa1100.c new file mode 100644 index 000000000..ef6918d7c --- /dev/null +++ b/arch/arm/kernel/leds-sa1100.c @@ -0,0 +1,333 @@ +/* + * linux/arch/arm/kernel/leds-sa1100.c + * + * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu> + * + * Original (leds-footbridge.c) by Russell King + * + * Added Brutus LEDs support + * Nicolas Pitre, Mar 19, 2000 + * + * Added LART LED support + * Erik Mouw (J.A.K.Mouw@its.tudelft.nl), April 21, 2000 + * + * + * Assabet uses the LEDs as follows: + * - Green - toggles state every 50 timer interrupts + * - Red - on if system is not idle + * + * Brutus uses the LEDs as follows: + * - D3 (Green, GPIO9) - toggles state every 50 timer interrupts + * - D17 (Red, GPIO20) - on if system is not idle + * - D4 (Green, GPIO8) - misc function + * + * LART uses the LED as follows: + * - GPIO23 is the LED, on if system is not idle + * You can use both CONFIG_LEDS_CPU and CONFIG_LEDS_TIMER at the same + * time, but in that case the timer events will still dictate the + * pace of the LED. + * + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/spinlock.h> + +#include <asm/hardware.h> +#include <asm/leds.h> +#include <asm/system.h> + + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +static unsigned int led_state; +static unsigned int hw_led_state; + + +#ifdef CONFIG_SA1100_ASSABET + +#define BCR_LED_MASK (BCR_LED_GREEN | BCR_LED_RED) + +static void assabet_leds_event(led_event_t evt) +{ + unsigned long flags; + + save_flags_cli(flags); + + switch (evt) { + case led_start: + hw_led_state = BCR_LED_RED | BCR_LED_GREEN; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = BCR_LED_RED | BCR_LED_GREEN; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = BCR_LED_RED | BCR_LED_GREEN; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= BCR_LED_GREEN; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= BCR_LED_RED; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~BCR_LED_RED; + break; +#endif + + case led_green_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~BCR_LED_GREEN; + break; + + case led_green_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= BCR_LED_GREEN; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~BCR_LED_RED; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= BCR_LED_RED; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) + BCR = BCR_value = (BCR_value & ~BCR_LED_MASK) | hw_led_state; + + restore_flags(flags); +} + +#endif /* CONFIG_SA1100_ASSABET */ + +#ifdef CONFIG_SA1100_BRUTUS + +#define LED_D3 GPIO_GPIO(9) +#define LED_D4 GPIO_GPIO(8) +#define LED_D17 GPIO_GPIO(20) +#define LED_MASK (LED_D3|LED_D4|LED_D17) + +static void brutus_leds_event(led_event_t evt) +{ + unsigned long flags; + + save_flags_cli(flags); + + switch (evt) { + case led_start: + hw_led_state = LED_MASK; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= LED_D3; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= LED_D17; + break; + + case led_idle_end: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~LED_D17; + break; +#endif + + case led_green_on: + hw_led_state &= ~LED_D4; + break; + + case led_green_off: + hw_led_state |= LED_D4; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~LED_D17; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= LED_D17; + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) { + GPSR = hw_led_state; + GPCR = hw_led_state ^ LED_MASK; + } + + restore_flags(flags); +} + +#endif /* CONFIG_SA1100_BRUTUS */ + +#ifdef CONFIG_SA1100_LART + +#define LED_23 GPIO_GPIO23 +#define LED_MASK (LED_23) + + +static void lart_leds_event(led_event_t evt) +{ + unsigned long flags; + + save_flags_cli(flags); + + switch(evt) { + case led_start: + hw_led_state = LED_MASK; + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = LED_MASK; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state ^= LED_23; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + /* The LART people like the LED to be off when the + system is idle... */ + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state &= ~LED_23; + break; + + case led_idle_end: + /* ... and on if the system is not idle */ + if (!(led_state & LED_STATE_CLAIMED)) + hw_led_state |= LED_23; + break; +#endif + + case led_red_on: + if (led_state & LED_STATE_CLAIMED) + hw_led_state &= ~LED_23; + break; + + case led_red_off: + if (led_state & LED_STATE_CLAIMED) + hw_led_state |= LED_23; + break; + + default: + break; + } + + /* Now set the GPIO state, or nothing will happen at all */ + if (led_state & LED_STATE_ENABLED) { + GPSR = hw_led_state; + GPCR = hw_led_state ^ LED_MASK; + } + + restore_flags(flags); +} + +#endif /* CONFIG_SA1100_LART */ + +static void dummy_leds_event(led_event_t evt) +{ +} + +void (*leds_event)(led_event_t) = dummy_leds_event; + +EXPORT_SYMBOL(leds_event); + +static int __init +sa1100_leds_init(void) +{ +#ifdef CONFIG_SA1100_ASSABET + if (machine_is_assabet()) + leds_event = assabet_leds_event; +#endif +#ifdef CONFIG_SA1100_BRUTUS + if (machine_is_brutus()) + leds_event = brutus_leds_event; +#endif +#ifdef CONFIG_SA1100_LART + if (machine_is_lart()) + leds_event = lart_leds_event; +#endif + + leds_event(led_start); + return 0; +} + +__initcall(sa1100_leds_init); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index c7ace10b5..40b3b9e72 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -353,10 +353,12 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) pid_t __ret; __asm__ __volatile__( - "mov r0, %1 @ kernel_thread sys_clone\n" -" mov r1, #0\n" - __syscall(clone)"\n" -" mov %0, r0" + "mov r0, %1 @ kernel_thread sys_clone + mov r1, #0 + "__syscall(clone)" + teq r0, #0 @ if we are the child + moveq fp, #0 @ ensure that fp is zero + mov %0, r0" : "=r" (__ret) : "Ir" (flags | CLONE_VM) : "r0", "r1"); if (__ret == 0) diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 0ace4c898..1684c5f5f 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -393,10 +393,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EPERM; if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) goto out; /* set the ptrace bit in the process flags. */ - current->flags |= PF_PTRACED; + current->ptrace |= PT_PTRACED; ret = 0; goto out; } @@ -419,9 +419,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out; /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) + if (child->ptrace & PT_PTRACED) goto out; - child->flags |= PF_PTRACED; + child->ptrace |= PT_PTRACED; if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; @@ -432,7 +432,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) goto out; } ret = -ESRCH; - if (!(child->flags & PF_PTRACED)) + if (!(child->ptrace & PT_PTRACED)) goto out; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) @@ -486,9 +486,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if ((unsigned long) data > _NSIG) goto out; if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; + child->ptrace |= PT_TRACESYS; else - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; wake_up_process (child); /* make sure single-step breakpoint is gone. */ @@ -515,7 +515,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) if ((unsigned long) data > _NSIG) goto out; child->thread.debug.nsaved = -1; - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; wake_up_process(child); child->exit_code = data; /* give it a chance to run. */ @@ -568,7 +568,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); wake_up_process (child); child->exit_code = data; REMOVE_LINKS(child); @@ -590,8 +590,8 @@ out: asmlinkage void syscall_trace(void) { - if ((current->flags & (PF_PTRACED|PF_TRACESYS)) - != (PF_PTRACED|PF_TRACESYS)) + if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) + != (PT_PTRACED|PT_TRACESYS)) return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index a2ec71526..93a370f2d 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -290,68 +290,95 @@ struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem) * need to convert that sequence back into the C sequence when * there is contention on the semaphore. * - * r0 contains the semaphore pointer on entry. Save the C-clobbered - * registers (r0 to r3, ip and lr) except r0 in the cases where it - * is used as a return value.. + * ip contains the semaphore pointer on entry. Save the C-clobbered + * registers (r0 to r3 and lr), but not ip, as we use it as a return + * value in some cases.. */ asm(" .section .text.lock, \"ax\" .align 5 .globl __down_failed __down_failed: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __down - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __down_interruptible_failed __down_interruptible_failed: - stmfd sp!, {r1 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __down_interruptible - ldmfd sp!, {r1 - r3, ip, pc} + mov ip, r0 + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __down_trylock_failed __down_trylock_failed: - stmfd sp!, {r1 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __down_trylock - ldmfd sp!, {r1 - r3, ip, pc} + mov ip, r0 + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __up_wakeup __up_wakeup: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bl __up - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} .align 5 .globl __down_read_failed __down_read_failed: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bcc 1f - bl down_read_failed_biased - ldmfd sp!, {r0 - r3, ip, pc} -1: bl down_read_failed - /***/ +1: bl down_read_failed_biased + ldmfd sp!, {r0 - r3, pc} +2: bl down_read_failed + mrs r1, cpsr + orr r2, r1, #128 + msr cpsr_c, r2 + ldr r3, [r0] + subs r3, r3, #1 + str r3, [r0] + msr cpsr_c, r1 + ldmplfd sp!, {r0 - r3, pc} + bcc 2b + b 1b .align 5 .globl __down_write_failed __down_write_failed: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip bcc 1f - bl down_write_failed_biased - ldmfd sp!, {r0 - r3, ip, pc} -1: bl down_write_failed - /***/ +1: bl down_write_failed_biased + ldmfd sp!, {r0 - r3, pc} +2: bl down_write_failed + mrs r1, cpsr + orr r2, r1, #128 + msr cpsr_c, r2 + ldr r3, [r0] + subs r3, r3, #"RW_LOCK_BIAS_STR" + str r3, [r0] + msr cpsr_c, r1 + ldmeqfd sp!, {r0 - r3, pc} + bcc 2b + b 1b .align 5 .globl __rwsem_wake __rwsem_wake: - stmfd sp!, {r0 - r3, ip, lr} + stmfd sp!, {r0 - r3, lr} + mov r0, ip beq 1f bl rwsem_wake_readers - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} 1: bl rwsem_wake_writer - ldmfd sp!, {r0 - r3, ip, pc} + ldmfd sp!, {r0 - r3, pc} .previous "); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index ec67dcbd0..1f4295540 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -124,11 +124,11 @@ static void __init setup_processor(void) #ifdef MULTI_CPU processor = *list->proc; +#endif printk("Processor: %s %s revision %d\n", proc_info.manufacturer, proc_info.cpu_name, (int)processor_id & 15); -#endif sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS); sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS); @@ -164,24 +164,6 @@ static struct machine_desc * __init setup_architecture(unsigned int nr) return list; } -static unsigned long __init memparse(char *ptr, char **retptr) -{ - unsigned long ret = simple_strtoul(ptr, retptr, 0); - - switch (**retptr) { - case 'M': - case 'm': - ret <<= 10; - case 'K': - case 'k': - ret <<= 10; - (*retptr)++; - default: - break; - } - return ret; -} - /* * Initial parsing of the command line. We need to pick out the * memory size. We look for mem=size@start, where start and size @@ -217,6 +199,7 @@ parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from) mi->bank[mi->nr_banks].start = start; mi->bank[mi->nr_banks].size = size; + mi->bank[mi->nr_banks].node = 0; mi->nr_banks += 1; } c = *from++; @@ -378,6 +361,7 @@ void __init setup_arch(char **cmdline_p) if (meminfo.nr_banks == 0) { meminfo.nr_banks = 1; meminfo.bank[0].start = PHYS_OFFSET; + meminfo.bank[0].node = 0; if (params) meminfo.bank[0].size = params->u1.s.nr_pages << PAGE_SHIFT; else @@ -393,8 +377,8 @@ void __init setup_arch(char **cmdline_p) saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; parse_cmdline(&meminfo, cmdline_p, from); bootmem_init(&meminfo); - request_standard_resources(&meminfo, mdesc); paging_init(&meminfo); + request_standard_resources(&meminfo, mdesc); #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 15f8fb4cb..431dd96c1 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -512,7 +512,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index c79b323a9..bdb725551 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -154,21 +154,29 @@ static inline void do_set_rtc(void) static void do_leds(void) { - static unsigned int count = 50; - static int last_pid; - - if (current->pid != last_pid) { - last_pid = current->pid; - if (last_pid) - leds_event(led_idle_end); - else - leds_event(led_idle_start); +#ifdef CONFIG_LEDS_CPU + { + static int last_pid; + + if (current->pid != last_pid) { + last_pid = current->pid; + if (last_pid) + leds_event(led_idle_end); + else + leds_event(led_idle_start); + } } - - if (--count == 0) { - count = 50; - leds_event(led_timer); +#endif +#ifdef CONFIG_LEDS_TIMER + { + static unsigned int count = 50; + + if (--count == 0) { + count = 50; + leds_event(led_timer); + } } +#endif } #else #define do_leds() |