diff options
Diffstat (limited to 'arch')
367 files changed, 12825 insertions, 4489 deletions
diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c index ec53c28e33d..3af21c78933 100644 --- a/arch/alpha/boot/bootp.c +++ b/arch/alpha/boot/bootp.c @@ -9,7 +9,7 @@ */ #include <linux/kernel.h> #include <linux/string.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/mm.h> #include <asm/system.h> diff --git a/arch/alpha/boot/bootpz.c b/arch/alpha/boot/bootpz.c index a6657f2cf9b..4307bde80a3 100644 --- a/arch/alpha/boot/bootpz.c +++ b/arch/alpha/boot/bootpz.c @@ -11,7 +11,7 @@ */ #include <linux/kernel.h> #include <linux/string.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/mm.h> #include <asm/system.h> diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c index 78c9b0b6eea..90ed55b662a 100644 --- a/arch/alpha/boot/main.c +++ b/arch/alpha/boot/main.c @@ -7,7 +7,7 @@ */ #include <linux/kernel.h> #include <linux/string.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/mm.h> #include <asm/system.h> diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index bd193ffd6fe..729c475d226 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -94,12 +94,12 @@ show_interrupts(struct seq_file *p, void *v) #endif seq_printf(p, " %14s", irq_desc[irq].chip->typename); seq_printf(p, " %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', + (action->flags & IRQF_DISABLED)?'+':' ', action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ", %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', + (action->flags & IRQF_DISABLED)?'+':' ', action->name); } diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c index ffa4ac543cf..ddf5cf8dcb0 100644 --- a/arch/alpha/kernel/irq_alpha.c +++ b/arch/alpha/kernel/irq_alpha.c @@ -214,7 +214,7 @@ static unsigned int rtc_startup(unsigned int irq) { return 0; } struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "timer", }; diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 01c8c8b2333..41ebf51a107 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -474,7 +474,7 @@ out: */ unsigned long -thread_saved_pc(task_t *t) +thread_saved_pc(struct task_struct *t) { unsigned long base = (unsigned long)task_stack_page(t); unsigned long fp, sp = task_thread_info(t)->pcb.ksp; diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c index 0148e095638..4ac2b328b8d 100644 --- a/arch/alpha/kernel/sys_jensen.c +++ b/arch/alpha/kernel/sys_jensen.c @@ -74,7 +74,7 @@ jensen_local_startup(unsigned int irq) * the IPL from being dropped during handler processing. */ if (irq_desc[irq].action) - irq_desc[irq].action->flags |= SA_INTERRUPT; + irq_desc[irq].action->flags |= IRQF_DISABLED; return 0; } diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c index a8bfc8c16a7..302aab38d95 100644 --- a/arch/alpha/kernel/sys_titan.c +++ b/arch/alpha/kernel/sys_titan.c @@ -279,15 +279,15 @@ titan_late_init(void) * all reported to the kernel as machine checks, so the handler * is a nop so it can be called to count the individual events. */ - request_irq(63+16, titan_intr_nop, SA_INTERRUPT, + request_irq(63+16, titan_intr_nop, IRQF_DISABLED, "CChip Error", NULL); - request_irq(62+16, titan_intr_nop, SA_INTERRUPT, + request_irq(62+16, titan_intr_nop, IRQF_DISABLED, "PChip 0 H_Error", NULL); - request_irq(61+16, titan_intr_nop, SA_INTERRUPT, + request_irq(61+16, titan_intr_nop, IRQF_DISABLED, "PChip 1 H_Error", NULL); - request_irq(60+16, titan_intr_nop, SA_INTERRUPT, + request_irq(60+16, titan_intr_nop, IRQF_DISABLED, "PChip 0 C_Error", NULL); - request_irq(59+16, titan_intr_nop, SA_INTERRUPT, + request_irq(59+16, titan_intr_nop, IRQF_DISABLED, "PChip 1 C_Error", NULL); /* @@ -348,9 +348,9 @@ privateer_init_pci(void) * Hook a couple of extra err interrupts that the * common titan code won't. */ - request_irq(53+16, titan_intr_nop, SA_INTERRUPT, + request_irq(53+16, titan_intr_nop, IRQF_DISABLED, "NMI", NULL); - request_irq(50+16, titan_intr_nop, SA_INTERRUPT, + request_irq(50+16, titan_intr_nop, IRQF_DISABLED, "Temperature Warning", NULL); /* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f123c7c9fc9..f81a62380ad 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -47,6 +47,18 @@ config MCA <file:Documentation/mca.txt> (and especially the web page given there) before attempting to build an MCA bus kernel. +config GENERIC_HARDIRQS + bool + default y + +config HARDIRQS_SW_RESEND + bool + default y + +config GENERIC_IRQ_PROBE + bool + default y + config RWSEM_GENERIC_SPINLOCK bool default y @@ -121,11 +133,11 @@ config ARCH_VERSATILE help This enables support for ARM Ltd Versatile board. -config ARCH_AT91RM9200 - bool "Atmel AT91RM9200" +config ARCH_AT91 + bool "Atmel AT91" help - Say Y here if you intend to run this kernel on an Atmel - AT91RM9200-based board. + This enables support for systems based on the Atmel AT91RM9200 + and AT91SAM9xxx processors. config ARCH_CLPS7500 bool "Cirrus CL-PS7500FE" @@ -547,7 +559,7 @@ config LEDS ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ - ARCH_AT91RM9200 + ARCH_AT91RM9200 || MACH_TRIZEPS4 help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. @@ -678,7 +690,7 @@ config XIP_PHYS_ADDR endmenu -if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP1) +if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP) menu "CPU Frequency scaling" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index a3bbaaf480b..3345c6d0fd1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -114,7 +114,7 @@ endif machine-$(CONFIG_ARCH_H720X) := h720x machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 machine-$(CONFIG_ARCH_REALVIEW) := realview - machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200 + machine-$(CONFIG_ARCH_AT91) := at91rm9200 machine-$(CONFIG_ARCH_EP93XX) := ep93xx machine-$(CONFIG_ARCH_PNX4008) := pnx4008 machine-$(CONFIG_ARCH_NETX) := netx diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index f7b5c6db30f..14a9ff9c68d 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -447,8 +447,11 @@ __common_mmu_cache_on: mov r1, #-1 mcr p15, 0, r3, c2, c0, 0 @ load page table pointer mcr p15, 0, r1, c3, c0, 0 @ load domain access control - mcr p15, 0, r0, c1, c0, 0 @ load control register - mov pc, lr + b 1f + .align 5 @ cache line aligned +1: mcr p15, 0, r0, c1, c0, 0 @ load control register + mrc p15, 0, r0, c1, c0, 0 @ and read it back to + sub pc, lr, r0, lsr #32 @ properly flush pipeline /* * All code following this line is relocatable. It is relocated by diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index c02dc8116a1..f3c1ebfdd0a 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -33,6 +33,7 @@ static void __iomem *gic_dist_base; static void __iomem *gic_cpu_base; +static DEFINE_SPINLOCK(irq_controller_lock); /* * Routines to acknowledge, disable and enable interrupts @@ -52,32 +53,45 @@ static void __iomem *gic_cpu_base; static void gic_ack_irq(unsigned int irq) { u32 mask = 1 << (irq % 32); + + spin_lock(&irq_controller_lock); writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); writel(irq, gic_cpu_base + GIC_CPU_EOI); + spin_unlock(&irq_controller_lock); } static void gic_mask_irq(unsigned int irq) { u32 mask = 1 << (irq % 32); + + spin_lock(&irq_controller_lock); writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); + spin_unlock(&irq_controller_lock); } static void gic_unmask_irq(unsigned int irq) { u32 mask = 1 << (irq % 32); + + spin_lock(&irq_controller_lock); writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4); + spin_unlock(&irq_controller_lock); } #ifdef CONFIG_SMP -static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu) +static void gic_set_cpu(unsigned int irq, cpumask_t mask_val) { void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3); unsigned int shift = (irq % 4) * 8; + unsigned int cpu = first_cpu(mask_val); u32 val; + spin_lock(&irq_controller_lock); + irq_desc[irq].cpu = cpu; val = readl(reg) & ~(0xff << shift); val |= 1 << (cpu + shift); writel(val, reg); + spin_unlock(&irq_controller_lock); } #endif @@ -86,7 +100,7 @@ static struct irqchip gic_chip = { .mask = gic_mask_irq, .unmask = gic_unmask_irq, #ifdef CONFIG_SMP - .set_cpu = gic_set_cpu, + .set_affinity = gic_set_cpu, #endif }; diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index fe06a36a213..1cdb26a47e1 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -150,7 +150,7 @@ static void sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { unsigned int stat0, stat1, i; - void __iomem *base = desc->data; + void __iomem *base = get_irq_data(irq); stat0 = sa1111_readl(base + SA1111_INTSTATCLR0); stat1 = sa1111_readl(base + SA1111_INTSTATCLR1); @@ -168,11 +168,11 @@ sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1) if (stat0 & 1) - do_edge_IRQ(i, irq_desc + i, regs); + handle_edge_irq(i, irq_desc + i, regs); for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1) if (stat1 & 1) - do_edge_IRQ(i, irq_desc + i, regs); + handle_edge_irq(i, irq_desc + i, regs); /* For level-based interrupts */ desc->chip->unmask(irq); diff --git a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c index 486add853fb..3f60dd9aca8 100644 --- a/arch/arm/common/time-acorn.c +++ b/arch/arm/common/time-acorn.c @@ -16,6 +16,7 @@ #include <linux/timex.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <asm/hardware.h> #include <asm/io.h> @@ -76,7 +77,7 @@ ioc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction ioc_timer_irq = { .name = "timer", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .handler = ioc_timer_interrupt }; diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index 9e1c1cceb73..4f3d8d37741 100644 --- a/arch/arm/configs/at91rm9200dk_defconfig +++ b/arch/arm/configs/at91rm9200dk_defconfig @@ -103,6 +103,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index 6e0805a971d..08b5dc38876 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig @@ -103,6 +103,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig index 69c39e09874..bee7813d040 100644 --- a/arch/arm/configs/ateb9200_defconfig +++ b/arch/arm/configs/ateb9200_defconfig @@ -105,6 +105,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig index 5ccd29a7c1f..8a075c8ecc6 100644 --- a/arch/arm/configs/carmeva_defconfig +++ b/arch/arm/configs/carmeva_defconfig @@ -82,6 +82,7 @@ CONFIG_OBSOLETE_MODPARM=y # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig index 94bd9932a40..3594155a813 100644 --- a/arch/arm/configs/csb337_defconfig +++ b/arch/arm/configs/csb337_defconfig @@ -103,6 +103,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig index 1519124c550..640d70c1f06 100644 --- a/arch/arm/configs/csb637_defconfig +++ b/arch/arm/configs/csb637_defconfig @@ -103,6 +103,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig index 51ded20e3f6..1db633e2c94 100644 --- a/arch/arm/configs/kafa_defconfig +++ b/arch/arm/configs/kafa_defconfig @@ -105,6 +105,7 @@ CONFIG_DEFAULT_IOSCHED="deadline" # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig index fee4f566452..45396e08719 100644 --- a/arch/arm/configs/kb9202_defconfig +++ b/arch/arm/configs/kb9202_defconfig @@ -80,6 +80,7 @@ CONFIG_KMOD=y # CONFIG_ARCH_IMX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig index ee3ecbd9002..05adb0b34e7 100644 --- a/arch/arm/configs/omap_h2_1610_defconfig +++ b/arch/arm/configs/omap_h2_1610_defconfig @@ -1,19 +1,20 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.14 -# Wed Nov 9 18:53:40 2005 +# Linux kernel version: 2.6.17 +# Thu Jun 29 15:25:18 2006 # CONFIG_ARM=y CONFIG_MMU=y -CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -29,26 +30,26 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -56,7 +57,6 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_KMOD is not set @@ -64,6 +64,7 @@ CONFIG_OBSOLETE_MODPARM=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -81,16 +82,26 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # System Type # +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91RM9200 is not set # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set # CONFIG_ARCH_IOP3XX is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set # CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set @@ -98,11 +109,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set CONFIG_ARCH_OMAP=y -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set # # TI OMAP Implementations @@ -141,6 +147,7 @@ CONFIG_ARCH_OMAP16XX=y CONFIG_MACH_OMAP_H2=y # CONFIG_MACH_OMAP_H3 is not set # CONFIG_MACH_OMAP_OSK is not set +# CONFIG_MACH_NOKIA770 is not set # CONFIG_MACH_OMAP_GENERIC is not set # @@ -177,7 +184,6 @@ CONFIG_ARM_THUMB=y # # Bus support # -CONFIG_ISA_DMA_API=y # # PCCARD (PCMCIA/CardBus) support @@ -189,6 +195,8 @@ CONFIG_ISA_DMA_API=y # CONFIG_PREEMPT=y CONFIG_NO_IDLE_HZ=y +CONFIG_HZ=128 +# CONFIG_AEABI is not set # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -249,6 +257,8 @@ CONFIG_BINFMT_AOUT=y # Power management options # CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set # CONFIG_APM is not set # @@ -259,9 +269,12 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -278,12 +291,18 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -295,6 +314,11 @@ CONFIG_TCP_CONG_BIC=y # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -312,7 +336,6 @@ CONFIG_TCP_CONG_BIC=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -333,6 +356,12 @@ CONFIG_TCP_CONG_BIC=y CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set # # Memory Technology Devices (MTD) @@ -526,6 +555,7 @@ CONFIG_SERIO_SERPORT=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -534,6 +564,7 @@ CONFIG_HW_CONSOLE=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -559,8 +590,8 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set -# CONFIG_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -572,6 +603,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # # TPM devices # +# CONFIG_TCG_TPM is not set # CONFIG_TELCLOCK is not set # @@ -580,10 +612,22 @@ CONFIG_WATCHDOG_NOWAYOUT=y # CONFIG_I2C is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set # CONFIG_HWMON_DEBUG_CHIP is not set # @@ -591,13 +635,23 @@ CONFIG_HWMON=y # # -# Multimedia Capabilities Port drivers +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers # # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -607,11 +661,13 @@ CONFIG_HWMON=y # # Graphics support # +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y # CONFIG_FB_CFB_FILLRECT is not set # CONFIG_FB_CFB_COPYAREA is not set # CONFIG_FB_CFB_IMAGEBLIT is not set # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_S1D13XXX is not set @@ -635,7 +691,6 @@ CONFIG_FONT_8x16=y # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set # CONFIG_FONT_10x18 is not set -# CONFIG_FONT_RL is not set # # Logo configuration @@ -660,16 +715,15 @@ CONFIG_SOUND=y # Open Sound System # CONFIG_SOUND_PRIME=y -# CONFIG_OBSOLETE_OSS_DRIVER is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_OSS is not set # # USB support # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set # CONFIG_USB is not set # @@ -680,17 +734,6 @@ CONFIG_USB_ARCH_HAS_OHCI=y # USB Gadget Support # # CONFIG_USB_GADGET is not set -# CONFIG_USB_GADGET_NET2280 is not set -# CONFIG_USB_GADGET_PXA2XX is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_LH7A40X is not set -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_ZERO is not set -# CONFIG_USB_ETH is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_G_SERIAL is not set # # MMC/SD Card support @@ -698,20 +741,27 @@ CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_MMC is not set # +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -741,7 +791,7 @@ CONFIG_SYSFS=y # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -843,10 +893,13 @@ CONFIG_NLS_DEFAULT="iso8859-1" # Kernel hacking # # CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set # CONFIG_DEBUG_KERNEL is not set CONFIG_LOG_BUF_SHIFT=14 CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set # CONFIG_DEBUG_USER is not set # diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig index 5401c01caef..2b4a63be03f 100644 --- a/arch/arm/configs/onearm_defconfig +++ b/arch/arm/configs/onearm_defconfig @@ -85,6 +85,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y CONFIG_ARCH_AT91RM9200=y # CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig new file mode 100644 index 00000000000..a6698dc4f6b --- /dev/null +++ b/arch/arm/configs/trizeps4_defconfig @@ -0,0 +1,1579 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17 +# Sat Jun 24 22:45:14 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_SYSCTL=y +CONFIG_AUDIT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_LOGICPD_PXA270 is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +CONFIG_MACH_TRIZEPS4=y +CONFIG_MACH_TRIZEPS4_CONXS=y +# CONFIG_MACH_TRIZEPS4_ANY is not set +CONFIG_PXA27x=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_XSCALE_PMU=y + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_PCMCIA_PXA2XX=m + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200n8" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +CONFIG_FPE_NWFPE_XP=y +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_APM=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +CONFIG_IP_NF_QUEUE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_SIGMATEL_FIR is not set +# CONFIG_PXA_FICP is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIUSB is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIBT3C is not set +# CONFIG_BT_HCIBLUECARD is not set +# CONFIG_BT_HCIBTUART is not set +# CONFIG_BT_HCIVHCI is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +CONFIG_NFTL=y +CONFIG_NFTL_RW=y +CONFIG_INFTL=y +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_NOSWAP is not set +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_LE_BYTE_SWAP=y +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x0 +CONFIG_MTD_PHYSMAP_LEN=0x4000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_TRIZEPS4 is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_SHARP_SL is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +CONFIG_MTD_DOC2001PLUS=y +CONFIG_MTD_DOCPROBE=y +CONFIG_MTD_DOCECC=y +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_DOCPROBE_ADDRESS=0 + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_H1900 is not set +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_DISKONCHIP=y +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +# CONFIG_MTD_NAND_SHARPSL is not set +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=4 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_IDE_PXA_CF=y +CONFIG_IDE_ARM=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_DM9000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_HERMES=m +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +# CONFIG_PCMCIA_SPECTRUM is not set +CONFIG_AIRO_CS=m +# CONFIG_PCMCIA_WL3501 is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_CS=m +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_TSDEV=y +CONFIG_INPUT_TSDEV_SCREEN_X=640 +CONFIG_INPUT_TSDEV_SCREEN_Y=480 +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_MOUSE_SERIAL=y +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_SA1100_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_PXA=y +CONFIG_I2C_PXA_SLAVE=y +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=m +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +CONFIG_SPI_PXA2XX=m + +# +# SPI Protocol Masters +# + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# +CONFIG_UCB1400=y +CONFIG_UCB1400_TS=y + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_IDE_DISK=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_SEQUENCER_OSS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_AC97_BUS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA ARM devices +# +CONFIG_SND_PXA2XX_PCM=y +CONFIG_SND_PXA2XX_AC97=y + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +CONFIG_USB_TOUCHSCREEN=m +# CONFIG_USB_TOUCHSCREEN_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN_PANJIT is not set +# CONFIG_USB_TOUCHSCREEN_3M is not set +# CONFIG_USB_TOUCHSCREEN_ITM is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_AT91 is not set +CONFIG_USB_GADGET_DUMMY_HCD=y +CONFIG_USB_DUMMY_HCD=y +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_PXA=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_SA1100=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS_PROC_FS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-15" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_DEBUG_USER=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +# CONFIG_SECURITY_NETWORK is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC32=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_DEC16=y diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7cffbaef064..f0c0cdb1c18 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 -obj-$(CONFIG_IWMMXT) += iwmmxt.o +obj-$(CONFIG_IWMMXT) += iwmmxt.o iwmmxt-notifier.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt ifneq ($(CONFIG_ARCH_EBSA110),y) diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 447ede5143a..cc2d58d028e 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -105,6 +105,7 @@ int main(void) BLANK(); DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list)); DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush)); - DEFINE(PROCINFO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mmu_flags)); + DEFINE(PROCINFO_MM_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mm_mmu_flags)); + DEFINE(PROCINFO_IO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_io_mmu_flags)); return 0; } diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index 68a257666d9..b9a74a741d0 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -619,7 +619,7 @@ ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg ecard_t *ec = slot_to_ecard(slot); if (ec->claimed) { - struct irqdesc *d = irqdesc + ec->irq; + struct irq_desc *d = irq_desc + ec->irq; /* * this ugly code is so that we can operate a * prioritorising system: @@ -883,7 +883,7 @@ static ssize_t ecard_show_resources(struct device *dev, struct device_attribute int i; for (i = 0; i < ECARD_NUM_RESOURCES; i++) - str += sprintf(str, "%08lx %08lx %08lx\n", + str += sprintf(str, "%08x %08x %08lx\n", ec->resource[i].start, ec->resource[i].end, ec->resource[i].flags); diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 26f197afd20..7ea5f01dfc7 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -589,9 +589,7 @@ ENTRY(__switch_to) #ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register #endif -#if defined(CONFIG_IWMMXT) - bl iwmmxt_task_switch -#elif defined(CONFIG_CPU_XSCALE) +#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra ldmib r4, {r4, r5} mar acc0, r4, r5 diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 1ec3f7faa25..e8e90346f11 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -38,6 +38,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/seq_file.h> #include <asm/cacheflush.h> diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 518b80cd87d..2242f5f7cb7 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -220,7 +220,7 @@ __create_page_tables: teq r0, r6 bne 1b - ldr r7, [r10, #PROCINFO_MMUFLAGS] @ mmuflags + ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags /* * Create identity mapping for first MB of kernel to @@ -271,8 +271,7 @@ __create_page_tables: #endif #ifdef CONFIG_DEBUG_LL - bic r7, r7, #0x0c @ turn off cacheable - @ and bufferable bits + ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags /* * Map in IO space for serial debugging. * This allows debug messages to be output diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 4d31cf8d02d..c3d4e94ef5b 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -26,6 +26,7 @@ #include <linux/signal.h> #include <linux/ioport.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/ptrace.h> #include <linux/slab.h> #include <linux/random.h> @@ -37,192 +38,18 @@ #include <linux/kallsyms.h> #include <linux/proc_fs.h> -#include <asm/irq.h> #include <asm/system.h> -#include <asm/mach/irq.h> #include <asm/mach/time.h> /* - * Maximum IRQ count. Currently, this is arbitary. However, it should - * not be set too low to prevent false triggering. Conversely, if it - * is set too high, then you could miss a stuck IRQ. - * - * Maybe we ought to set a timer and re-enable the IRQ at a later time? - */ -#define MAX_IRQ_CNT 100000 - -static int noirqdebug __read_mostly; -static volatile unsigned long irq_err_count; -static DEFINE_SPINLOCK(irq_controller_lock); -static LIST_HEAD(irq_pending); - -struct irqdesc irq_desc[NR_IRQS]; -void (*init_arch_irq)(void) __initdata = NULL; - -/* * No architecture-specific irq_finish function defined in arm/arch/irqs.h. */ #ifndef irq_finish #define irq_finish(irq) do { } while (0) #endif -/* - * Dummy mask/unmask handler - */ -void dummy_mask_unmask_irq(unsigned int irq) -{ -} - -irqreturn_t no_action(int irq, void *dev_id, struct pt_regs *regs) -{ - return IRQ_NONE; -} - -void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - irq_err_count++; - printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); -} - -static struct irqchip bad_chip = { - .ack = dummy_mask_unmask_irq, - .mask = dummy_mask_unmask_irq, - .unmask = dummy_mask_unmask_irq, -}; - -static struct irqdesc bad_irq_desc = { - .chip = &bad_chip, - .handle = do_bad_IRQ, - .pend = LIST_HEAD_INIT(bad_irq_desc.pend), - .disable_depth = 1, -}; - -#ifdef CONFIG_SMP -void synchronize_irq(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - - while (desc->running) - barrier(); -} -EXPORT_SYMBOL(synchronize_irq); - -#define smp_set_running(desc) do { desc->running = 1; } while (0) -#define smp_clear_running(desc) do { desc->running = 0; } while (0) -#else -#define smp_set_running(desc) do { } while (0) -#define smp_clear_running(desc) do { } while (0) -#endif - -/** - * disable_irq_nosync - disable an irq without waiting - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Enables and disables - * are nested. We do this lazily. - * - * This function may be called from IRQ context. - */ -void disable_irq_nosync(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - desc->disable_depth++; - list_del_init(&desc->pend); - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(disable_irq_nosync); - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Enables and disables - * are nested. This functions waits for any pending IRQ - * handlers for this interrupt to complete before returning. - * If you use this function while holding a resource the IRQ - * handler may need you will deadlock. - * - * This function may be called - with care - from IRQ context. - */ -void disable_irq(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - - disable_irq_nosync(irq); - if (desc->action) - synchronize_irq(irq); -} -EXPORT_SYMBOL(disable_irq); - -/** - * enable_irq - enable interrupt handling on an irq - * @irq: Interrupt to enable - * - * Re-enables the processing of interrupts on this IRQ line. - * Note that this may call the interrupt handler, so you may - * get unexpected results if you hold IRQs disabled. - * - * This function may be called from IRQ context. - */ -void enable_irq(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - if (unlikely(!desc->disable_depth)) { - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); - } else if (!--desc->disable_depth) { - desc->probing = 0; - desc->chip->unmask(irq); - - /* - * If the interrupt is waiting to be processed, - * try to re-run it. We can't directly run it - * from here since the caller might be in an - * interrupt-protected region. - */ - if (desc->pending && list_empty(&desc->pend)) { - desc->pending = 0; - if (!desc->chip->retrigger || - desc->chip->retrigger(irq)) - list_add(&desc->pend, &irq_pending); - } - } - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(enable_irq); - -/* - * Enable wake on selected irq - */ -void enable_irq_wake(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - if (desc->chip->set_wake) - desc->chip->set_wake(irq, 1); - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(enable_irq_wake); - -void disable_irq_wake(unsigned int irq) -{ - struct irqdesc *desc = irq_desc + irq; - unsigned long flags; - - spin_lock_irqsave(&irq_controller_lock, flags); - if (desc->chip->set_wake) - desc->chip->set_wake(irq, 0); - spin_unlock_irqrestore(&irq_controller_lock, flags); -} -EXPORT_SYMBOL(disable_irq_wake); +void (*init_arch_irq)(void) __initdata = NULL; +unsigned long irq_err_count; int show_interrupts(struct seq_file *p, void *v) { @@ -242,8 +69,8 @@ int show_interrupts(struct seq_file *p, void *v) } if (i < NR_IRQS) { - spin_lock_irqsave(&irq_controller_lock, flags); - action = irq_desc[i].action; + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; if (!action) goto unlock; @@ -256,7 +83,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); unlock: - spin_unlock_irqrestore(&irq_controller_lock, flags); + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { #ifdef CONFIG_ARCH_ACORN show_fiq_list(p, v); @@ -270,267 +97,11 @@ unlock: return 0; } -/* - * IRQ lock detection. - * - * Hopefully, this should get us out of a few locked situations. - * However, it may take a while for this to happen, since we need - * a large number if IRQs to appear in the same jiffie with the - * same instruction pointer (or within 2 instructions). - */ -static int check_irq_lock(struct irqdesc *desc, int irq, struct pt_regs *regs) -{ - unsigned long instr_ptr = instruction_pointer(regs); - - if (desc->lck_jif == jiffies && - desc->lck_pc >= instr_ptr && desc->lck_pc < instr_ptr + 8) { - desc->lck_cnt += 1; - - if (desc->lck_cnt > MAX_IRQ_CNT) { - printk(KERN_ERR "IRQ LOCK: IRQ%d is locking the system, disabled\n", irq); - return 1; - } - } else { - desc->lck_cnt = 0; - desc->lck_pc = instruction_pointer(regs); - desc->lck_jif = jiffies; - } - return 0; -} - -static void -report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int ret) -{ - static int count = 100; - struct irqaction *action; - - if (noirqdebug) - return; - - if (ret != IRQ_HANDLED && ret != IRQ_NONE) { - if (!count) - return; - count--; - printk("irq%u: bogus retval mask %x\n", irq, ret); - } else { - desc->irqs_unhandled++; - if (desc->irqs_unhandled <= 99900) - return; - desc->irqs_unhandled = 0; - printk("irq%u: nobody cared\n", irq); - } - show_regs(regs); - dump_stack(); - printk(KERN_ERR "handlers:"); - action = desc->action; - do { - printk("\n" KERN_ERR "[<%p>]", action->handler); - print_symbol(" (%s)", (unsigned long)action->handler); - action = action->next; - } while (action); - printk("\n"); -} - -static int -__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) -{ - unsigned int status; - int ret, retval = 0; - - spin_unlock(&irq_controller_lock); - -#ifdef CONFIG_NO_IDLE_HZ - if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) { - spin_lock(&system_timer->dyn_tick->lock); - if (system_timer->dyn_tick->state & DYN_TICK_ENABLED) - system_timer->dyn_tick->handler(irq, 0, regs); - spin_unlock(&system_timer->dyn_tick->lock); - } -#endif - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - - status = 0; - do { - ret = action->handler(irq, action->dev_id, regs); - if (ret == IRQ_HANDLED) - status |= action->flags; - retval |= ret; - action = action->next; - } while (action); - - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - - spin_lock_irq(&irq_controller_lock); - - return retval; -} - -/* - * This is for software-decoded IRQs. The caller is expected to - * handle the ack, clear, mask and unmask issues. - */ -void -do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - struct irqaction *action; - const unsigned int cpu = smp_processor_id(); - - desc->triggered = 1; - - kstat_cpu(cpu).irqs[irq]++; - - smp_set_running(desc); - - action = desc->action; - if (action) { - int ret = __do_irq(irq, action, regs); - if (ret != IRQ_HANDLED) - report_bad_irq(irq, regs, desc, ret); - } - - smp_clear_running(desc); -} - -/* - * Most edge-triggered IRQ implementations seem to take a broken - * approach to this. Hence the complexity. - */ -void -do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - const unsigned int cpu = smp_processor_id(); - - desc->triggered = 1; - - /* - * If we're currently running this IRQ, or its disabled, - * we shouldn't process the IRQ. Instead, turn on the - * hardware masks. - */ - if (unlikely(desc->running || desc->disable_depth)) - goto running; - - /* - * Acknowledge and clear the IRQ, but don't mask it. - */ - desc->chip->ack(irq); - - /* - * Mark the IRQ currently in progress. - */ - desc->running = 1; - - kstat_cpu(cpu).irqs[irq]++; - - do { - struct irqaction *action; - - action = desc->action; - if (!action) - break; - - if (desc->pending && !desc->disable_depth) { - desc->pending = 0; - desc->chip->unmask(irq); - } - - __do_irq(irq, action, regs); - } while (desc->pending && !desc->disable_depth); - - desc->running = 0; - - /* - * If we were disabled or freed, shut down the handler. - */ - if (likely(desc->action && !check_irq_lock(desc, irq, regs))) - return; - - running: - /* - * We got another IRQ while this one was masked or - * currently running. Delay it. - */ - desc->pending = 1; - desc->chip->mask(irq); - desc->chip->ack(irq); -} - -/* - * Level-based IRQ handler. Nice and simple. - */ -void -do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) -{ - struct irqaction *action; - const unsigned int cpu = smp_processor_id(); - - desc->triggered = 1; - - /* - * Acknowledge, clear _AND_ disable the interrupt. - */ - desc->chip->ack(irq); - - if (likely(!desc->disable_depth)) { - kstat_cpu(cpu).irqs[irq]++; - - smp_set_running(desc); - - /* - * Return with this interrupt masked if no action - */ - action = desc->action; - if (action) { - int ret = __do_irq(irq, desc->action, regs); - - if (ret != IRQ_HANDLED) - report_bad_irq(irq, regs, desc, ret); - - if (likely(!desc->disable_depth && - !check_irq_lock(desc, irq, regs))) - desc->chip->unmask(irq); - } - - smp_clear_running(desc); - } -} - -static void do_pending_irqs(struct pt_regs *regs) -{ - struct list_head head, *l, *n; - - do { - struct irqdesc *desc; - - /* - * First, take the pending interrupts off the list. - * The act of calling the handlers may add some IRQs - * back onto the list. - */ - head = irq_pending; - INIT_LIST_HEAD(&irq_pending); - head.next->prev = &head; - head.prev->next = &head; - - /* - * Now run each entry. We must delete it from our - * list before calling the handler. - */ - list_for_each_safe(l, n, &head) { - desc = list_entry(l, struct irqdesc, pend); - list_del_init(&desc->pend); - desc_handle_irq(desc - irq_desc, desc, regs); - } - - /* - * The list must be empty. - */ - BUG_ON(!list_empty(&head)); - } while (!list_empty(&irq_pending)); -} +/* Handle bad interrupts */ +static struct irq_desc bad_irq_desc = { + .handle_irq = handle_bad_irq, + .lock = SPIN_LOCK_UNLOCKED +}; /* * do_IRQ handles all hardware IRQ's. Decoded IRQs should not @@ -549,96 +120,15 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) desc = &bad_irq_desc; irq_enter(); - spin_lock(&irq_controller_lock); - desc_handle_irq(irq, desc, regs); - /* - * Now re-run any pending interrupts. - */ - if (!list_empty(&irq_pending)) - do_pending_irqs(regs); + desc_handle_irq(irq, desc, regs); + /* AT91 specific workaround */ irq_finish(irq); - spin_unlock(&irq_controller_lock); irq_exit(); } -void __set_irq_handler(unsigned int irq, irq_handler_t handle, int is_chained) -{ - struct irqdesc *desc; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to install handler for IRQ%d\n", irq); - return; - } - - if (handle == NULL) - handle = do_bad_IRQ; - - desc = irq_desc + irq; - - if (is_chained && desc->chip == &bad_chip) - printk(KERN_WARNING "Trying to install chained handler for IRQ%d\n", irq); - - spin_lock_irqsave(&irq_controller_lock, flags); - if (handle == do_bad_IRQ) { - desc->chip->mask(irq); - desc->chip->ack(irq); - desc->disable_depth = 1; - } - desc->handle = handle; - if (handle != do_bad_IRQ && is_chained) { - desc->valid = 0; - desc->probe_ok = 0; - desc->disable_depth = 0; - desc->chip->unmask(irq); - } - spin_unlock_irqrestore(&irq_controller_lock, flags); -} - -void set_irq_chip(unsigned int irq, struct irqchip *chip) -{ - struct irqdesc *desc; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq); - return; - } - - if (chip == NULL) - chip = &bad_chip; - - desc = irq_desc + irq; - spin_lock_irqsave(&irq_controller_lock, flags); - desc->chip = chip; - spin_unlock_irqrestore(&irq_controller_lock, flags); -} - -int set_irq_type(unsigned int irq, unsigned int type) -{ - struct irqdesc *desc; - unsigned long flags; - int ret = -ENXIO; - - if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); - return -ENODEV; - } - - desc = irq_desc + irq; - if (desc->chip->set_type) { - spin_lock_irqsave(&irq_controller_lock, flags); - ret = desc->chip->set_type(irq, type); - spin_unlock_irqrestore(&irq_controller_lock, flags); - } - - return ret; -} -EXPORT_SYMBOL(set_irq_type); - void set_irq_flags(unsigned int irq, unsigned int iflags) { struct irqdesc *desc; @@ -650,421 +140,32 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) } desc = irq_desc + irq; - spin_lock_irqsave(&irq_controller_lock, flags); - desc->valid = (iflags & IRQF_VALID) != 0; - desc->probe_ok = (iflags & IRQF_PROBE) != 0; - desc->noautoenable = (iflags & IRQF_NOAUTOEN) != 0; - spin_unlock_irqrestore(&irq_controller_lock, flags); -} - -int setup_irq(unsigned int irq, struct irqaction *new) -{ - int shared = 0; - struct irqaction *old, **p; - unsigned long flags; - struct irqdesc *desc; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - /* - * The following block of code has to be executed atomically - */ - desc = irq_desc + irq; - spin_lock_irqsave(&irq_controller_lock, flags); - p = &desc->action; - if ((old = *p) != NULL) { - /* - * Can't share interrupts unless both agree to and are - * the same type. - */ - if (!(old->flags & new->flags & SA_SHIRQ) || - (~old->flags & new->flags) & SA_TRIGGER_MASK) { - spin_unlock_irqrestore(&irq_controller_lock, flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if (!shared) { - desc->probing = 0; - desc->running = 0; - desc->pending = 0; - desc->disable_depth = 1; - - if (new->flags & SA_TRIGGER_MASK && - desc->chip->set_type) { - unsigned int type = new->flags & SA_TRIGGER_MASK; - desc->chip->set_type(irq, type); - } - - if (!desc->noautoenable) { - desc->disable_depth = 0; - desc->chip->unmask(irq); - } - } - - spin_unlock_irqrestore(&irq_controller_lock, flags); - return 0; -} - -/** - * request_irq - allocate an interrupt line - * @irq: Interrupt line to allocate - * @handler: Function to be called when the IRQ occurs - * @irqflags: Interrupt type flags - * @devname: An ascii name for the claiming device - * @dev_id: A cookie passed back to the handler function - * - * This call allocates interrupt resources and enables the - * interrupt line and IRQ handling. From the point this - * call is made your handler function may be invoked. Since - * your handler function must clear any interrupt the board - * raises, you must take care both to initialise your hardware - * and to set up the interrupt handler in the right order. - * - * Dev_id must be globally unique. Normally the address of the - * device data structure is used as the cookie. Since the handler - * receives this value it makes sense to use it. - * - * If your interrupt is shared you must pass a non NULL dev_id - * as this is required when freeing the interrupt. - * - * Flags: - * - * SA_SHIRQ Interrupt is shared - * - * SA_INTERRUPT Disable local interrupts while processing - * - * SA_SAMPLE_RANDOM The interrupt can be used for entropy - * - */ -int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irq_flags, const char * devname, void *dev_id) -{ - unsigned long retval; - struct irqaction *action; - - if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler || - (irq_flags & SA_SHIRQ && !dev_id)) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irq_flags; - cpus_clear(action->mask); - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - - if (retval) - kfree(action); - return retval; -} - -EXPORT_SYMBOL(request_irq); - -/** - * free_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. - * - * This function must not be called from interrupt context. - */ -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction * action, **p; - unsigned long flags; - - if (irq >= NR_IRQS || !irq_desc[irq].valid) { - printk(KERN_ERR "Trying to free IRQ%d\n",irq); - dump_stack(); - return; - } - - spin_lock_irqsave(&irq_controller_lock, flags); - for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - *p = action->next; - break; - } - spin_unlock_irqrestore(&irq_controller_lock, flags); - - if (!action) { - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); - dump_stack(); - } else { - synchronize_irq(irq); - kfree(action); - } -} - -EXPORT_SYMBOL(free_irq); - -static DECLARE_MUTEX(probe_sem); - -/* Start the interrupt probing. Unlike other architectures, - * we don't return a mask of interrupts from probe_irq_on, - * but return the number of interrupts enabled for the probe. - * The interrupts which have been enabled for probing is - * instead recorded in the irq_desc structure. - */ -unsigned long probe_irq_on(void) -{ - unsigned int i, irqs = 0; - unsigned long delay; - - down(&probe_sem); - - /* - * first snaffle up any unassigned but - * probe-able interrupts - */ - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { - if (!irq_desc[i].probe_ok || irq_desc[i].action) - continue; - - irq_desc[i].probing = 1; - irq_desc[i].triggered = 0; - if (irq_desc[i].chip->set_type) - irq_desc[i].chip->set_type(i, IRQT_PROBE); - irq_desc[i].chip->unmask(i); - irqs += 1; - } - spin_unlock_irq(&irq_controller_lock); - - /* - * wait for spurious interrupts to mask themselves out again - */ - for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) - /* min 100ms delay */; - - /* - * now filter out any obviously spurious interrupts - */ - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { - if (irq_desc[i].probing && irq_desc[i].triggered) { - irq_desc[i].probing = 0; - irqs -= 1; - } - } - spin_unlock_irq(&irq_controller_lock); - - return irqs; -} - -EXPORT_SYMBOL(probe_irq_on); - -unsigned int probe_irq_mask(unsigned long irqs) -{ - unsigned int mask = 0, i; - - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < 16 && i < NR_IRQS; i++) - if (irq_desc[i].probing && irq_desc[i].triggered) - mask |= 1 << i; - spin_unlock_irq(&irq_controller_lock); - - up(&probe_sem); - - return mask; -} -EXPORT_SYMBOL(probe_irq_mask); - -/* - * Possible return values: - * >= 0 - interrupt number - * -1 - no interrupt/many interrupts - */ -int probe_irq_off(unsigned long irqs) -{ - unsigned int i; - int irq_found = NO_IRQ; - - /* - * look at the interrupts, and find exactly one - * that we were probing has been triggered - */ - spin_lock_irq(&irq_controller_lock); - for (i = 0; i < NR_IRQS; i++) { - if (irq_desc[i].probing && - irq_desc[i].triggered) { - if (irq_found != NO_IRQ) { - irq_found = NO_IRQ; - goto out; - } - irq_found = i; - } - } - - if (irq_found == -1) - irq_found = NO_IRQ; -out: - spin_unlock_irq(&irq_controller_lock); - - up(&probe_sem); - - return irq_found; -} - -EXPORT_SYMBOL(probe_irq_off); - -#ifdef CONFIG_SMP -static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu) -{ - pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); - - spin_lock_irq(&irq_controller_lock); - desc->cpu = cpu; - desc->chip->set_cpu(desc, irq, cpu); - spin_unlock_irq(&irq_controller_lock); -} - -#ifdef CONFIG_PROC_FS -static int -irq_affinity_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - struct irqdesc *desc = irq_desc + ((int)data); - int len = cpumask_scnprintf(page, count, desc->affinity); - - if (count - len < 2) - return -EINVAL; - page[len++] = '\n'; - page[len] = '\0'; - - return len; -} - -static int -irq_affinity_write_proc(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - unsigned int irq = (unsigned int)data; - struct irqdesc *desc = irq_desc + irq; - cpumask_t affinity, tmp; - int ret = -EIO; - - if (!desc->chip->set_cpu) - goto out; - - ret = cpumask_parse(buffer, count, affinity); - if (ret) - goto out; - - cpus_and(tmp, affinity, cpu_online_map); - if (cpus_empty(tmp)) { - ret = -EINVAL; - goto out; - } - - desc->affinity = affinity; - route_irq(desc, irq, first_cpu(tmp)); - ret = count; - - out: - return ret; -} -#endif -#endif - -void __init init_irq_proc(void) -{ -#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS) - struct proc_dir_entry *dir; - int irq; - - dir = proc_mkdir("irq", NULL); - if (!dir) - return; - - for (irq = 0; irq < NR_IRQS; irq++) { - struct proc_dir_entry *entry; - struct irqdesc *desc; - char name[16]; - - desc = irq_desc + irq; - memset(name, 0, sizeof(name)); - snprintf(name, sizeof(name) - 1, "%u", irq); - - desc->procdir = proc_mkdir(name, dir); - if (!desc->procdir) - continue; - - entry = create_proc_entry("smp_affinity", 0600, desc->procdir); - if (entry) { - entry->nlink = 1; - entry->data = (void *)irq; - entry->read_proc = irq_affinity_read_proc; - entry->write_proc = irq_affinity_write_proc; - } - } -#endif + spin_lock_irqsave(&desc->lock, flags); + desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; + if (iflags & IRQF_VALID) + desc->status &= ~IRQ_NOREQUEST; + if (iflags & IRQF_PROBE) + desc->status &= ~IRQ_NOPROBE; + if (!(iflags & IRQF_NOAUTOEN)) + desc->status &= ~IRQ_NOAUTOEN; + spin_unlock_irqrestore(&desc->lock, flags); } void __init init_IRQ(void) { - struct irqdesc *desc; int irq; + for (irq = 0; irq < NR_IRQS; irq++) + irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_DELAYED_DISABLE | + IRQ_NOPROBE; + #ifdef CONFIG_SMP bad_irq_desc.affinity = CPU_MASK_ALL; bad_irq_desc.cpu = smp_processor_id(); #endif - - for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { - *desc = bad_irq_desc; - INIT_LIST_HEAD(&desc->pend); - } - init_arch_irq(); } -static int __init noirqdebug_setup(char *str) -{ - noirqdebug = 1; - return 1; -} - -__setup("noirqdebug", noirqdebug_setup); - #ifdef CONFIG_HOTPLUG_CPU /* * The CPU has been marked offline. Migrate IRQs off this CPU. If diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c new file mode 100644 index 00000000000..44a86c33796 --- /dev/null +++ b/arch/arm/kernel/iwmmxt-notifier.c @@ -0,0 +1,64 @@ +/* + * linux/arch/arm/kernel/iwmmxt-notifier.c + * + * XScale iWMMXt (Concan) context switching and handling + * + * Initial code: + * Copyright (c) 2003, Intel Corporation + * + * Full lazy switching support, optimizations and more, by Nicolas Pitre + * Copyright (c) 2003-2004, MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/config.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <asm/thread_notify.h> +#include <asm/io.h> + +static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) +{ + struct thread_info *thread = t; + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + /* + * flush_thread() zeroes thread->fpstate, so no need + * to do anything here. + * + * FALLTHROUGH: Ensure we don't try to overwrite our newly + * initialised state information on the first fault. + */ + + case THREAD_NOTIFY_RELEASE: + iwmmxt_task_release(thread); + break; + + case THREAD_NOTIFY_SWITCH: + iwmmxt_task_switch(thread); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block iwmmxt_notifier_block = { + .notifier_call = iwmmxt_do, +}; + +static int __init iwmmxt_init(void) +{ + thread_register_notifier(&iwmmxt_notifier_block); + + return 0; +} + +late_initcall(iwmmxt_init); diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index a3bae95e536..b63b528f22a 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -271,30 +271,27 @@ ENTRY(iwmmxt_task_restore) /* * Concan handling on task switch * - * r0 = previous task_struct pointer (must be preserved) - * r1 = previous thread_info pointer - * r2 = next thread_info pointer (must be preserved) + * r0 = next thread_info pointer * - * Called only from __switch_to with task preemption disabled. - * No need to care about preserving r4 and above. + * Called only from the iwmmxt notifier with task preemption disabled. */ ENTRY(iwmmxt_task_switch) - mrc p15, 0, r4, c15, c1, 0 - tst r4, #0x3 @ CP0 and CP1 accessible? + mrc p15, 0, r1, c15, c1, 0 + tst r1, #0x3 @ CP0 and CP1 accessible? bne 1f @ yes: block them for next task - ldr r5, =concan_owner - add r6, r2, #TI_IWMMXT_STATE @ get next task Concan save area - ldr r5, [r5] @ get current Concan owner - teq r5, r6 @ next task owns it? + ldr r2, =concan_owner + add r3, r0, #TI_IWMMXT_STATE @ get next task Concan save area + ldr r2, [r2] @ get current Concan owner + teq r2, r3 @ next task owns it? movne pc, lr @ no: leave Concan disabled -1: eor r4, r4, #3 @ flip Concan access - mcr p15, 0, r4, c15, c1, 0 +1: eor r1, r1, #3 @ flip Concan access + mcr p15, 0, r1, c15, c1, 0 - mrc p15, 0, r4, c2, c0, 0 - sub pc, lr, r4, lsr #32 @ cpwait and return + mrc p15, 0, r1, c2, c0, 0 + sub pc, lr, r1, lsr #32 @ cpwait and return /* * Remove Concan ownership of given task diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index c3258b763c5..3079535afcc 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -352,9 +352,6 @@ void flush_thread(void) memset(&thread->fpstate, 0, sizeof(union fp_state)); thread_notify(THREAD_NOTIFY_FLUSH, thread); -#if defined(CONFIG_IWMMXT) - iwmmxt_task_release(thread); -#endif } void release_thread(struct task_struct *dead_task) @@ -362,9 +359,6 @@ void release_thread(struct task_struct *dead_task) struct thread_info *thread = task_thread_info(dead_task); thread_notify(THREAD_NOTIFY_RELEASE, thread); -#if defined(CONFIG_IWMMXT) - iwmmxt_task_release(thread); -#endif } asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 7447a198732..ed1c4d62d99 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -344,9 +344,9 @@ static void __init setup_processor(void) cpu_cache = *list->cache; #endif - printk("CPU: %s [%08x] revision %d (ARMv%s)\n", + printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n", cpu_name, processor_id, (int)processor_id & 15, - proc_arch[cpu_architecture()]); + proc_arch[cpu_architecture()], cr_alignment); sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS); sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS); diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c index aa01d6753d6..baa997c857d 100644 --- a/arch/arm/mach-aaec2000/core.c +++ b/arch/arm/mach-aaec2000/core.c @@ -142,7 +142,7 @@ aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction aaec2000_timer_irq = { .name = "AAEC-2000 Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = aaec2000_timer_interrupt, }; diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig index 70d402f76ce..2f85e8693b1 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91rm9200/Kconfig @@ -1,6 +1,21 @@ -if ARCH_AT91RM9200 +if ARCH_AT91 + +menu "Atmel AT91 System-on-Chip" + +comment "Atmel AT91 Processors" + +config ARCH_AT91RM9200 + bool "AT91RM9200" -menu "AT91RM9200 Implementations" +config ARCH_AT91SAM9260 + bool "AT91SAM9260" + +config ARCH_AT91SAM9261 + bool "AT91SAM9261" + +# ---------------------------------------------------------- + +if ARCH_AT91RM9200 comment "AT91RM9200 Board Type" @@ -8,58 +23,87 @@ config MACH_ONEARM bool "Ajeco 1ARM Single Board Computer" depends on ARCH_AT91RM9200 help - Select this if you are using Ajeco's 1ARM Single Board Computer + Select this if you are using Ajeco's 1ARM Single Board Computer. + <http://www.ajeco.fi/products.htm> config ARCH_AT91RM9200DK bool "Atmel AT91RM9200-DK Development board" depends on ARCH_AT91RM9200 help - Select this if you are using Atmel's AT91RM9200-DK Development board + Select this if you are using Atmel's AT91RM9200-DK Development board. + (Discontinued) + config MACH_AT91RM9200EK bool "Atmel AT91RM9200-EK Evaluation Kit" depends on ARCH_AT91RM9200 help - Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit + Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit. + <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3507> config MACH_CSB337 - bool "Cogent CSB337 board" + bool "Cogent CSB337" depends on ARCH_AT91RM9200 help - Select this if you are using Cogent's CSB337 board + Select this if you are using Cogent's CSB337 board. + <http://www.cogcomp.com/csb_csb337.htm> config MACH_CSB637 - bool "Cogent CSB637 board" + bool "Cogent CSB637" depends on ARCH_AT91RM9200 help - Select this if you are using Cogent's CSB637 board + Select this if you are using Cogent's CSB637 board. + <http://www.cogcomp.com/csb_csb637.htm> config MACH_CARMEVA - bool "Conitec's ARM&EVA" + bool "Conitec ARM&EVA" depends on ARCH_AT91RM9200 help - Select this if you are using Conitec's AT91RM9200-MCU-Module + Select this if you are using Conitec's AT91RM9200-MCU-Module. + <http://www.conitec.net/english/linuxboard.htm> -config MACH_KB9200 - bool "KwikByte's KB920x" +config MACH_ATEB9200 + bool "Embest ATEB9200" depends on ARCH_AT91RM9200 help - Select this if you are using KwikByte's KB920x board + Select this if you are using Embest's ATEB9200 board. + <http://www.embedinfo.com/english/product/ATEB9200.asp> -config MACH_ATEB9200 - bool "Embest's ATEB9200" +config MACH_KB9200 + bool "KwikByte KB920x" depends on ARCH_AT91RM9200 help - Select this if you are using Embest's ATEB9200 board + Select this if you are using KwikByte's KB920x board. + <http://kwikbyte.com/KB9202_description_new.htm> config MACH_KAFA bool "Sperry-Sun KAFA board" depends on ARCH_AT91RM9200 help - Select this if you are using Sperry-Sun's KAFA board + Select this if you are using Sperry-Sun's KAFA board. + +endif + +# ---------------------------------------------------------- + +if ARCH_AT91SAM9260 + +comment "AT91SAM9260 Board Type" + +endif + +# ---------------------------------------------------------- + +if ARCH_AT91SAM9261 + +comment "AT91SAM9261 Board Type" + +endif + +# ---------------------------------------------------------- -comment "AT91RM9200 Feature Selections" +comment "AT91 Feature Selections" config AT91_PROGRAMMABLE_CLOCKS bool "Programmable Clocks" diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index 82db957322d..c174805c24e 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -2,14 +2,19 @@ # Makefile for the linux kernel. # -obj-y := clock.o irq.o time.o gpio.o common.o devices.o +obj-y := clock.o irq.o gpio.o devices.o obj-m := obj-n := obj- := obj-$(CONFIG_PM) += pm.o -# Board-specific support +# CPU-specific support +obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o +obj-$(CONFIG_ARCH_AT91SAM9260) += +obj-$(CONFIG_ARCH_AT91SAM9261) += + +# AT91RM9200 Board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o @@ -20,6 +25,10 @@ obj-$(CONFIG_MACH_KB9200) += board-kb9202.o obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o obj-$(CONFIG_MACH_KAFA) += board-kafa.o +# AT91SAM9260 board-specific support + +# AT91SAM9261 board-specific support + # LEDs support led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o led-$(CONFIG_MACH_AT91RM9200EK) += leds.o diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/at91rm9200.c index cc55f4c28d9..7e1d072bdd8 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/at91rm9200.c @@ -1,5 +1,5 @@ /* - * arch/arm/mach-at91rm9200/common.c + * arch/arm/mach-at91rm9200/at91rm9200.c * * Copyright (C) 2005 SAN People * diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c index f2f080350cc..a92a8622c78 100644 --- a/arch/arm/mach-at91rm9200/time.c +++ b/arch/arm/mach-at91rm9200/at91rm9200_time.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mach-at91rm9200/time.c + * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c * * Copyright (C) 2003 SAN People * Copyright (C) 2003 ATMEL @@ -21,13 +21,13 @@ #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/time.h> #include <asm/hardware.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/mach/time.h> static unsigned long last_crtr; @@ -85,7 +85,7 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_r static struct irqaction at91rm9200_timer_irq = { .name = "at91_tick", - .flags = SA_SHIRQ | SA_INTERRUPT | SA_TIMER, + .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER, .handler = at91rm9200_timer_interrupt }; diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 83c34747087..5783c282ae7 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -10,12 +10,13 @@ */ #include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> #include <asm/io.h> -#include <asm/mach/irq.h> #include <asm/hardware.h> #include <asm/arch/gpio.h> @@ -340,7 +341,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs void __iomem *pio; u32 isr; - pio = desc->base; + pio = get_irq_chip_data(irq); /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); @@ -350,12 +351,12 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs if (!isr) break; - pin = (unsigned) desc->data; + pin = (unsigned) get_irq_data(irq); gpio = &irq_desc[pin]; while (isr) { if (isr & 1) { - if (unlikely(gpio->disable_depth)) { + if (unlikely(gpio->depth)) { /* * The core ARM interrupt handler lazily disables IRQs so * another IRQ must be generated before it actually gets @@ -364,7 +365,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs gpio_irq_mask(pin); } else - gpio->handle(pin, gpio, regs); + desc_handle_irq(pin, gpio, regs); } pin++; gpio++; diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c index 1a23f0dcd4b..a071eac4a30 100644 --- a/arch/arm/mach-clps711x/time.c +++ b/arch/arm/mach-clps711x/time.c @@ -19,6 +19,7 @@ #include <linux/timex.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/sched.h> #include <asm/hardware.h> @@ -57,7 +58,7 @@ p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction clps711x_timer_irq = { .name = "CLPS711x Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = p720t_timer_interrupt, }; diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index 5b12cab0e69..92eaebdd560 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c @@ -9,6 +9,7 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/list.h> #include <linux/sched.h> #include <linux/init.h> @@ -315,7 +316,7 @@ clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction clps7500_timer_irq = { .name = "CLPS7500 Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = clps7500_timer_interrupt, }; diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 6d620d8268c..70dd12ef3c4 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -199,7 +199,7 @@ ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction ebsa110_timer_irq = { .name = "EBSA110 Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = ebsa110_timer_interrupt, }; diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig index e15e4c54a25..f1b740083ae 100644 --- a/arch/arm/mach-ep93xx/Kconfig +++ b/arch/arm/mach-ep93xx/Kconfig @@ -9,12 +9,24 @@ config CRUNCH comment "EP93xx Platforms" +config MACH_EDB9302 + bool "Support Cirrus Logic EDB9302" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9302 Evaluation Board. + config MACH_EDB9315 bool "Support Cirrus Logic EDB9315" help Say 'Y' here if you want your kernel to support the Cirrus Logic EDB9315 Evaluation Board. +config MACH_EDB9315A + bool "Support Cirrus Logic EDB9315A" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9315A Evaluation Board. + config MACH_GESBC9312 bool "Support Glomation GESBC-9312-sx" help diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile index dfa7e2e8a18..1f5a6b0487e 100644 --- a/arch/arm/mach-ep93xx/Makefile +++ b/arch/arm/mach-ep93xx/Makefile @@ -6,6 +6,8 @@ obj-m := obj-n := obj- := +obj-$(CONFIG_MACH_EDB9302) += edb9302.o obj-$(CONFIG_MACH_EDB9315) += edb9315.o +obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o obj-$(CONFIG_MACH_TS72XX) += ts72xx.o diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 26df3b666b5..a87a784b920 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -116,7 +116,7 @@ static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction ep93xx_timer_irq = { .name = "ep93xx timer", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = ep93xx_timer_interrupt, }; diff --git a/arch/arm/mach-ep93xx/edb9302.c b/arch/arm/mach-ep93xx/edb9302.c new file mode 100644 index 00000000000..62a8efd2325 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9302.c @@ -0,0 +1,62 @@ +/* + * arch/arm/mach-ep93xx/edb9302.c + * Cirrus Logic EDB9302 support. + * + * Copyright (C) 2006 George Kashperko <george@chas.com.ua> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9302_flash_data = { + .width = 2, +}; + +static struct resource edb9302_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9302_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9302_flash_data, + }, + .num_resources = 1, + .resource = &edb9302_flash_resource, +}; + +static void __init edb9302_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9302_flash); +} + +MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") + /* Maintainer: George Kashperko <george@chas.com.ua> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9302_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9315a.c b/arch/arm/mach-ep93xx/edb9315a.c new file mode 100644 index 00000000000..bfefdaa8f79 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9315a.c @@ -0,0 +1,62 @@ +/* + * arch/arm/mach-ep93xx/edb9315a.c + * Cirrus Logic EDB9315A support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9315a_flash_data = { + .width = 2, +}; + +static struct resource edb9315a_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9315a_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9315a_flash_data, + }, + .num_resources = 1, + .resource = &edb9315a_flash_resource, +}; + +static void __init edb9315a_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9315a_flash); +} + +MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0xc0000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9315a_init_machine, +MACHINE_END diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index 14a62d6008f..2af610811ca 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -6,6 +6,7 @@ */ #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <asm/irq.h> @@ -43,7 +44,7 @@ timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction footbridge_timer_irq = { .name = "Timer1 timer tick", .handler = timer1_interrupt, - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, }; /* diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index 5dace259783..607ed1f5b3f 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -332,15 +332,15 @@ void __init dc21285_preinit(void) /* * We don't care if these fail. */ - request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT, + request_irq(IRQ_PCI_SERR, dc21285_serr_irq, IRQF_DISABLED, "PCI system error", &serr_timer); - request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT, + request_irq(IRQ_PCI_PERR, dc21285_parity_irq, IRQF_DISABLED, "PCI parity error", &perr_timer); - request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT, + request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, IRQF_DISABLED, "PCI abort", NULL); - request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT, + request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, IRQF_DISABLED, "Discard timer", NULL); - request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT, + request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, IRQF_DISABLED, "PCI data parity", NULL); if (cfn_mode) { diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c index e1c43b331d6..87448c2d6ba 100644 --- a/arch/arm/mach-footbridge/isa-irq.c +++ b/arch/arm/mach-footbridge/isa-irq.c @@ -98,9 +98,22 @@ isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) desc_handle_irq(isa_irq, desc, regs); } -static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", }; -static struct resource pic1_resource = { "pic1", 0x20, 0x3f }; -static struct resource pic2_resource = { "pic2", 0xa0, 0xbf }; +static struct irqaction irq_cascade = { + .handler = no_action, + .name = "cascade", +}; + +static struct resource pic1_resource = { + .name = "pic1", + .start = 0x20, + .end = 0x3f, +}; + +static struct resource pic2_resource = { + .name = "pic2", + .start = 0xa0, + .end = 0xbf, +}; void __init isa_init_irq(unsigned int host_irq) { diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c index c1d74f7ab66..c4810a40c8e 100644 --- a/arch/arm/mach-footbridge/isa-timer.c +++ b/arch/arm/mach-footbridge/isa-timer.c @@ -6,6 +6,7 @@ */ #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <asm/io.h> #include <asm/irq.h> @@ -72,7 +73,7 @@ isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction isa_timer_irq = { .name = "ISA timer tick", .handler = isa_timer_interrupt, - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, }; static void __init isa_timer_init(void) diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c index af9e4a5d5ea..a9a8255a3a0 100644 --- a/arch/arm/mach-h720x/cpu-h7201.c +++ b/arch/arm/mach-h720x/cpu-h7201.c @@ -41,7 +41,7 @@ h7201_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction h7201_timer_irq = { .name = "h7201 Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = h7201_timer_interrupt, }; diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c index a4a7c0125d0..da678d163fd 100644 --- a/arch/arm/mach-h720x/cpu-h7202.c +++ b/arch/arm/mach-h720x/cpu-h7202.c @@ -171,7 +171,7 @@ static struct irqchip h7202_timerx_chip = { static struct irqaction h7202_timer_irq = { .name = "h7202 Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = h7202_timer_interrupt, }; diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index 294b1c450f2..6ed7523c65b 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -12,6 +12,7 @@ #include <linux/sched.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/time.h> #include <asm/hardware.h> @@ -71,7 +72,7 @@ imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction imx_timer_irq = { .name = "i.MX Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = imx_timer_interrupt, }; diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 576a5e979c0..42021fdfa0c 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -13,6 +13,7 @@ #include <linux/device.h> #include <linux/spinlock.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/sched.h> #include <linux/smp.h> #include <linux/termios.h> @@ -281,7 +282,7 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction integrator_timer_irq = { .name = "Integrator Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = integrator_timer_interrupt, }; diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c index bc07f52a6fd..ee49cf790da 100644 --- a/arch/arm/mach-integrator/time.c +++ b/arch/arm/mach-integrator/time.c @@ -125,7 +125,7 @@ static int rtc_probe(struct amba_device *dev, void *id) xtime.tv_sec = __raw_readl(rtc_base + RTC_DR); - ret = request_irq(dev->irq[0], arm_rtc_interrupt, SA_INTERRUPT, + ret = request_irq(dev->irq[0], arm_rtc_interrupt, IRQF_DISABLED, "rtc-pl030", dev); if (ret) goto map_out; diff --git a/arch/arm/mach-iop3xx/Kconfig b/arch/arm/mach-iop3xx/Kconfig index 2bfe8c729f9..4422f238860 100644 --- a/arch/arm/mach-iop3xx/Kconfig +++ b/arch/arm/mach-iop3xx/Kconfig @@ -30,12 +30,15 @@ config MACH_IQ80332 select ARCH_IOP331 help Say Y here if you want to run your kernel on the Intel IQ80332 - evaluation kit for the IOP332 chipset + evaluation kit for the IOP332 chipset. config ARCH_EP80219 - bool "Enable support for EP80219" - select ARCH_IOP321 - select ARCH_IQ31244 + bool "Enable support for EP80219" + select ARCH_IOP321 + select ARCH_IQ31244 + help + Say Y here if you want to run your kernel on the Intel EP80219 + evaluation kit for the Intel 80219 chipset (a IOP321 variant). # Which IOP variant are we running? config ARCH_IOP321 @@ -56,8 +59,8 @@ config IOP331_STEPD bool "Chip stepping D of the IOP80331 processor or IOP80333" depends on (ARCH_IOP331) help - Say Y here if you have StepD of the IOP80331 or IOP8033 - based platforms. + Say Y here if you have StepD of the IOP80331 or IOP8033 + based platforms. endmenu endif diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c index d67ac0e5d43..04b1a6f7eba 100644 --- a/arch/arm/mach-iop3xx/iop321-time.c +++ b/arch/arm/mach-iop3xx/iop321-time.c @@ -85,7 +85,7 @@ iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction iop321_timer_irq = { .name = "IOP321 Timer Tick", .handler = iop321_timer_interrupt, - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, }; static void __init iop321_timer_init(void) diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c index 3c1f0ebbd63..0c09e74c574 100644 --- a/arch/arm/mach-iop3xx/iop331-time.c +++ b/arch/arm/mach-iop3xx/iop331-time.c @@ -82,7 +82,7 @@ iop331_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction iop331_timer_irq = { .name = "IOP331 Timer Tick", .handler = iop331_timer_interrupt, - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, }; static void __init iop331_timer_init(void) diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 3cfc5aab825..7f91f689a04 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c @@ -19,6 +19,7 @@ #include <linux/spinlock.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/serial.h> #include <linux/tty.h> #include <linux/bitops.h> @@ -223,7 +224,7 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction ixp2000_timer_irq = { .name = "IXP2000 Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = ixp2000_timer_interrupt, }; @@ -408,7 +409,7 @@ static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc, str for(i = 31; i >= 0; i--) { if(status & (1 << i)) { desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i; - desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs); + desc_handle_irq(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs); } } } diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c index 9b8ded25980..40eef8b3674 100644 --- a/arch/arm/mach-ixp2000/ixdp2x00.c +++ b/arch/arm/mach-ixp2000/ixdp2x00.c @@ -167,7 +167,7 @@ void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long } /* Hook into PCI interrupt */ - set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x00_irq_handler); + set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler); } /************************************************************************* diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c index 8477ae1d8f7..7f42366f60d 100644 --- a/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/arch/arm/mach-ixp2000/ixdp2x01.c @@ -127,7 +127,7 @@ void __init ixdp2x01_init_irq(void) } /* Hook into PCI interrupts */ - set_irq_chained_handler(IRQ_IXP2000_PCIB, &ixdp2x01_irq_handler); + set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler); } diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c index 82ad6ef90a3..566a07821c7 100644 --- a/arch/arm/mach-ixp23xx/core.c +++ b/arch/arm/mach-ixp23xx/core.c @@ -271,7 +271,7 @@ static void pci_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs * } int_desc = irq_desc + irqno; - int_desc->handle(irqno, int_desc, regs); + desc_handle_irq(irqno, int_desc, regs); desc->chip->unmask(irq); } @@ -363,7 +363,7 @@ ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction ixp23xx_timer_irq = { .name = "IXP23xx Timer Tick", .handler = ixp23xx_timer_interrupt, - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, }; void __init ixp23xx_init_timer(void) diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c index bba9d9f0869..37a32e6bcca 100644 --- a/arch/arm/mach-ixp23xx/ixdp2351.c +++ b/arch/arm/mach-ixp23xx/ixdp2351.c @@ -19,6 +19,7 @@ #include <linux/spinlock.h> #include <linux/sched.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/serial.h> #include <linux/tty.h> #include <linux/bitops.h> @@ -36,7 +37,6 @@ #include <asm/memory.h> #include <asm/hardware.h> #include <asm/mach-types.h> -#include <asm/irq.h> #include <asm/system.h> #include <asm/tlbflush.h> #include <asm/pgtable.h> @@ -74,7 +74,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc, struct int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i); cpld_desc = irq_desc + cpld_irq; - cpld_desc->handle(cpld_irq, cpld_desc, regs); + desc_handle_irq(cpld_irq, cpld_desc, regs); } } @@ -111,7 +111,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc, struct int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i); cpld_desc = irq_desc + cpld_irq; - cpld_desc->handle(cpld_irq, cpld_desc, regs); + desc_handle_irq(cpld_irq, cpld_desc, regs); } } @@ -158,8 +158,8 @@ void ixdp2351_init_irq(void) } } - set_irq_chained_handler(IRQ_IXP23XX_INTA, &ixdp2351_inta_handler); - set_irq_chained_handler(IRQ_IXP23XX_INTB, &ixdp2351_intb_handler); + set_irq_chained_handler(IRQ_IXP23XX_INTA, ixdp2351_inta_handler); + set_irq_chained_handler(IRQ_IXP23XX_INTB, ixdp2351_intb_handler); } /* diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 13c7c629d03..7c25dbd5a18 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -287,7 +287,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs static struct irqaction ixp4xx_timer_irq = { .name = "IXP4xx Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = ixp4xx_timer_interrupt, }; diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c index e6b7fcd923f..2cebb287889 100644 --- a/arch/arm/mach-ixp4xx/coyote-pci.c +++ b/arch/arm/mach-ixp4xx/coyote-pci.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/irq.h> #include <asm/mach-types.h> #include <asm/hardware.h> diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c index 8b8ca80c944..d5156c043f0 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/delay.h> #include <asm/mach/pci.h> diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c index 526fb6175bc..ed527080021 100644 --- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c @@ -16,10 +16,10 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/irq.h> #include <asm/mach-types.h> #include <asm/hardware.h> -#include <asm/irq.h> #include <asm/mach/pci.h> diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c index 2d3b770d9e8..b8ebaf4a9c8 100644 --- a/arch/arm/mach-ixp4xx/nas100d-pci.c +++ b/arch/arm/mach-ixp4xx/nas100d-pci.c @@ -17,6 +17,7 @@ #include <linux/pci.h> #include <linux/init.h> +#include <linux/irq.h> #include <asm/mach/pci.h> #include <asm/mach-types.h> diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c index a3745ed37f9..81ffcae1f56 100644 --- a/arch/arm/mach-ixp4xx/nas100d-power.c +++ b/arch/arm/mach-ixp4xx/nas100d-power.c @@ -17,9 +17,9 @@ * */ -#include <linux/module.h> -#include <linux/reboot.h> #include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/module.h> #include <linux/reboot.h> #include <asm/mach-types.h> @@ -42,7 +42,7 @@ static int __init nas100d_power_init(void) set_irq_type(NAS100D_RB_IRQ, IRQT_LOW); if (request_irq(NAS100D_RB_IRQ, &nas100d_reset_handler, - SA_INTERRUPT, "NAS100D reset button", NULL) < 0) { + IRQF_DISABLED, "NAS100D reset button", NULL) < 0) { printk(KERN_DEBUG "Reset Button IRQ %d not available\n", NAS100D_RB_IRQ); diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c index 6d38e97142c..e2a2230b69f 100644 --- a/arch/arm/mach-ixp4xx/nslu2-power.c +++ b/arch/arm/mach-ixp4xx/nslu2-power.c @@ -54,7 +54,7 @@ static int __init nslu2_power_init(void) set_irq_type(NSLU2_PB_IRQ, IRQT_HIGH); if (request_irq(NSLU2_RB_IRQ, &nslu2_reset_handler, - SA_INTERRUPT, "NSLU2 reset button", NULL) < 0) { + IRQF_DISABLED, "NSLU2 reset button", NULL) < 0) { printk(KERN_DEBUG "Reset Button IRQ %d not available\n", NSLU2_RB_IRQ); @@ -63,7 +63,7 @@ static int __init nslu2_power_init(void) } if (request_irq(NSLU2_PB_IRQ, &nslu2_power_handler, - SA_INTERRUPT, "NSLU2 power button", NULL) < 0) { + IRQF_DISABLED, "NSLU2 power button", NULL) < 0) { printk(KERN_DEBUG "Power Button IRQ %d not available\n", NSLU2_PB_IRQ); diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c index ac626436e96..b7af5640ea7 100644 --- a/arch/arm/mach-l7200/core.c +++ b/arch/arm/mach-l7200/core.c @@ -7,6 +7,7 @@ */ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/device.h> #include <asm/types.h> diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index c0e6854289f..35c3606a207 100644 --- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <asm/hardware.h> #include <asm/setup.h> diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c index 1919835d961..ad5652e0150 100644 --- a/arch/arm/mach-lh7a40x/time.c +++ b/arch/arm/mach-lh7a40x/time.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/time.h> #include <asm/hardware.h> @@ -52,7 +53,7 @@ lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction lh7a40x_timer_irq = { .name = "LHA740x Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = lh7a40x_timer_interrupt, }; diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index edfbdf40c60..6d72c81b7d9 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -54,7 +54,7 @@ netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction netx_timer_irq = { .name = "NetX Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = netx_timer_interrupt, }; diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index f8d716ccc1d..d135568dc9e 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -62,6 +62,13 @@ config MACH_OMAP_PERSEUS2 Support for TI OMAP 730 Perseus2 board. Say Y here if you have such a board. +config MACH_OMAP_FSAMPLE + bool "TI F-Sample" + depends on ARCH_OMAP1 && ARCH_OMAP730 + help + Support for TI OMAP 850 F-Sample board. Say Y here if you have such + a board. + config MACH_VOICEBLUE bool "Voiceblue" depends on ARCH_OMAP1 && ARCH_OMAP15XX diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 9ea719550ad..7165f74f78d 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o +obj-$(CONFIG_MACH_OMAP_FSAMPLE) += board-fsample.o obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 73df32aac4c..8437d065ada 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -80,8 +80,15 @@ static struct omap_uart_config ams_delta_uart_config __initdata = { .enabled_uarts = 1, }; +static struct omap_usb_config ams_delta_usb_config __initdata = { + .register_host = 1, + .hmc_mode = 16, + .pins[0] = 2, +}; + static struct omap_board_config_kernel ams_delta_config[] = { { OMAP_TAG_UART, &ams_delta_uart_config }, + { OMAP_TAG_USB, &ams_delta_usb_config }, }; static struct platform_device ams_delta_led_device = { diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c new file mode 100644 index 00000000000..c753a3c5aad --- /dev/null +++ b/arch/arm/mach-omap1/board-fsample.c @@ -0,0 +1,319 @@ +/* + * linux/arch/arm/mach-omap1/board-fsample.c + * + * Modified from board-perseus2.c + * + * Original OMAP730 support by Jean Pihet <j-pihet@ti.com> + * Updated for 2.6 by Kevin Hilman <kjh@hilman.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> +#include <linux/input.h> + +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/flash.h> +#include <asm/mach/map.h> + +#include <asm/arch/tc.h> +#include <asm/arch/gpio.h> +#include <asm/arch/mux.h> +#include <asm/arch/fpga.h> +#include <asm/arch/keypad.h> +#include <asm/arch/common.h> +#include <asm/arch/board.h> +#include <asm/arch/board-fsample.h> + +static int fsample_keymap[] = { + KEY(0,0,KEY_UP), + KEY(0,1,KEY_RIGHT), + KEY(0,2,KEY_LEFT), + KEY(0,3,KEY_DOWN), + KEY(0,4,KEY_CENTER), + KEY(0,5,KEY_0_5), + KEY(1,0,KEY_SOFT2), + KEY(1,1,KEY_SEND), + KEY(1,2,KEY_END), + KEY(1,3,KEY_VOLUMEDOWN), + KEY(1,4,KEY_VOLUMEUP), + KEY(1,5,KEY_RECORD), + KEY(2,0,KEY_SOFT1), + KEY(2,1,KEY_3), + KEY(2,2,KEY_6), + KEY(2,3,KEY_9), + KEY(2,4,KEY_SHARP), + KEY(2,5,KEY_2_5), + KEY(3,0,KEY_BACK), + KEY(3,1,KEY_2), + KEY(3,2,KEY_5), + KEY(3,3,KEY_8), + KEY(3,4,KEY_0), + KEY(3,5,KEY_HEADSETHOOK), + KEY(4,0,KEY_HOME), + KEY(4,1,KEY_1), + KEY(4,2,KEY_4), + KEY(4,3,KEY_7), + KEY(4,4,KEY_STAR), + KEY(4,5,KEY_POWER), + 0 +}; + +static struct resource smc91x_resources[] = { + [0] = { + .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ + .end = H2P2_DBG_FPGA_ETHR_START + 0xf, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = INT_730_MPU_EXT_NIRQ, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mtd_partition nor_partitions[] = { + /* bootloader (U-Boot, etc) in first sector */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* bootloader params in the next sector */ + { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = 0, + }, + /* kernel */ + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + .mask_flags = 0 + }, + /* rest of flash is a file system */ + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0 + }, +}; + +static struct flash_platform_data nor_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = nor_partitions, + .nr_parts = ARRAY_SIZE(nor_partitions), +}; + +static struct resource nor_resource = { + .start = OMAP_CS0_PHYS, + .end = OMAP_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device nor_device = { + .name = "omapflash", + .id = 0, + .dev = { + .platform_data = &nor_data, + }, + .num_resources = 1, + .resource = &nor_resource, +}; + +static struct nand_platform_data nand_data = { + .options = NAND_SAMSUNG_LP_OPTIONS, +}; + +static struct resource nand_resource = { + .start = OMAP_CS3_PHYS, + .end = OMAP_CS3_PHYS + SZ_4K - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device nand_device = { + .name = "omapnand", + .id = 0, + .dev = { + .platform_data = &nand_data, + }, + .num_resources = 1, + .resource = &nand_resource, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static struct resource kp_resources[] = { + [0] = { + .start = INT_730_MPUIO_KEYPAD, + .end = INT_730_MPUIO_KEYPAD, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct omap_kp_platform_data kp_data = { + .rows = 8, + .cols = 8, + .keymap = fsample_keymap, +}; + +static struct platform_device kp_device = { + .name = "omap-keypad", + .id = -1, + .dev = { + .platform_data = &kp_data, + }, + .num_resources = ARRAY_SIZE(kp_resources), + .resource = kp_resources, +}; + +static struct platform_device lcd_device = { + .name = "lcd_p2", + .id = -1, +}; + +static struct platform_device *devices[] __initdata = { + &nor_device, + &nand_device, + &smc91x_device, + &kp_device, + &lcd_device, +}; + +#define P2_NAND_RB_GPIO_PIN 62 + +static int nand_dev_ready(struct nand_platform_data *data) +{ + return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN); +} + +static struct omap_uart_config fsample_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1)), +}; + +static struct omap_lcd_config fsample_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct omap_board_config_kernel fsample_config[] = { + { OMAP_TAG_UART, &fsample_uart_config }, + { OMAP_TAG_LCD, &fsample_lcd_config }, +}; + +static void __init omap_fsample_init(void) +{ + if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN))) + nand_data.dev_ready = nand_dev_ready; + + omap_cfg_reg(L3_1610_FLASH_CS2B_OE); + omap_cfg_reg(M8_1610_FLASH_CS2B_WE); + + platform_add_devices(devices, ARRAY_SIZE(devices)); + + omap_board_config = fsample_config; + omap_board_config_size = ARRAY_SIZE(fsample_config); + omap_serial_init(); +} + +static void __init fsample_init_smc91x(void) +{ + fpga_write(1, H2P2_DBG_FPGA_LAN_RESET); + mdelay(50); + fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1, + H2P2_DBG_FPGA_LAN_RESET); + mdelay(50); +} + +void omap_fsample_init_irq(void) +{ + omap1_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); + fsample_init_smc91x(); +} + +/* Only FPGA needs to be mapped here. All others are done with ioremap */ +static struct map_desc omap_fsample_io_desc[] __initdata = { + { + .virtual = H2P2_DBG_FPGA_BASE, + .pfn = __phys_to_pfn(H2P2_DBG_FPGA_START), + .length = H2P2_DBG_FPGA_SIZE, + .type = MT_DEVICE + }, + { + .virtual = FSAMPLE_CPLD_BASE, + .pfn = __phys_to_pfn(FSAMPLE_CPLD_START), + .length = FSAMPLE_CPLD_SIZE, + .type = MT_DEVICE + } +}; + +static void __init omap_fsample_map_io(void) +{ + omap1_map_common_io(); + iotable_init(omap_fsample_io_desc, + ARRAY_SIZE(omap_fsample_io_desc)); + + /* Early, board-dependent init */ + + /* + * Hold GSM Reset until needed + */ + omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL); + + /* + * UARTs -> done automagically by 8250 driver + */ + + /* + * CSx timings, GPIO Mux ... setup + */ + + /* Flash: CS0 timings setup */ + omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0); + omap_writel(0x00000088, OMAP730_FLASH_ACFG_0); + + /* + * Ethernet support through the debug board + * CS1 timings setup + */ + omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1); + omap_writel(0x00000000, OMAP730_FLASH_ACFG_1); + + /* + * Configure MPU_EXT_NIRQ IO in IO_CONF9 register, + * It is used as the Ethernet controller interrupt + */ + omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); +} + +MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample") +/* Maintainer: Brian Swetland <swetland@google.com> */ + .phys_io = 0xfff00000, + .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, + .boot_params = 0x10000100, + .map_io = omap_fsample_map_io, + .init_irq = omap_fsample_init_irq, + .init_machine = omap_fsample_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index e90c137a4cf..4cbc62db5b5 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c @@ -37,6 +37,8 @@ #include <asm/arch/usb.h> #include <asm/arch/keypad.h> #include <asm/arch/common.h> +#include <asm/arch/mcbsp.h> +#include <asm/arch/omap-alsa.h> static int innovator_keymap[] = { KEY(0, 0, KEY_F1), @@ -112,6 +114,42 @@ static struct platform_device innovator_flash_device = { .resource = &innovator_flash_resource, }; +#define DEFAULT_BITPERSAMPLE 16 + +static struct omap_mcbsp_reg_cfg mcbsp_regs = { + .spcr2 = FREE | FRST | GRST | XRST | XINTM(3), + .spcr1 = RINTM(3) | RRST, + .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) | + RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0), + .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16), + .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) | + XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG, + .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16), + .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1), + .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1), + /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */ + .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */ +}; + +static struct omap_alsa_codec_config alsa_config = { + .name = "OMAP Innovator AIC23", + .mcbsp_regs_alsa = &mcbsp_regs, + .codec_configure_dev = NULL, // aic23_configure, + .codec_set_samplerate = NULL, // aic23_set_samplerate, + .codec_clock_setup = NULL, // aic23_clock_setup, + .codec_clock_on = NULL, // aic23_clock_on, + .codec_clock_off = NULL, // aic23_clock_off, + .get_default_samplerate = NULL, // aic23_get_default_samplerate, +}; + +static struct platform_device innovator_mcbsp1_device = { + .name = "omap_alsa_mcbsp", + .id = 1, + .dev = { + .platform_data = &alsa_config, + }, +}; + static struct resource innovator_kp_resources[] = { [0] = { .start = INT_KEYBOARD, @@ -139,6 +177,10 @@ static struct platform_device innovator_kp_device = { #ifdef CONFIG_ARCH_OMAP15XX +#include <linux/spi/spi.h> +#include <linux/spi/ads7846.h> + + /* Only FPGA needs to be mapped here. All others are done with ioremap */ static struct map_desc innovator1510_io_desc[] __initdata = { { @@ -174,13 +216,44 @@ static struct platform_device innovator1510_lcd_device = { .id = -1, }; +static struct platform_device innovator1510_spi_device = { + .name = "spi_inn1510", + .id = -1, +}; + static struct platform_device *innovator1510_devices[] __initdata = { &innovator_flash_device, &innovator1510_smc91x_device, + &innovator_mcbsp1_device, &innovator_kp_device, &innovator1510_lcd_device, + &innovator1510_spi_device, }; +static int innovator_get_pendown_state(void) +{ + return !(fpga_read(OMAP1510_FPGA_TOUCHSCREEN) & (1 << 5)); +} + +static const struct ads7846_platform_data innovator1510_ts_info = { + .model = 7846, + .vref_delay_usecs = 100, /* internal, no capacitor */ + .x_plate_ohms = 419, + .y_plate_ohms = 486, + .get_pendown_state = innovator_get_pendown_state, +}; + +static struct spi_board_info __initdata innovator1510_boardinfo[] = { { + /* FPGA (bus "10") CS0 has an ads7846e */ + .modalias = "ads7846", + .platform_data = &innovator1510_ts_info, + .irq = OMAP1510_INT_FPGA_TS, + .max_speed_hz = 120000 /* max sample rate at 3V */ + * 26 /* command + data + overhead */, + .bus_num = 10, + .chip_select = 0, +} }; + #endif /* CONFIG_ARCH_OMAP15XX */ #ifdef CONFIG_ARCH_OMAP16XX @@ -311,6 +384,8 @@ static void __init innovator_init(void) #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap1510()) { platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices)); + spi_register_board_info(innovator1510_boardinfo, + ARRAY_SIZE(innovator1510_boardinfo)); } #endif #ifdef CONFIG_ARCH_OMAP16XX diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 1160093e8ef..b742261c97a 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -29,11 +29,10 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> -#include <linux/input.h> #include <asm/hardware.h> #include <asm/mach-types.h> @@ -45,25 +44,10 @@ #include <asm/arch/usb.h> #include <asm/arch/mux.h> #include <asm/arch/tc.h> -#include <asm/arch/keypad.h> #include <asm/arch/common.h> #include <asm/arch/mcbsp.h> #include <asm/arch/omap-alsa.h> -static int osk_keymap[] = { - KEY(0, 0, KEY_F1), - KEY(0, 3, KEY_UP), - KEY(1, 1, KEY_LEFTCTRL), - KEY(1, 2, KEY_LEFT), - KEY(2, 0, KEY_SPACE), - KEY(2, 1, KEY_ESC), - KEY(2, 2, KEY_DOWN), - KEY(3, 2, KEY_ENTER), - KEY(3, 3, KEY_RIGHT), - 0 -}; - - static struct mtd_partition osk_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ { @@ -181,48 +165,17 @@ static struct omap_alsa_codec_config alsa_config = { static struct platform_device osk5912_mcbsp1_device = { .name = "omap_alsa_mcbsp", - .id = 1, + .id = 1, .dev = { .platform_data = &alsa_config, }, }; -static struct resource osk5912_kp_resources[] = { - [0] = { - .start = INT_KEYBOARD, - .end = INT_KEYBOARD, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct omap_kp_platform_data osk_kp_data = { - .rows = 8, - .cols = 8, - .keymap = osk_keymap, -}; - -static struct platform_device osk5912_kp_device = { - .name = "omap-keypad", - .id = -1, - .dev = { - .platform_data = &osk_kp_data, - }, - .num_resources = ARRAY_SIZE(osk5912_kp_resources), - .resource = osk5912_kp_resources, -}; - -static struct platform_device osk5912_lcd_device = { - .name = "lcd_osk", - .id = -1, -}; - static struct platform_device *osk5912_devices[] __initdata = { &osk5912_flash_device, &osk5912_smc91x_device, &osk5912_cf_device, &osk5912_mcbsp1_device, - &osk5912_kp_device, - &osk5912_lcd_device, }; static void __init osk_init_smc91x(void) @@ -276,18 +229,100 @@ static struct omap_uart_config osk_uart_config __initdata = { .enabled_uarts = (1 << 0), }; +#ifdef CONFIG_OMAP_OSK_MISTRAL static struct omap_lcd_config osk_lcd_config __initdata = { .ctrl_name = "internal", }; +#endif static struct omap_board_config_kernel osk_config[] = { { OMAP_TAG_USB, &osk_usb_config }, { OMAP_TAG_UART, &osk_uart_config }, +#ifdef CONFIG_OMAP_OSK_MISTRAL { OMAP_TAG_LCD, &osk_lcd_config }, +#endif }; #ifdef CONFIG_OMAP_OSK_MISTRAL +#include <linux/input.h> +#include <linux/spi/spi.h> +#include <linux/spi/ads7846.h> + +#include <asm/arch/keypad.h> + +static const int osk_keymap[] = { + /* KEY(col, row, code) */ + KEY(0, 0, KEY_F1), /* SW4 */ + KEY(0, 3, KEY_UP), /* (sw2/up) */ + KEY(1, 1, KEY_LEFTCTRL), /* SW5 */ + KEY(1, 2, KEY_LEFT), /* (sw2/left) */ + KEY(2, 0, KEY_SPACE), /* SW3 */ + KEY(2, 1, KEY_ESC), /* SW6 */ + KEY(2, 2, KEY_DOWN), /* (sw2/down) */ + KEY(3, 2, KEY_ENTER), /* (sw2/select) */ + KEY(3, 3, KEY_RIGHT), /* (sw2/right) */ + 0 +}; + +static struct omap_kp_platform_data osk_kp_data = { + .rows = 8, + .cols = 8, + .keymap = (int *) osk_keymap, +}; + +static struct resource osk5912_kp_resources[] = { + [0] = { + .start = INT_KEYBOARD, + .end = INT_KEYBOARD, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device osk5912_kp_device = { + .name = "omap-keypad", + .id = -1, + .dev = { + .platform_data = &osk_kp_data, + }, + .num_resources = ARRAY_SIZE(osk5912_kp_resources), + .resource = osk5912_kp_resources, +}; + +static struct platform_device osk5912_lcd_device = { + .name = "lcd_osk", + .id = -1, +}; + +static struct platform_device *mistral_devices[] __initdata = { + &osk5912_kp_device, + &osk5912_lcd_device, +}; + +static int mistral_get_pendown_state(void) +{ + return !omap_get_gpio_datain(4); +} + +static const struct ads7846_platform_data mistral_ts_info = { + .model = 7846, + .vref_delay_usecs = 100, /* internal, no capacitor */ + .x_plate_ohms = 419, + .y_plate_ohms = 486, + .get_pendown_state = mistral_get_pendown_state, +}; + +static struct spi_board_info __initdata mistral_boardinfo[] = { { + /* MicroWire (bus 2) CS0 has an ads7846e */ + .modalias = "ads7846", + .platform_data = &mistral_ts_info, + .irq = OMAP_GPIO_IRQ(4), + .max_speed_hz = 120000 /* max sample rate at 3V */ + * 26 /* command + data + overhead */, + .bus_num = 2, + .chip_select = 0, +} }; + #ifdef CONFIG_PM static irqreturn_t osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs) @@ -298,14 +333,18 @@ osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs) static void __init osk_mistral_init(void) { - /* FIXME here's where to feed in framebuffer, touchpad, and - * keyboard setup ... not in the drivers for those devices! - * - * NOTE: we could actually tell if there's a Mistral board + /* NOTE: we could actually tell if there's a Mistral board * attached, e.g. by trying to read something from the ads7846. - * But this is too early for that... + * But this arch_init() code is too early for that, since we + * can't talk to the ads or even the i2c eeprom. */ + // omap_cfg_reg(P19_1610_GPIO6); // BUSY + omap_cfg_reg(P20_1610_GPIO4); // PENIRQ + set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING); + spi_register_board_info(mistral_boardinfo, + ARRAY_SIZE(mistral_boardinfo)); + /* the sideways button (SW1) is for use as a "wakeup" button */ omap_cfg_reg(N15_1610_MPUIO2); if (omap_request_gpio(OMAP_MPUIO(2)) == 0) { @@ -318,7 +357,7 @@ static void __init osk_mistral_init(void) */ ret = request_irq(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), &osk_mistral_wake_interrupt, - SA_SHIRQ, "mistral_wakeup", + IRQF_SHARED, "mistral_wakeup", &osk_mistral_wake_interrupt); if (ret != 0) { omap_free_gpio(OMAP_MPUIO(2)); @@ -329,6 +368,8 @@ static void __init osk_mistral_init(void) #endif } else printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n"); + + platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices)); } #else static void __init osk_mistral_init(void) { } diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 619db18144e..f1958e882e8 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -1,3 +1,4 @@ +//kernel/linux-omap-fsample/arch/arm/mach-omap1/clock.c#2 - edit change 3808 (text) /* * linux/arch/arm/mach-omap1/clock.c * @@ -20,6 +21,7 @@ #include <asm/io.h> +#include <asm/arch/cpu.h> #include <asm/arch/usb.h> #include <asm/arch/clock.h> #include <asm/arch/sram.h> @@ -270,8 +272,12 @@ static int omap1_select_table_rate(struct clk * clk, unsigned long rate) /* * In most cases we should not need to reprogram DPLL. * Reprogramming the DPLL is tricky, it must be done from SRAM. + * (on 730, bit 13 must always be 1) */ - omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); + if (cpu_is_omap730()) + omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val | 0x2000); + else + omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); ck_dpll1.rate = ptr->pll_rate; propagate_rate(&ck_dpll1); @@ -748,7 +754,7 @@ int __init omap1_clk_init(void) printk(KERN_ERR "System frequencies not set. Check your config.\n"); /* Guess sane values (60MHz) */ omap_writew(0x2290, DPLL_CTL); - omap_writew(0x1005, ARM_CKCTL); + omap_writew(cpu_is_omap730() ? 0x3005 : 0x1005, ARM_CKCTL); ck_dpll1.rate = 60000000; propagate_rate(&ck_dpll1); } @@ -761,13 +767,17 @@ int __init omap1_clk_init(void) ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); -#ifdef CONFIG_MACH_OMAP_PERSEUS2 +#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE) /* Select slicer output as OMAP input clock */ omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); #endif /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ - omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); + /* (on 730, bit 13 must not be cleared) */ + if (cpu_is_omap730()) + omap_writew(omap_readw(ARM_CKCTL) & 0x2fff, ARM_CKCTL); + else + omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); /* Put DSP/MPUI into reset until needed */ omap_writew(0, ARM_RSTCT1); diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c index 880cd2d8f4a..34eb79ee6e6 100644 --- a/arch/arm/mach-omap1/fpga.c +++ b/arch/arm/mach-omap1/fpga.c @@ -133,7 +133,7 @@ static struct irqchip omap_fpga_irq = { * mask_ack routine for all of the FPGA interrupts has been changed from * fpga_mask_ack_irq() to fpga_ack_irq() so that the specific FPGA interrupt * being serviced is left unmasked. We can do this because the FPGA cascade - * interrupt is installed with the SA_INTERRUPT flag, which leaves all + * interrupt is installed with the IRQF_DISABLED flag, which leaves all * interrupts masked at the CPU while an FPGA interrupt handler executes. * * Limited testing indicates that this workaround appears to be effective diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c index ddf6b07dc9c..cd76185bab7 100644 --- a/arch/arm/mach-omap1/pm.c +++ b/arch/arm/mach-omap1/pm.c @@ -1,3 +1,4 @@ +//kernel/linux-omap-fsample/arch/arm/mach-omap1/pm.c#3 - integrate change 4545 (text) /* * linux/arch/arm/mach-omap1/pm.c * @@ -50,6 +51,7 @@ #include <asm/mach/irq.h> #include <asm/mach-types.h> +#include <asm/arch/cpu.h> #include <asm/arch/irqs.h> #include <asm/arch/clock.h> #include <asm/arch/sram.h> @@ -326,8 +328,9 @@ void omap_pm_suspend(void) /* stop DSP */ omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1); - /* shut down dsp_ck */ - omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL); + /* shut down dsp_ck */ + if (!cpu_is_omap730()) + omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL); /* temporarily enabling api_ck to access DSP registers */ omap_writew(omap_readw(ARM_IDLECT2) | 1 << EN_APICK, ARM_IDLECT2); @@ -687,7 +690,7 @@ static irqreturn_t omap_wakeup_interrupt(int irq, void * dev, static struct irqaction omap_wakeup_irq = { .name = "peripheral wakeup", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .handler = omap_wakeup_interrupt }; diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index 56319742aa1..976edfb882e 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/delay.h> #include <linux/serial.h> #include <linux/tty.h> @@ -252,7 +253,7 @@ static void __init omap_serial_set_port_wakeup(int gpio_nr) } omap_set_gpio_direction(gpio_nr, 1); ret = request_irq(OMAP_GPIO_IRQ(gpio_nr), &omap_serial_wake_interrupt, - SA_TRIGGER_RISING, "serial wakeup", NULL); + IRQF_TRIGGER_RISING, "serial wakeup", NULL); if (ret) { omap_free_gpio(gpio_nr); printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n", diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index c2d3205bc59..4d91b9f5108 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -93,7 +93,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc) * will break. On P2, the timer count rate is 6.5 MHz after programming PTV * with 0. This divides the 13MHz input by 2, and is undocumented. */ -#ifdef CONFIG_MACH_OMAP_PERSEUS2 +#if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE) /* REVISIT: This ifdef construct should be replaced by a query to clock * framework to see if timer base frequency is 12.0, 13.0 or 19.2 MHz. */ @@ -177,7 +177,7 @@ static irqreturn_t omap_mpu_timer_interrupt(int irq, void *dev_id, static struct irqaction omap_mpu_timer_irq = { .name = "mpu timer", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = omap_mpu_timer_interrupt, }; @@ -191,7 +191,7 @@ static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id, static struct irqaction omap_mpu_timer1_irq = { .name = "mpu timer1 overflow", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .handler = omap_mpu_timer1_interrupt, }; diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 537dd2e6d38..aab97ccf1e6 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -8,6 +8,7 @@ config ARCH_OMAP24XX config ARCH_OMAP2420 bool "OMAP2420 support" depends on ARCH_OMAP24XX + select OMAP_DM_TIMER comment "OMAP Board Type" depends on ARCH_OMAP2 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 111eaa64258..266d88e77bd 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -3,12 +3,13 @@ # # Common support -obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o serial.o +obj-y := irq.o id.o io.o sram-fn.o memory.o prcm.o clock.o mux.o devices.o \ + serial.o gpmc.o obj-$(CONFIG_OMAP_MPU_TIMER) += timer-gp.o # Power Management -obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o # Specific board support obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 6c6ba172cdf..7993b7bae2b 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -234,17 +234,17 @@ static void __init apollon_sw_init(void) set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING); if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt, - SA_SHIRQ, "enter sw", + IRQF_SHARED, "enter sw", &apollon_sw_interrupt)) return; set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING); if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt, - SA_SHIRQ, "up sw", + IRQF_SHARED, "up sw", &apollon_sw_interrupt)) return; set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING); if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt, - SA_SHIRQ, "down sw", + IRQF_SHARED, "down sw", &apollon_sw_interrupt)) return; } diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 7edf0f69da1..d1b648a4efb 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -659,26 +659,35 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate) /* Isolate control register */ div_sel = (SRC_RATE_SEL_MASK & clk->flags); - div_off = clk->src_offset; + div_off = clk->rate_offset; validrate = omap2_clksel_round_rate(clk, rate, &new_div); - if(validrate != rate) + if (validrate != rate) return(ret); field_val = omap2_get_clksel(&div_sel, &field_mask, clk); if (div_sel == 0) return ret; - if(clk->flags & CM_SYSCLKOUT_SEL1){ - switch(new_div){ - case 16: field_val = 4; break; - case 8: field_val = 3; break; - case 4: field_val = 2; break; - case 2: field_val = 1; break; - case 1: field_val = 0; break; + if (clk->flags & CM_SYSCLKOUT_SEL1) { + switch (new_div) { + case 16: + field_val = 4; + break; + case 8: + field_val = 3; + break; + case 4: + field_val = 2; + break; + case 2: + field_val = 1; + break; + case 1: + field_val = 0; + break; } - } - else + } else field_val = new_div; reg = (void __iomem *)div_sel; @@ -743,7 +752,7 @@ static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset, val = 0x2; break; case CM_WKUP_SEL1: - src_reg_addr = (u32)&CM_CLKSEL2_CORE; + src_reg_addr = (u32)&CM_CLKSEL_WKUP; mask = 0x3; if (src_clk == &func_32k_ck) val = 0x0; @@ -783,9 +792,9 @@ static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset, val = 0; if (src_clk == &sys_ck) val = 1; - if (src_clk == &func_54m_ck) - val = 2; if (src_clk == &func_96m_ck) + val = 2; + if (src_clk == &func_54m_ck) val = 3; break; } diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 6c78d471fab..2781dfbc516 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -1062,7 +1062,7 @@ static struct clk gpt2_ick = { .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */ - .enable_bit = 0, + .enable_bit = 4, .recalc = &omap2_followparent_recalc, }; diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 4842ffe2670..aa4322451e8 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -104,6 +104,51 @@ static inline void omap_init_sti(void) static inline void omap_init_sti(void) {} #endif +#if defined(CONFIG_SPI_OMAP24XX) + +#include <asm/arch/mcspi.h> + +#define OMAP2_MCSPI1_BASE 0x48098000 +#define OMAP2_MCSPI2_BASE 0x4809a000 + +/* FIXME: use resources instead */ + +static struct omap2_mcspi_platform_config omap2_mcspi1_config = { + .base = io_p2v(OMAP2_MCSPI1_BASE), + .num_cs = 4, +}; + +struct platform_device omap2_mcspi1 = { + .name = "omap2_mcspi", + .id = 1, + .dev = { + .platform_data = &omap2_mcspi1_config, + }, +}; + +static struct omap2_mcspi_platform_config omap2_mcspi2_config = { + .base = io_p2v(OMAP2_MCSPI2_BASE), + .num_cs = 2, +}; + +struct platform_device omap2_mcspi2 = { + .name = "omap2_mcspi", + .id = 2, + .dev = { + .platform_data = &omap2_mcspi2_config, + }, +}; + +static void omap_init_mcspi(void) +{ + platform_device_register(&omap2_mcspi1); + platform_device_register(&omap2_mcspi2); +} + +#else +static inline void omap_init_mcspi(void) {} +#endif + /*-------------------------------------------------------------------------*/ static int __init omap2_init_devices(void) @@ -112,6 +157,7 @@ static int __init omap2_init_devices(void) * in alphabetical order so they're easier to sort through. */ omap_init_i2c(); + omap_init_mcspi(); omap_init_sti(); return 0; diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c new file mode 100644 index 00000000000..c7a48f921fe --- /dev/null +++ b/arch/arm/mach-omap2/gpmc.c @@ -0,0 +1,209 @@ +/* + * GPMC support functions + * + * Copyright (C) 2005-2006 Nokia Corporation + * + * Author: Juha Yrjola + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <asm/io.h> +#include <asm/arch/gpmc.h> + +#undef DEBUG + +#define GPMC_BASE 0x6800a000 +#define GPMC_REVISION 0x00 +#define GPMC_SYSCONFIG 0x10 +#define GPMC_SYSSTATUS 0x14 +#define GPMC_IRQSTATUS 0x18 +#define GPMC_IRQENABLE 0x1c +#define GPMC_TIMEOUT_CONTROL 0x40 +#define GPMC_ERR_ADDRESS 0x44 +#define GPMC_ERR_TYPE 0x48 +#define GPMC_CONFIG 0x50 +#define GPMC_STATUS 0x54 +#define GPMC_PREFETCH_CONFIG1 0x1e0 +#define GPMC_PREFETCH_CONFIG2 0x1e4 +#define GPMC_PREFETCH_CONTROL 0x1e8 +#define GPMC_PREFETCH_STATUS 0x1f0 +#define GPMC_ECC_CONFIG 0x1f4 +#define GPMC_ECC_CONTROL 0x1f8 +#define GPMC_ECC_SIZE_CONFIG 0x1fc + +#define GPMC_CS0 0x60 +#define GPMC_CS_SIZE 0x30 + +static void __iomem *gpmc_base = + (void __iomem *) IO_ADDRESS(GPMC_BASE); +static void __iomem *gpmc_cs_base = + (void __iomem *) IO_ADDRESS(GPMC_BASE) + GPMC_CS0; + +static struct clk *gpmc_l3_clk; + +static void gpmc_write_reg(int idx, u32 val) +{ + __raw_writel(val, gpmc_base + idx); +} + +static u32 gpmc_read_reg(int idx) +{ + return __raw_readl(gpmc_base + idx); +} + +void gpmc_cs_write_reg(int cs, int idx, u32 val) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx; + __raw_writel(val, reg_addr); +} + +u32 gpmc_cs_read_reg(int cs, int idx) +{ + return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx); +} + +/* TODO: Add support for gpmc_fck to clock framework and use it */ +static unsigned long gpmc_get_fclk_period(void) +{ + /* In picoseconds */ + return 1000000000 / ((clk_get_rate(gpmc_l3_clk)) / 1000); +} + +unsigned int gpmc_ns_to_ticks(unsigned int time_ns) +{ + unsigned long tick_ps; + + /* Calculate in picosecs to yield more exact results */ + tick_ps = gpmc_get_fclk_period(); + + return (time_ns * 1000 + tick_ps - 1) / tick_ps; +} + +#ifdef DEBUG +static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, + int time, const char *name) +#else +static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, + int time) +#endif +{ + u32 l; + int ticks, mask, nr_bits; + + if (time == 0) + ticks = 0; + else + ticks = gpmc_ns_to_ticks(time); + nr_bits = end_bit - st_bit + 1; + if (ticks >= 1 << nr_bits) + return -1; + + mask = (1 << nr_bits) - 1; + l = gpmc_cs_read_reg(cs, reg); +#ifdef DEBUG + printk(KERN_INFO "GPMC CS%d: %-10s: %d ticks, %3lu ns (was %i ticks)\n", + cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000, + (l >> st_bit) & mask); +#endif + l &= ~(mask << st_bit); + l |= ticks << st_bit; + gpmc_cs_write_reg(cs, reg, l); + + return 0; +} + +#ifdef DEBUG +#define GPMC_SET_ONE(reg, st, end, field) \ + if (set_gpmc_timing_reg(cs, (reg), (st), (end), \ + t->field, #field) < 0) \ + return -1 +#else +#define GPMC_SET_ONE(reg, st, end, field) \ + if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \ + return -1 +#endif + +int gpmc_cs_calc_divider(int cs, unsigned int sync_clk) +{ + int div; + u32 l; + + l = sync_clk * 1000 + (gpmc_get_fclk_period() - 1); + div = l / gpmc_get_fclk_period(); + if (div > 4) + return -1; + if (div < 0) + div = 1; + + return div; +} + +int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) +{ + int div; + u32 l; + + div = gpmc_cs_calc_divider(cs, t->sync_clk); + if (div < 0) + return -1; + + GPMC_SET_ONE(GPMC_CS_CONFIG2, 0, 3, cs_on); + GPMC_SET_ONE(GPMC_CS_CONFIG2, 8, 12, cs_rd_off); + GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off); + + GPMC_SET_ONE(GPMC_CS_CONFIG3, 0, 3, adv_on); + GPMC_SET_ONE(GPMC_CS_CONFIG3, 8, 12, adv_rd_off); + GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off); + + GPMC_SET_ONE(GPMC_CS_CONFIG4, 0, 3, oe_on); + GPMC_SET_ONE(GPMC_CS_CONFIG4, 8, 12, oe_off); + GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on); + GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off); + + GPMC_SET_ONE(GPMC_CS_CONFIG5, 0, 4, rd_cycle); + GPMC_SET_ONE(GPMC_CS_CONFIG5, 8, 12, wr_cycle); + GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access); + + GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + +#ifdef DEBUG + printk(KERN_INFO "GPMC CS%d CLK period is %lu (div %d)\n", + cs, gpmc_get_fclk_period(), div); +#endif + + l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + l &= ~0x03; + l |= (div - 1); + + return 0; +} + +unsigned long gpmc_cs_get_base_addr(int cs) +{ + return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24; +} + +void __init gpmc_init(void) +{ + u32 l; + + gpmc_l3_clk = clk_get(NULL, "core_l3_ck"); + BUG_ON(IS_ERR(gpmc_l3_clk)); + + l = gpmc_read_reg(GPMC_REVISION); + printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); + /* Set smart idle mode and automatic L3 clock gating */ + l = gpmc_read_reg(GPMC_SYSCONFIG); + l &= 0x03 << 3; + l |= (0x02 << 3) | (1 << 0); + gpmc_write_reg(GPMC_SYSCONFIG, l); +} diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 20dd6e74e91..a0728c33e5d 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -26,6 +26,7 @@ extern void omap_sram_init(void); extern int omap2_clk_init(void); extern void omap2_check_revision(void); +extern void gpmc_init(void); /* * The machine specific code may provide the extra mapping besides the @@ -66,4 +67,5 @@ void __init omap2_init_common_hw(void) { omap2_mux_init(); omap2_clk_init(); + gpmc_init(); } diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 4c5f2c04883..60ef084faff 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -52,6 +52,12 @@ MUX_CFG_24XX("W19_24XX_SYS_NIRQ", 0x12c, 0, 1, 1, 1) /* 24xx clocks */ MUX_CFG_24XX("W14_24XX_SYS_CLKOUT", 0x137, 0, 1, 1, 1) +/* 24xx GPMC wait pin monitoring */ +MUX_CFG_24XX("L3_GPMC_WAIT0", 0x09a, 0, 1, 1, 1) +MUX_CFG_24XX("N7_GPMC_WAIT1", 0x09b, 0, 1, 1, 1) +MUX_CFG_24XX("M1_GPMC_WAIT2", 0x09c, 0, 1, 1, 1) +MUX_CFG_24XX("P1_GPMC_WAIT3", 0x09d, 0, 1, 1, 1) + /* 24xx McBSP */ MUX_CFG_24XX("Y15_24XX_MCBSP2_CLKX", 0x124, 1, 1, 0, 1) MUX_CFG_24XX("R14_24XX_MCBSP2_FSX", 0x125, 1, 1, 0, 1) @@ -59,18 +65,38 @@ MUX_CFG_24XX("W15_24XX_MCBSP2_DR", 0x126, 1, 1, 0, 1) MUX_CFG_24XX("V15_24XX_MCBSP2_DX", 0x127, 1, 1, 0, 1) /* 24xx GPIO */ -MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1) +MUX_CFG_24XX("M21_242X_GPIO11", 0x0c9, 3, 1, 1, 1) MUX_CFG_24XX("AA10_242X_GPIO13", 0x0e5, 3, 0, 0, 1) -MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1) -MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1) -MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1) +MUX_CFG_24XX("AA6_242X_GPIO14", 0x0e6, 3, 0, 0, 1) +MUX_CFG_24XX("AA4_242X_GPIO15", 0x0e7, 3, 0, 0, 1) +MUX_CFG_24XX("Y11_242X_GPIO16", 0x0e8, 3, 0, 0, 1) MUX_CFG_24XX("AA12_242X_GPIO17", 0x0e9, 3, 0, 0, 1) -MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1) +MUX_CFG_24XX("AA8_242X_GPIO58", 0x0ea, 3, 0, 0, 1) MUX_CFG_24XX("Y20_24XX_GPIO60", 0x12c, 3, 0, 0, 1) -MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1) +MUX_CFG_24XX("W4__24XX_GPIO74", 0x0f2, 3, 0, 0, 1) MUX_CFG_24XX("M15_24XX_GPIO92", 0x10a, 3, 0, 0, 1) MUX_CFG_24XX("V14_24XX_GPIO117", 0x128, 3, 1, 0, 1) +/* 242x DBG GPIO */ +MUX_CFG_24XX("V4_242X_GPIO49", 0xd3, 3, 0, 0, 1) +MUX_CFG_24XX("W2_242X_GPIO50", 0xd4, 3, 0, 0, 1) +MUX_CFG_24XX("U4_242X_GPIO51", 0xd5, 3, 0, 0, 1) +MUX_CFG_24XX("V3_242X_GPIO52", 0xd6, 3, 0, 0, 1) +MUX_CFG_24XX("V2_242X_GPIO53", 0xd7, 3, 0, 0, 1) +MUX_CFG_24XX("V6_242X_GPIO53", 0xcf, 3, 0, 0, 1) +MUX_CFG_24XX("T4_242X_GPIO54", 0xd8, 3, 0, 0, 1) +MUX_CFG_24XX("Y4_242X_GPIO54", 0xd0, 3, 0, 0, 1) +MUX_CFG_24XX("T3_242X_GPIO55", 0xd9, 3, 0, 0, 1) +MUX_CFG_24XX("U2_242X_GPIO56", 0xda, 3, 0, 0, 1) + +/* 24xx external DMA requests */ +MUX_CFG_24XX("AA10_242X_DMAREQ0", 0x0e5, 2, 0, 0, 1) +MUX_CFG_24XX("AA6_242X_DMAREQ1", 0x0e6, 2, 0, 0, 1) +MUX_CFG_24XX("E4_242X_DMAREQ2", 0x074, 2, 0, 0, 1) +MUX_CFG_24XX("G4_242X_DMAREQ3", 0x073, 2, 0, 0, 1) +MUX_CFG_24XX("D3_242X_DMAREQ4", 0x072, 2, 0, 0, 1) +MUX_CFG_24XX("E3_242X_DMAREQ5", 0x071, 2, 0, 0, 1) + /* TSC IRQ */ MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1) diff --git a/arch/arm/mach-omap2/pm-domain.c b/arch/arm/mach-omap2/pm-domain.c new file mode 100644 index 00000000000..5e20e740cde --- /dev/null +++ b/arch/arm/mach-omap2/pm-domain.c @@ -0,0 +1,300 @@ +/* + * linux/arch/arm/mach-omap2/pm-domain.c + * + * Power domain functions for OMAP2 + * + * Copyright (C) 2006 Nokia Corporation + * Tony Lindgren <tony@atomide.com> + * + * Some code based on earlier OMAP2 sample PM code + * Copyright (C) 2005 Texas Instruments, Inc. + * Richard Woodruff <r-woodruff2@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/clk.h> + +#include <asm/io.h> + +#include "prcm-regs.h" + +/* Power domain offsets */ +#define PM_MPU_OFFSET 0x100 +#define PM_CORE_OFFSET 0x200 +#define PM_GFX_OFFSET 0x300 +#define PM_WKUP_OFFSET 0x400 /* Autoidle only */ +#define PM_PLL_OFFSET 0x500 /* Autoidle only */ +#define PM_DSP_OFFSET 0x800 +#define PM_MDM_OFFSET 0xc00 + +/* Power domain wake-up dependency control register */ +#define PM_WKDEP_OFFSET 0xc8 +#define EN_MDM (1 << 5) +#define EN_WKUP (1 << 4) +#define EN_GFX (1 << 3) +#define EN_DSP (1 << 2) +#define EN_MPU (1 << 1) +#define EN_CORE (1 << 0) + +/* Core power domain state transition control register */ +#define PM_PWSTCTRL_OFFSET 0xe0 +#define FORCESTATE (1 << 18) /* Only for DSP & GFX */ +#define MEM4RETSTATE (1 << 6) +#define MEM3RETSTATE (1 << 5) +#define MEM2RETSTATE (1 << 4) +#define MEM1RETSTATE (1 << 3) +#define LOGICRETSTATE (1 << 2) /* Logic is retained */ +#define POWERSTATE_OFF 0x3 +#define POWERSTATE_RETENTION 0x1 +#define POWERSTATE_ON 0x0 + +/* Power domain state register */ +#define PM_PWSTST_OFFSET 0xe4 + +/* Hardware supervised state transition control register */ +#define CM_CLKSTCTRL_OFFSET 0x48 +#define AUTOSTAT_MPU (1 << 0) /* MPU */ +#define AUTOSTAT_DSS (1 << 2) /* Core */ +#define AUTOSTAT_L4 (1 << 1) /* Core */ +#define AUTOSTAT_L3 (1 << 0) /* Core */ +#define AUTOSTAT_GFX (1 << 0) /* GFX */ +#define AUTOSTAT_IVA (1 << 8) /* 2420 IVA in DSP domain */ +#define AUTOSTAT_DSP (1 << 0) /* DSP */ +#define AUTOSTAT_MDM (1 << 0) /* MDM */ + +/* Automatic control of interface clock idling */ +#define CM_AUTOIDLE1_OFFSET 0x30 +#define CM_AUTOIDLE2_OFFSET 0x34 /* Core only */ +#define CM_AUTOIDLE3_OFFSET 0x38 /* Core only */ +#define CM_AUTOIDLE4_OFFSET 0x3c /* Core only */ +#define AUTO_54M(x) (((x) & 0x3) << 6) +#define AUTO_96M(x) (((x) & 0x3) << 2) +#define AUTO_DPLL(x) (((x) & 0x3) << 0) +#define AUTO_STOPPED 0x3 +#define AUTO_BYPASS_FAST 0x2 /* DPLL only */ +#define AUTO_BYPASS_LOW_POWER 0x1 /* DPLL only */ +#define AUTO_DISABLED 0x0 + +/* Voltage control PRCM_VOLTCTRL bits */ +#define AUTO_EXTVOLT (1 << 15) +#define FORCE_EXTVOLT (1 << 14) +#define SETOFF_LEVEL(x) (((x) & 0x3) << 12) +#define MEMRETCTRL (1 << 8) +#define SETRET_LEVEL(x) (((x) & 0x3) << 6) +#define VOLT_LEVEL(x) (((x) & 0x3) << 0) + +#define OMAP24XX_PRCM_VBASE IO_ADDRESS(OMAP24XX_PRCM_BASE) +#define prcm_readl(r) __raw_readl(OMAP24XX_PRCM_VBASE + (r)) +#define prcm_writel(v, r) __raw_writel((v), OMAP24XX_PRCM_VBASE + (r)) + +static u32 pmdomain_get_wakeup_dependencies(int domain_offset) +{ + return prcm_readl(domain_offset + PM_WKDEP_OFFSET); +} + +static void pmdomain_set_wakeup_dependencies(u32 state, int domain_offset) +{ + prcm_writel(state, domain_offset + PM_WKDEP_OFFSET); +} + +static u32 pmdomain_get_powerstate(int domain_offset) +{ + return prcm_readl(domain_offset + PM_PWSTCTRL_OFFSET); +} + +static void pmdomain_set_powerstate(u32 state, int domain_offset) +{ + prcm_writel(state, domain_offset + PM_PWSTCTRL_OFFSET); +} + +static u32 pmdomain_get_clock_autocontrol(int domain_offset) +{ + return prcm_readl(domain_offset + CM_CLKSTCTRL_OFFSET); +} + +static void pmdomain_set_clock_autocontrol(u32 state, int domain_offset) +{ + prcm_writel(state, domain_offset + CM_CLKSTCTRL_OFFSET); +} + +static u32 pmdomain_get_clock_autoidle1(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE1_OFFSET); +} + +/* Core domain only */ +static u32 pmdomain_get_clock_autoidle2(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE2_OFFSET); +} + +/* Core domain only */ +static u32 pmdomain_get_clock_autoidle3(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE3_OFFSET); +} + +/* Core domain only */ +static u32 pmdomain_get_clock_autoidle4(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE4_OFFSET); +} + +static void pmdomain_set_clock_autoidle1(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE1_OFFSET + domain_offset); +} + +/* Core domain only */ +static void pmdomain_set_clock_autoidle2(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE2_OFFSET + domain_offset); +} + +/* Core domain only */ +static void pmdomain_set_clock_autoidle3(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE3_OFFSET + domain_offset); +} + +/* Core domain only */ +static void pmdomain_set_clock_autoidle4(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE4_OFFSET + domain_offset); +} + +/* + * Configures power management domains to idle clocks automatically. + */ +void pmdomain_set_autoidle(void) +{ + u32 val; + + /* Set PLL auto stop for 54M, 96M & DPLL */ + pmdomain_set_clock_autoidle1(AUTO_54M(AUTO_STOPPED) | + AUTO_96M(AUTO_STOPPED) | + AUTO_DPLL(AUTO_STOPPED), PM_PLL_OFFSET); + + /* External clock input control + * REVISIT: Should this be in clock framework? + */ + PRCM_CLKSRC_CTRL |= (0x3 << 3); + + /* Configure number of 32KHz clock cycles for sys_clk */ + PRCM_CLKSSETUP = 0x00ff; + + /* Configure automatic voltage transition */ + PRCM_VOLTSETUP = 0; + val = PRCM_VOLTCTRL; + val &= ~(SETOFF_LEVEL(0x3) | VOLT_LEVEL(0x3)); + val |= SETOFF_LEVEL(1) | VOLT_LEVEL(1) | AUTO_EXTVOLT; + PRCM_VOLTCTRL = val; + + /* Disable emulation tools functional clock */ + PRCM_CLKEMUL_CTRL = 0x0; + + /* Set core memory retention state */ + val = pmdomain_get_powerstate(PM_CORE_OFFSET); + if (cpu_is_omap2420()) { + val &= ~(0x7 << 3); + val |= (MEM3RETSTATE | MEM2RETSTATE | MEM1RETSTATE); + } else { + val &= ~(0xf << 3); + val |= (MEM4RETSTATE | MEM3RETSTATE | MEM2RETSTATE | + MEM1RETSTATE); + } + pmdomain_set_powerstate(val, PM_CORE_OFFSET); + + /* OCP interface smart idle. REVISIT: Enable autoidle bit0 ? */ + val = SMS_SYSCONFIG; + val &= ~(0x3 << 3); + val |= (0x2 << 3) | (1 << 0); + SMS_SYSCONFIG |= val; + + val = SDRC_SYSCONFIG; + val &= ~(0x3 << 3); + val |= (0x2 << 3); + SDRC_SYSCONFIG = val; + + /* Configure L3 interface for smart idle. + * REVISIT: Enable autoidle bit0 ? + */ + val = GPMC_SYSCONFIG; + val &= ~(0x3 << 3); + val |= (0x2 << 3) | (1 << 0); + GPMC_SYSCONFIG = val; + + pmdomain_set_powerstate(LOGICRETSTATE | POWERSTATE_RETENTION, + PM_MPU_OFFSET); + pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_CORE_OFFSET); + if (!cpu_is_omap2420()) + pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_MDM_OFFSET); + + /* Assume suspend function has saved the state for DSP and GFX */ + pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_DSP_OFFSET); + pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_GFX_OFFSET); + +#if 0 + /* REVISIT: Internal USB needs special handling */ + force_standby_usb(); + if (cpu_is_omap2430()) + force_hsmmc(); + sdram_self_refresh_on_idle_req(1); +#endif + + /* Enable clock auto control for all domains. + * Note that CORE domain includes also DSS, L4 & L3. + */ + pmdomain_set_clock_autocontrol(AUTOSTAT_MPU, PM_MPU_OFFSET); + pmdomain_set_clock_autocontrol(AUTOSTAT_GFX, PM_GFX_OFFSET); + pmdomain_set_clock_autocontrol(AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3, + PM_CORE_OFFSET); + if (cpu_is_omap2420()) + pmdomain_set_clock_autocontrol(AUTOSTAT_IVA | AUTOSTAT_DSP, + PM_DSP_OFFSET); + else { + pmdomain_set_clock_autocontrol(AUTOSTAT_DSP, PM_DSP_OFFSET); + pmdomain_set_clock_autocontrol(AUTOSTAT_MDM, PM_MDM_OFFSET); + } + + /* Enable clock autoidle for all domains */ + pmdomain_set_clock_autoidle1(0x2, PM_DSP_OFFSET); + if (cpu_is_omap2420()) { + pmdomain_set_clock_autoidle1(0xfffffff9, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle2(0x7, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle1(0x3f, PM_WKUP_OFFSET); + } else { + pmdomain_set_clock_autoidle1(0xeafffff1, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle2(0xfff, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle1(0x7f, PM_WKUP_OFFSET); + pmdomain_set_clock_autoidle1(0x3, PM_MDM_OFFSET); + } + pmdomain_set_clock_autoidle3(0x7, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle4(0x1f, PM_CORE_OFFSET); +} + +/* + * Initializes power domains by removing wake-up dependencies and powering + * down DSP and GFX. Gets called from PM init. Note that DSP and IVA code + * must re-enable DSP and GFX when used. + */ +void __init pmdomain_init(void) +{ + /* Remove all domain wakeup dependencies */ + pmdomain_set_wakeup_dependencies(EN_WKUP | EN_CORE, PM_MPU_OFFSET); + pmdomain_set_wakeup_dependencies(0, PM_DSP_OFFSET); + pmdomain_set_wakeup_dependencies(0, PM_GFX_OFFSET); + pmdomain_set_wakeup_dependencies(EN_WKUP | EN_MPU, PM_CORE_OFFSET); + if (cpu_is_omap2430()) + pmdomain_set_wakeup_dependencies(0, PM_MDM_OFFSET); + + /* Power down DSP and GFX */ + pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_DSP_OFFSET); + pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_GFX_OFFSET); +} diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 562168fa2b1..d7eee99b7e3 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/sysfs.h> #include <linux/module.h> +#include <linux/delay.h> #include <asm/io.h> #include <asm/irq.h> @@ -36,11 +37,18 @@ #include <asm/arch/sram.h> #include <asm/arch/pm.h> +#include "prcm-regs.h" + static struct clk *vclk; static void (*omap2_sram_idle)(void); static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); static void (*saved_idle)(void); +extern void __init pmdomain_init(void); +extern void pmdomain_set_autoidle(void); + +static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE]; + void omap2_pm_idle(void) { local_irq_disable(); @@ -87,23 +95,272 @@ static int omap2_pm_prepare(suspend_state_t state) return error; } +#define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \ + OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) | \ + OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3)) + +#define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4)) + +#define INT2_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) | \ + OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) | \ + OMAP_IRQ_BIT(INT_24XX_UART3_IRQ)) + +#define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, ®, reg); + +static void omap2_pm_debug(char * desc) +{ + printk("%s:\n", desc); + + preg(CM_CLKSTCTRL_MPU); + preg(CM_CLKSTCTRL_CORE); + preg(CM_CLKSTCTRL_GFX); + preg(CM_CLKSTCTRL_DSP); + preg(CM_CLKSTCTRL_MDM); + + preg(PM_PWSTCTRL_MPU); + preg(PM_PWSTCTRL_CORE); + preg(PM_PWSTCTRL_GFX); + preg(PM_PWSTCTRL_DSP); + preg(PM_PWSTCTRL_MDM); + + preg(PM_PWSTST_MPU); + preg(PM_PWSTST_CORE); + preg(PM_PWSTST_GFX); + preg(PM_PWSTST_DSP); + preg(PM_PWSTST_MDM); + + preg(CM_AUTOIDLE1_CORE); + preg(CM_AUTOIDLE2_CORE); + preg(CM_AUTOIDLE3_CORE); + preg(CM_AUTOIDLE4_CORE); + preg(CM_AUTOIDLE_WKUP); + preg(CM_AUTOIDLE_PLL); + preg(CM_AUTOIDLE_DSP); + preg(CM_AUTOIDLE_MDM); + + preg(CM_ICLKEN1_CORE); + preg(CM_ICLKEN2_CORE); + preg(CM_ICLKEN3_CORE); + preg(CM_ICLKEN4_CORE); + preg(CM_ICLKEN_GFX); + preg(CM_ICLKEN_WKUP); + preg(CM_ICLKEN_DSP); + preg(CM_ICLKEN_MDM); + + preg(CM_IDLEST1_CORE); + preg(CM_IDLEST2_CORE); + preg(CM_IDLEST3_CORE); + preg(CM_IDLEST4_CORE); + preg(CM_IDLEST_GFX); + preg(CM_IDLEST_WKUP); + preg(CM_IDLEST_CKGEN); + preg(CM_IDLEST_DSP); + preg(CM_IDLEST_MDM); + + preg(RM_RSTST_MPU); + preg(RM_RSTST_GFX); + preg(RM_RSTST_WKUP); + preg(RM_RSTST_DSP); + preg(RM_RSTST_MDM); + + preg(PM_WKDEP_MPU); + preg(PM_WKDEP_CORE); + preg(PM_WKDEP_GFX); + preg(PM_WKDEP_DSP); + preg(PM_WKDEP_MDM); + + preg(CM_FCLKEN_WKUP); + preg(CM_ICLKEN_WKUP); + preg(CM_IDLEST_WKUP); + preg(CM_AUTOIDLE_WKUP); + preg(CM_CLKSEL_WKUP); + + preg(PM_WKEN_WKUP); + preg(PM_WKST_WKUP); +} + +static inline void omap2_pm_save_registers(void) +{ + /* Save interrupt registers */ + OMAP24XX_SAVE(INTC_MIR0); + OMAP24XX_SAVE(INTC_MIR1); + OMAP24XX_SAVE(INTC_MIR2); + + /* Save power control registers */ + OMAP24XX_SAVE(CM_CLKSTCTRL_MPU); + OMAP24XX_SAVE(CM_CLKSTCTRL_CORE); + OMAP24XX_SAVE(CM_CLKSTCTRL_GFX); + OMAP24XX_SAVE(CM_CLKSTCTRL_DSP); + OMAP24XX_SAVE(CM_CLKSTCTRL_MDM); + + /* Save power state registers */ + OMAP24XX_SAVE(PM_PWSTCTRL_MPU); + OMAP24XX_SAVE(PM_PWSTCTRL_CORE); + OMAP24XX_SAVE(PM_PWSTCTRL_GFX); + OMAP24XX_SAVE(PM_PWSTCTRL_DSP); + OMAP24XX_SAVE(PM_PWSTCTRL_MDM); + + /* Save autoidle registers */ + OMAP24XX_SAVE(CM_AUTOIDLE1_CORE); + OMAP24XX_SAVE(CM_AUTOIDLE2_CORE); + OMAP24XX_SAVE(CM_AUTOIDLE3_CORE); + OMAP24XX_SAVE(CM_AUTOIDLE4_CORE); + OMAP24XX_SAVE(CM_AUTOIDLE_WKUP); + OMAP24XX_SAVE(CM_AUTOIDLE_PLL); + OMAP24XX_SAVE(CM_AUTOIDLE_DSP); + OMAP24XX_SAVE(CM_AUTOIDLE_MDM); + + /* Save idle state registers */ + OMAP24XX_SAVE(CM_IDLEST1_CORE); + OMAP24XX_SAVE(CM_IDLEST2_CORE); + OMAP24XX_SAVE(CM_IDLEST3_CORE); + OMAP24XX_SAVE(CM_IDLEST4_CORE); + OMAP24XX_SAVE(CM_IDLEST_GFX); + OMAP24XX_SAVE(CM_IDLEST_WKUP); + OMAP24XX_SAVE(CM_IDLEST_CKGEN); + OMAP24XX_SAVE(CM_IDLEST_DSP); + OMAP24XX_SAVE(CM_IDLEST_MDM); + + /* Save clock registers */ + OMAP24XX_SAVE(CM_FCLKEN1_CORE); + OMAP24XX_SAVE(CM_FCLKEN2_CORE); + OMAP24XX_SAVE(CM_ICLKEN1_CORE); + OMAP24XX_SAVE(CM_ICLKEN2_CORE); + OMAP24XX_SAVE(CM_ICLKEN3_CORE); + OMAP24XX_SAVE(CM_ICLKEN4_CORE); +} + +static inline void omap2_pm_restore_registers(void) +{ + /* Restore clock state registers */ + OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU); + OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE); + OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX); + OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP); + OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM); + + /* Restore power state registers */ + OMAP24XX_RESTORE(PM_PWSTCTRL_MPU); + OMAP24XX_RESTORE(PM_PWSTCTRL_CORE); + OMAP24XX_RESTORE(PM_PWSTCTRL_GFX); + OMAP24XX_RESTORE(PM_PWSTCTRL_DSP); + OMAP24XX_RESTORE(PM_PWSTCTRL_MDM); + + /* Restore idle state registers */ + OMAP24XX_RESTORE(CM_IDLEST1_CORE); + OMAP24XX_RESTORE(CM_IDLEST2_CORE); + OMAP24XX_RESTORE(CM_IDLEST3_CORE); + OMAP24XX_RESTORE(CM_IDLEST4_CORE); + OMAP24XX_RESTORE(CM_IDLEST_GFX); + OMAP24XX_RESTORE(CM_IDLEST_WKUP); + OMAP24XX_RESTORE(CM_IDLEST_CKGEN); + OMAP24XX_RESTORE(CM_IDLEST_DSP); + OMAP24XX_RESTORE(CM_IDLEST_MDM); + + /* Restore autoidle registers */ + OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE); + OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE); + OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE); + OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE); + OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP); + OMAP24XX_RESTORE(CM_AUTOIDLE_PLL); + OMAP24XX_RESTORE(CM_AUTOIDLE_DSP); + OMAP24XX_RESTORE(CM_AUTOIDLE_MDM); + + /* Restore clock registers */ + OMAP24XX_RESTORE(CM_FCLKEN1_CORE); + OMAP24XX_RESTORE(CM_FCLKEN2_CORE); + OMAP24XX_RESTORE(CM_ICLKEN1_CORE); + OMAP24XX_RESTORE(CM_ICLKEN2_CORE); + OMAP24XX_RESTORE(CM_ICLKEN3_CORE); + OMAP24XX_RESTORE(CM_ICLKEN4_CORE); + + /* REVISIT: Clear interrupts here */ + + /* Restore interrupt registers */ + OMAP24XX_RESTORE(INTC_MIR0); + OMAP24XX_RESTORE(INTC_MIR1); + OMAP24XX_RESTORE(INTC_MIR2); +} + +static int omap2_pm_suspend(void) +{ + int processor_type = 0; + + /* REVISIT: 0x21 or 0x26? */ + if (cpu_is_omap2420()) + processor_type = 0x21; + + if (!processor_type) + return -ENOTSUPP; + + local_irq_disable(); + local_fiq_disable(); + + omap2_pm_save_registers(); + + /* Disable interrupts except for the wake events */ + INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK; + INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK; + INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK; + + pmdomain_set_autoidle(); + + /* Clear old wake-up events */ + PM_WKST1_CORE = 0; + PM_WKST2_CORE = 0; + PM_WKST_WKUP = 0; + + /* Enable wake-up events */ + PM_WKEN1_CORE = (1 << 22) | (1 << 21); /* UART1 & 2 */ + PM_WKEN2_CORE = (1 << 2); /* UART3 */ + PM_WKEN_WKUP = (1 << 2) | (1 << 0); /* GPIO & GPT1 */ + + /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled + * in the SRAM suspend code */ + CM_FCLKEN1_CORE = 0; + CM_FCLKEN2_CORE = 0; + CM_ICLKEN1_CORE = 0; + CM_ICLKEN3_CORE = 0; + CM_ICLKEN4_CORE = 0; + + omap2_pm_debug("Status before suspend"); + + /* Must wait for serial buffers to clear */ + mdelay(200); + + /* Jump to SRAM suspend code + * REVISIT: When is this SDRC_DLLB_CTRL? + */ + omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type); + + /* Back from sleep */ + omap2_pm_restore_registers(); + + local_fiq_enable(); + local_irq_enable(); + + return 0; +} + static int omap2_pm_enter(suspend_state_t state) { + int ret = 0; + switch (state) { case PM_SUSPEND_STANDBY: case PM_SUSPEND_MEM: - /* FIXME: Add suspend */ + ret = omap2_pm_suspend(); break; - case PM_SUSPEND_DISK: - return -ENOTSUPP; - + ret = -ENOTSUPP; + break; default: - return -EINVAL; + ret = -EINVAL; } - return 0; + return ret; } static int omap2_pm_finish(suspend_state_t state) @@ -143,6 +400,8 @@ int __init omap2_pm_init(void) pm_set_ops(&omap_pm_ops); pm_idle = omap2_pm_idle; + pmdomain_init(); + return 0; } diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 1d2f5ac2f69..fe5fd6d42de 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -6,6 +6,7 @@ * Copyright (C) 2005 Nokia Corporation * Author: Paul Mundt <paul.mundt@nokia.com> * Juha Yrjölä <juha.yrjola@nokia.com> + * OMAP Dual-mode timer framework support by Timo Teras * * Some parts based off of TI's 24xx code: * @@ -22,54 +23,18 @@ #include <linux/interrupt.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/delay.h> #include <asm/mach/time.h> -#include <asm/delay.h> -#include <asm/io.h> +#include <asm/arch/dmtimer.h> -#define OMAP2_GP_TIMER1_BASE 0x48028000 -#define OMAP2_GP_TIMER2_BASE 0x4802a000 -#define OMAP2_GP_TIMER3_BASE 0x48078000 -#define OMAP2_GP_TIMER4_BASE 0x4807a000 +static struct omap_dm_timer *gptimer; -#define GP_TIMER_TIDR 0x00 -#define GP_TIMER_TISR 0x18 -#define GP_TIMER_TIER 0x1c -#define GP_TIMER_TCLR 0x24 -#define GP_TIMER_TCRR 0x28 -#define GP_TIMER_TLDR 0x2c -#define GP_TIMER_TSICR 0x40 - -#define OS_TIMER_NR 1 /* GP timer 2 */ - -static unsigned long timer_base[] = { - IO_ADDRESS(OMAP2_GP_TIMER1_BASE), - IO_ADDRESS(OMAP2_GP_TIMER2_BASE), - IO_ADDRESS(OMAP2_GP_TIMER3_BASE), - IO_ADDRESS(OMAP2_GP_TIMER4_BASE), -}; - -static inline unsigned int timer_read_reg(int nr, unsigned int reg) -{ - return __raw_readl(timer_base[nr] + reg); -} - -static inline void timer_write_reg(int nr, unsigned int reg, unsigned int val) -{ - __raw_writel(val, timer_base[nr] + reg); -} - -/* Note that we always enable the clock prescale divider bit */ -static inline void omap2_gp_timer_start(int nr, unsigned long load_val) +static inline void omap2_gp_timer_start(unsigned long load_val) { - unsigned int tmp; - - tmp = 0xffffffff - load_val; - - timer_write_reg(nr, GP_TIMER_TLDR, tmp); - timer_write_reg(nr, GP_TIMER_TCRR, tmp); - timer_write_reg(nr, GP_TIMER_TIER, 1 << 1); - timer_write_reg(nr, GP_TIMER_TCLR, (1 << 5) | (1 << 1) | 1); + omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val); + omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); + omap_dm_timer_start(gptimer); } static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id, @@ -77,7 +42,7 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id, { write_seqlock(&xtime_lock); - timer_write_reg(OS_TIMER_NR, GP_TIMER_TISR, 1 << 1); + omap_dm_timer_write_status(gptimer, OMAP_TIMER_INT_OVERFLOW); timer_tick(regs); write_sequnlock(&xtime_lock); @@ -87,41 +52,26 @@ static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id, static struct irqaction omap2_gp_timer_irq = { .name = "gp timer", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = omap2_gp_timer_interrupt, }; static void __init omap2_gp_timer_init(void) { - struct clk * sys_ck; - u32 tick_period = 120000; - u32 l; + u32 tick_period; - /* Reset clock and prescale value */ - timer_write_reg(OS_TIMER_NR, GP_TIMER_TCLR, 0); + omap_dm_timer_init(); + gptimer = omap_dm_timer_request_specific(1); + BUG_ON(gptimer == NULL); - sys_ck = clk_get(NULL, "sys_ck"); - if (IS_ERR(sys_ck)) - printk(KERN_ERR "Could not get sys_ck\n"); - else { - clk_enable(sys_ck); - tick_period = clk_get_rate(sys_ck) / 100; - clk_put(sys_ck); - } - - tick_period /= 2; /* Minimum prescale divider is 2 */ + omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK); + tick_period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / 100; tick_period -= 1; - l = timer_read_reg(OS_TIMER_NR, GP_TIMER_TIDR); - printk(KERN_INFO "OMAP2 GP timer (HW version %d.%d)\n", - (l >> 4) & 0x0f, l & 0x0f); - - setup_irq(38, &omap2_gp_timer_irq); - - omap2_gp_timer_start(OS_TIMER_NR, tick_period); + setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq); + omap2_gp_timer_start(tick_period); } struct sys_timer omap_timer = { .init = omap2_gp_timer_init, }; - diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c index 4ce68069852..888bf6cfba8 100644 --- a/arch/arm/mach-pnx4008/time.c +++ b/arch/arm/mach-pnx4008/time.c @@ -86,7 +86,7 @@ static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id, static struct irqaction pnx4008_timer_irq = { .name = "PNX4008 Tick Timer", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = pnx4008_timer_interrupt }; diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index ea5137f319c..03d07cae26c 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -35,6 +35,10 @@ config PXA_SHARPSL SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa) handheld computer. +config MACH_TRIZEPS4 + bool "Keith und Koep Trizeps4 DIMM-Module" + select PXA27x + endchoice if PXA_SHARPSL @@ -55,6 +59,21 @@ endchoice endif +if MACH_TRIZEPS4 + +choice + prompt "Select base board for Trizeps 4 module" + +config MACH_TRIZEPS4_CONXS + bool "ConXS Eval Board" + +config MACH_TRIZEPS4_ANY + bool "another Board" + +endchoice + +endif + endmenu config MACH_POODLE diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 1610690be41..9093eb1c94e 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o +obj-$(CONFIG_MACH_TRIZEPS4) += trizeps4.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o @@ -23,6 +24,7 @@ led-y := leds.o led-$(CONFIG_ARCH_LUBBOCK) += leds-lubbock.o led-$(CONFIG_MACH_MAINSTONE) += leds-mainstone.o led-$(CONFIG_ARCH_PXA_IDP) += leds-idp.o +led-$(CONFIG_MACH_TRIZEPS4) += leds-trizeps4.o obj-$(CONFIG_LEDS) += $(led-y) diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index bf6648a8390..cce26576999 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -225,7 +225,7 @@ static int corgi_mci_init(struct device *dev, irqreturn_t (*corgi_detect_int)(in corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250); err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "MMC card detect", data); if (err) { printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index 347b9dea24c..6914d22bc20 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/platform_device.h> #include <linux/fb.h> diff --git a/arch/arm/mach-pxa/leds-trizeps4.c b/arch/arm/mach-pxa/leds-trizeps4.c new file mode 100644 index 00000000000..14cfc85e44b --- /dev/null +++ b/arch/arm/mach-pxa/leds-trizeps4.c @@ -0,0 +1,134 @@ +/* + * linux/arch/arm/mach-pxa/leds-trizeps4.c + * + * Author: Jürgen Schindele + * Created: 20 02, 2006 + * Copyright: Jürgen Schindele + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/config.h> +#include <linux/init.h> + +#include <asm/hardware.h> +#include <asm/system.h> +#include <asm/types.h> +#include <asm/leds.h> + +#include <asm/arch/pxa-regs.h> +#include <asm/arch/trizeps4.h> + +#include "leds.h" + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +#define SYS_BUSY 0x01 +#define HEARTBEAT 0x02 +#define BLINK 0x04 + +static unsigned int led_state; +static unsigned int hw_led_state; + +void trizeps4_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = 0; + pxa_gpio_mode( GPIO_SYS_BUSY_LED | GPIO_OUT); /* LED1 */ + pxa_gpio_mode( GPIO_HEARTBEAT_LED | GPIO_OUT); /* LED2 */ + 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 = 0; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = 0; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + hw_led_state ^= HEARTBEAT; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + hw_led_state &= ~SYS_BUSY; + break; + + case led_idle_end: + hw_led_state |= SYS_BUSY; + break; +#endif + + case led_halted: + break; + + case led_green_on: + hw_led_state |= BLINK; + break; + + case led_green_off: + hw_led_state &= ~BLINK; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + break; + + case led_red_off: + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) { + switch (hw_led_state) { + case 0: + GPSR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + case 1: + GPCR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + case 2: + GPSR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPCR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + case 3: + GPCR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPCR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + } + } + else { + /* turn all off */ + GPSR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + } + + local_irq_restore(flags); +} diff --git a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c index bbe4d5f6afa..e13eb841e48 100644 --- a/arch/arm/mach-pxa/leds.c +++ b/arch/arm/mach-pxa/leds.c @@ -24,6 +24,8 @@ pxa_leds_init(void) leds_event = mainstone_leds_event; if (machine_is_pxa_idp()) leds_event = idp_leds_event; + if (machine_is_trizeps4()) + leds_event = trizeps4_leds_event; leds_event(led_start); return 0; diff --git a/arch/arm/mach-pxa/leds.h b/arch/arm/mach-pxa/leds.h index d98f6e93c12..4f829b8c39d 100644 --- a/arch/arm/mach-pxa/leds.h +++ b/arch/arm/mach-pxa/leds.h @@ -10,3 +10,4 @@ extern void idp_leds_event(led_event_t evt); extern void lubbock_leds_event(led_event_t evt); extern void mainstone_leds_event(led_event_t evt); +extern void trizeps4_leds_event(led_event_t evt); diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index ec0f43a102c..1a5f5c21481 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -248,58 +248,137 @@ static void lpd270_backlight_power(int on) /* 5.7" TFT QVGA (LoLo display number 1) */ static struct pxafb_mach_info sharp_lq057q3dc02 __initdata = { - .pixclock = 100000, - .xres = 240, - .yres = 320, + .pixclock = 150000, + .xres = 320, + .yres = 240, .bpp = 16, - .hsync_len = 64, - .left_margin = 0x27, - .right_margin = 0x09, - .vsync_len = 0x04, + .hsync_len = 0x14, + .left_margin = 0x28, + .right_margin = 0x0a, + .vsync_len = 0x02, .upper_margin = 0x08, .lower_margin = 0x14, - .sync = 0, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, .lccr0 = 0x07800080, - .lccr3 = 0x04400007, + .lccr3 = 0x00400000, + .pxafb_backlight_power = lpd270_backlight_power, +}; + +/* 12.1" TFT SVGA (LoLo display number 2) */ +static struct pxafb_mach_info sharp_lq121s1dg31 __initdata = { + .pixclock = 50000, + .xres = 800, + .yres = 600, + .bpp = 16, + .hsync_len = 0x05, + .left_margin = 0x52, + .right_margin = 0x05, + .vsync_len = 0x04, + .upper_margin = 0x14, + .lower_margin = 0x0a, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .lccr0 = 0x07800080, + .lccr3 = 0x00400000, + .pxafb_backlight_power = lpd270_backlight_power, +}; + +/* 3.6" TFT QVGA (LoLo display number 3) */ +static struct pxafb_mach_info sharp_lq036q1da01 __initdata = { + .pixclock = 150000, + .xres = 320, + .yres = 240, + .bpp = 16, + .hsync_len = 0x0e, + .left_margin = 0x04, + .right_margin = 0x0a, + .vsync_len = 0x03, + .upper_margin = 0x03, + .lower_margin = 0x03, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .lccr0 = 0x07800080, + .lccr3 = 0x00400000, .pxafb_backlight_power = lpd270_backlight_power, }; /* 6.4" TFT VGA (LoLo display number 5) */ static struct pxafb_mach_info sharp_lq64d343 __initdata = { - .pixclock = 20000, + .pixclock = 25000, .xres = 640, .yres = 480, .bpp = 16, - .hsync_len = 49, + .hsync_len = 0x31, .left_margin = 0x89, .right_margin = 0x19, - .vsync_len = 18, + .vsync_len = 0x12, .upper_margin = 0x22, - .lower_margin = 0, + .lower_margin = 0x00, .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, .lccr0 = 0x07800080, - .lccr3 = 0x04400001, + .lccr3 = 0x00400000, + .pxafb_backlight_power = lpd270_backlight_power, +}; + +/* 10.4" TFT VGA (LoLo display number 7) */ +static struct pxafb_mach_info sharp_lq10d368 __initdata = { + .pixclock = 25000, + .xres = 640, + .yres = 480, + .bpp = 16, + .hsync_len = 0x31, + .left_margin = 0x89, + .right_margin = 0x19, + .vsync_len = 0x12, + .upper_margin = 0x22, + .lower_margin = 0x00, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .lccr0 = 0x07800080, + .lccr3 = 0x00400000, .pxafb_backlight_power = lpd270_backlight_power, }; /* 3.5" TFT QVGA (LoLo display number 8) */ static struct pxafb_mach_info sharp_lq035q7db02_20 __initdata = { - .pixclock = 100000, + .pixclock = 150000, .xres = 240, .yres = 320, .bpp = 16, - .hsync_len = 0x34, - .left_margin = 0x09, - .right_margin = 0x09, - .vsync_len = 0x08, + .hsync_len = 0x0e, + .left_margin = 0x0a, + .right_margin = 0x0a, + .vsync_len = 0x03, .upper_margin = 0x05, .lower_margin = 0x14, - .sync = 0, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, .lccr0 = 0x07800080, - .lccr3 = 0x04400007, + .lccr3 = 0x00400000, .pxafb_backlight_power = lpd270_backlight_power, }; +static struct pxafb_mach_info *lpd270_lcd_to_use; + +static int __init lpd270_set_lcd(char *str) +{ + if (!strnicmp(str, "lq057q3dc02", 11)) { + lpd270_lcd_to_use = &sharp_lq057q3dc02; + } else if (!strnicmp(str, "lq121s1dg31", 11)) { + lpd270_lcd_to_use = &sharp_lq121s1dg31; + } else if (!strnicmp(str, "lq036q1da01", 11)) { + lpd270_lcd_to_use = &sharp_lq036q1da01; + } else if (!strnicmp(str, "lq64d343", 8)) { + lpd270_lcd_to_use = &sharp_lq64d343; + } else if (!strnicmp(str, "lq10d368", 8)) { + lpd270_lcd_to_use = &sharp_lq10d368; + } else if (!strnicmp(str, "lq035q7db02-20", 14)) { + lpd270_lcd_to_use = &sharp_lq035q7db02_20; + } else { + printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str); + } + + return 1; +} + +__setup("lcd=", lpd270_set_lcd); + static struct platform_device *platform_devices[] __initdata = { &smc91x_device, &lpd270_audio_device, @@ -345,9 +424,8 @@ static void __init lpd270_init(void) platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); - // set_pxa_fb_info(&sharp_lq057q3dc02); - set_pxa_fb_info(&sharp_lq64d343); - // set_pxa_fb_info(&sharp_lq035q7db02_20); + if (lpd270_lcd_to_use != NULL) + set_pxa_fb_info(lpd270_lcd_to_use); pxa_set_ohci_info(&lpd270_ohci_platform_data); } diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 1ab26c6914f..6a9a669d60d 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -419,7 +419,7 @@ static int lubbock_mci_init(struct device *dev, init_timer(&mmc_timer); mmc_timer.data = (unsigned long) data; return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int, - SA_SAMPLE_RANDOM, "lubbock-sd-detect", data); + IRQF_SAMPLE_RANDOM, "lubbock-sd-detect", data); } static int lubbock_mci_get_ro(struct device *dev) diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index b307f11951d..21ddf3de2f6 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -331,7 +331,7 @@ static int mainstone_mci_init(struct device *dev, irqreturn_t (*mstone_detect_in */ MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL; - err = request_irq(MAINSTONE_MMC_IRQ, mstone_detect_int, SA_INTERRUPT, + err = request_irq(MAINSTONE_MMC_IRQ, mstone_detect_int, IRQF_DISABLED, "MMC card detect", data); if (err) { printk(KERN_ERR "mainstone_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 9a9fa87cea9..6dbff6d9480 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -212,7 +212,7 @@ static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)( poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "MMC card detect", data); if (err) { printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 0f1648780c4..db6e8f56a75 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -18,11 +18,11 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/platform_device.h> #include <asm/hardware.h> #include <asm/mach-types.h> -#include <asm/irq.h> #include <asm/apm.h> #include <asm/arch/pm.h> #include <asm/arch/pxa-regs.h> @@ -142,18 +142,18 @@ void sharpsl_pm_pxa_init(void) pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN); /* Register interrupt handlers */ - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, SA_INTERRUPT, "AC Input Detect", sharpsl_ac_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin)); } else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQT_BOTHEDGE); - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, SA_INTERRUPT, "Battery Cover", sharpsl_fatal_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock)); } else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQT_FALLING); if (sharpsl_pm.machinfo->gpio_fatal) { - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, SA_INTERRUPT, "Fatal Battery", sharpsl_fatal_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal)); } else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING); @@ -162,7 +162,7 @@ void sharpsl_pm_pxa_init(void) if (sharpsl_pm.machinfo->batfull_irq) { /* Register interrupt handler. */ - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, SA_INTERRUPT, "CO", sharpsl_chrg_full_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull)); } else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING); diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index eb9937f6f5c..1c32a9310dc 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -308,7 +308,7 @@ static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(in spitz_mci_platform_data.detect_delay = msecs_to_jiffies(250); err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int, - SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "MMC card detect", data); if (err) { printk(KERN_ERR "spitz_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 1ef85fcc6c0..5dbd191c57c 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -117,7 +117,7 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction pxa_timer_irq = { .name = "PXA Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = pxa_timer_interrupt, }; diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 7152bc13680..249353616ab 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -185,7 +185,7 @@ static int tosa_mci_init(struct device *dev, irqreturn_t (*tosa_detect_int)(int, tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250); - err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int, SA_INTERRUPT, + err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int, IRQF_DISABLED, "MMC/SD card detect", data); if (err) { printk(KERN_ERR "tosa_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c new file mode 100644 index 00000000000..7c3007df1bd --- /dev/null +++ b/arch/arm/mach-pxa/trizeps4.c @@ -0,0 +1,473 @@ +/* + * linux/arch/arm/mach-pxa/trizeps4.c + * + * Support for the Keith und Koep Trizeps4 Module Platform. + * + * Author: Jürgen Schindele + * Created: 20 02, 2006 + * Copyright: Jürgen Schindele + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/sysdev.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/bitops.h> +#include <linux/fb.h> +#include <linux/ioport.h> +#include <linux/delay.h> +#include <linux/serial_8250.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include <asm/types.h> +#include <asm/setup.h> +#include <asm/memory.h> +#include <asm/mach-types.h> +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/sizes.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/mach/flash.h> + +#include <asm/arch/pxa-regs.h> +#include <asm/arch/trizeps4.h> +#include <asm/arch/audio.h> +#include <asm/arch/pxafb.h> +#include <asm/arch/mmc.h> +#include <asm/arch/irda.h> +#include <asm/arch/ohci.h> + +#include "generic.h" + +/******************************************************************************************** + * ONBOARD FLASH + ********************************************************************************************/ +static struct mtd_partition trizeps4_partitions[] = { + { + .name = "Bootloader", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE /* force read-only */ + },{ + .name = "Kernel", + .size = 0x00400000, + .offset = 0x00040000 + },{ + .name = "Filesystem", + .size = MTDPART_SIZ_FULL, + .offset = 0x00440000 + } +}; + +static struct flash_platform_data trizeps4_flash_data[] = { + { + .map_name = "cfi_probe", + .parts = trizeps4_partitions, + .nr_parts = ARRAY_SIZE(trizeps4_partitions) + } +}; + +static struct resource flash_resource = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_64M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device flash_device = { + .name = "pxa2xx-flash", + .id = 0, + .dev = { + .platform_data = &trizeps4_flash_data, + }, + .resource = &flash_resource, + .num_resources = 1, +}; + +/******************************************************************************************** + * DAVICOM DM9000 Ethernet + ********************************************************************************************/ +static struct resource dm9000_resources[] = { + [0] = { + .start = TRIZEPS4_ETH_PHYS+0x300, + .end = TRIZEPS4_ETH_PHYS+0x400-1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = TRIZEPS4_ETH_PHYS+0x8300, + .end = TRIZEPS4_ETH_PHYS+0x8400-1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = TRIZEPS4_ETH_IRQ, + .end = TRIZEPS4_ETH_IRQ, + .flags = (IORESOURCE_IRQ | IRQT_RISING), + }, +}; + +static struct platform_device dm9000_device = { + .name = "dm9000", + .id = -1, + .num_resources = ARRAY_SIZE(dm9000_resources), + .resource = dm9000_resources, +}; + +/******************************************************************************************** + * PXA270 serial ports + ********************************************************************************************/ +static struct plat_serial8250_port tri_serial_ports[] = { +#ifdef CONFIG_SERIAL_PXA + /* this uses the own PXA driver */ + { + 0, + }, +#else + /* this uses the generic 8520 driver */ + [0] = { + .membase = (void *)&FFUART, + .irq = IRQ_FFUART, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM32, + .regshift = 2, + .uartclk = (921600*16), + }, + [1] = { + .membase = (void *)&BTUART, + .irq = IRQ_BTUART, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM32, + .regshift = 2, + .uartclk = (921600*16), + }, + { + 0, + }, +#endif +}; + +static struct platform_device uart_devices = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = tri_serial_ports, + }, + .num_resources = 0, + .resource = NULL, +}; + +/******************************************************************************************** + * PXA270 ac97 sound codec + ********************************************************************************************/ +static struct platform_device ac97_audio_device = { + .name = "pxa2xx-ac97", + .id = -1, +}; + +static struct platform_device * trizeps4_devices[] __initdata = { + &flash_device, + &uart_devices, + &dm9000_device, + &ac97_audio_device, +}; + +#ifdef CONFIG_MACH_TRIZEPS4_CONXS +static short trizeps_conxs_bcr; + +/* PCCARD power switching supports only 3,3V */ +void board_pcmcia_power(int power) +{ + if (power) { + /* switch power on, put in reset and enable buffers */ + trizeps_conxs_bcr |= power; + trizeps_conxs_bcr |= ConXS_BCR_CF_RESET; + trizeps_conxs_bcr &= ~(ConXS_BCR_CF_BUF_EN); + ConXS_BCR = trizeps_conxs_bcr; + /* wait a little */ + udelay(2000); + /* take reset away */ + trizeps_conxs_bcr &= ~(ConXS_BCR_CF_RESET); + ConXS_BCR = trizeps_conxs_bcr; + udelay(2000); + } else { + /* put in reset */ + trizeps_conxs_bcr |= ConXS_BCR_CF_RESET; + ConXS_BCR = trizeps_conxs_bcr; + udelay(1000); + /* switch power off */ + trizeps_conxs_bcr &= ~(0xf); + ConXS_BCR = trizeps_conxs_bcr; + + } + pr_debug("%s: o%s 0x%x\n", __FUNCTION__, power ? "n": "ff", trizeps_conxs_bcr); +} + +/* backlight power switching for LCD panel */ +static void board_backlight_power(int on) +{ + if (on) { + trizeps_conxs_bcr |= ConXS_BCR_L_DISP; + } else { + trizeps_conxs_bcr &= ~ConXS_BCR_L_DISP; + } + pr_debug("%s: o%s 0x%x\n", __FUNCTION__, on ? "n" : "ff", trizeps_conxs_bcr); + ConXS_BCR = trizeps_conxs_bcr; +} + +/* Powersupply for MMC/SD cardslot */ +static void board_mci_power(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) { + pr_debug("%s: on\n", __FUNCTION__); + /* FIXME fill in values here */ + } else { + pr_debug("%s: off\n", __FUNCTION__); + /* FIXME fill in values here */ + } +} + +static short trizeps_conxs_ircr; + +/* Switch modes and Power for IRDA receiver */ +static void board_irda_mode(struct device *dev, int mode) +{ + unsigned long flags; + + local_irq_save(flags); + if (mode & IR_SIRMODE) { + /* Slow mode */ + trizeps_conxs_ircr &= ~ConXS_IRCR_MODE; + } else if (mode & IR_FIRMODE) { + /* Fast mode */ + trizeps_conxs_ircr |= ConXS_IRCR_MODE; + } + if (mode & IR_OFF) { + trizeps_conxs_ircr |= ConXS_IRCR_SD; + } else { + trizeps_conxs_ircr &= ~ConXS_IRCR_SD; + } + /* FIXME write values to register */ + local_irq_restore(flags); +} + +#else +/* for other baseboards define dummies */ +void board_pcmcia_power(int power) {;} +#define board_backlight_power NULL +#define board_mci_power NULL +#define board_irda_mode NULL + +#endif /* CONFIG_MACH_TRIZEPS4_CONXS */ +EXPORT_SYMBOL(board_pcmcia_power); + +static int trizeps4_mci_init(struct device *dev, irqreturn_t (*mci_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + /* setup GPIO for PXA27x MMC controller */ + pxa_gpio_mode(GPIO32_MMCCLK_MD); + pxa_gpio_mode(GPIO112_MMCCMD_MD); + pxa_gpio_mode(GPIO92_MMCDAT0_MD); + pxa_gpio_mode(GPIO109_MMCDAT1_MD); + pxa_gpio_mode(GPIO110_MMCDAT2_MD); + pxa_gpio_mode(GPIO111_MMCDAT3_MD); + + pxa_gpio_mode(GPIO_MMC_DET | GPIO_IN); + + err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int, + IRQF_DISABLED | IRQF_TRIGGER_RISING, + "MMC card detect", data); + if (err) { + printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + return 0; +} + +static void trizeps4_mci_exit(struct device *dev, void *data) +{ + free_irq(TRIZEPS4_MMC_IRQ, data); +} + +static struct pxamci_platform_data trizeps4_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = trizeps4_mci_init, + .exit = trizeps4_mci_exit, + .setpower = board_mci_power, +}; + +static struct pxaficp_platform_data trizeps4_ficp_platform_data = { + .transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF, + .transceiver_mode = board_irda_mode, +}; + +static int trizeps4_ohci_init(struct device *dev) +{ + /* setup Port1 GPIO pin. */ + pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ + pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ + + /* Set the Power Control Polarity Low and Power Sense + Polarity Low to active low. */ + UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & + ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); + + return 0; +} + +static void trizeps4_ohci_exit(struct device *dev) +{ + ; +} + +static struct pxaohci_platform_data trizeps4_ohci_platform_data = { + .port_mode = PMM_PERPORT_MODE, + .init = trizeps4_ohci_init, + .exit = trizeps4_ohci_exit, +}; + +static struct map_desc trizeps4_io_desc[] __initdata = { + { /* ConXS CFSR */ + .virtual = TRIZEPS4_CFSR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_CFSR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS BCR */ + .virtual = TRIZEPS4_BOCR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_BOCR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS IRCR */ + .virtual = TRIZEPS4_IRCR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_IRCR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS DCR */ + .virtual = TRIZEPS4_DICR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_DICR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS UPSR */ + .virtual = TRIZEPS4_UPSR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_UPSR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + } +}; + +static struct pxafb_mach_info sharp_lcd __initdata = { + .pixclock = 78000, + .xres = 640, + .yres = 480, + .bpp = 8, + .hsync_len = 4, + .left_margin = 4, + .right_margin = 4, + .vsync_len = 2, + .upper_margin = 0, + .lower_margin = 0, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + .lccr0 = LCCR0_Color | LCCR0_Pas | LCCR0_Dual, + .lccr3 = 0x0340ff02, + .pxafb_backlight_power = board_backlight_power, +}; + +static void __init trizeps4_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) +{ +} + +static void __init trizeps4_init(void) +{ + platform_add_devices(trizeps4_devices, ARRAY_SIZE(trizeps4_devices)); + + set_pxa_fb_info(&sharp_lcd); + + pxa_set_mci_info(&trizeps4_mci_platform_data); + pxa_set_ficp_info(&trizeps4_ficp_platform_data); + pxa_set_ohci_info(&trizeps4_ohci_platform_data); +} + +static void __init trizeps4_map_io(void) +{ + pxa_map_io(); + iotable_init(trizeps4_io_desc, ARRAY_SIZE(trizeps4_io_desc)); + + /* for DiskOnChip */ + pxa_gpio_mode(GPIO15_nCS_1_MD); + + /* for off-module PIC on ConXS board */ + pxa_gpio_mode(GPIO_PIC | GPIO_IN); + + /* UCB1400 irq */ + pxa_gpio_mode(GPIO_UCB1400 | GPIO_IN); + + /* for DM9000 LAN */ + pxa_gpio_mode(GPIO78_nCS_2_MD); + pxa_gpio_mode(GPIO_DM9000 | GPIO_IN); + + /* for PCMCIA device */ + pxa_gpio_mode(GPIO_PCD | GPIO_IN); + pxa_gpio_mode(GPIO_PRDY | GPIO_IN); + + /* for I2C adapter */ + pxa_gpio_mode(GPIO117_I2CSCL_MD); + pxa_gpio_mode(GPIO118_I2CSDA_MD); + + /* MMC_DET s.o. */ + pxa_gpio_mode(GPIO_MMC_DET | GPIO_IN); + + /* whats that for ??? */ + pxa_gpio_mode(GPIO79_nCS_3_MD); + + pxa_gpio_mode( GPIO_SYS_BUSY_LED | GPIO_OUT); /* LED1 */ + pxa_gpio_mode( GPIO_HEARTBEAT_LED | GPIO_OUT); /* LED2 */ + +#ifdef CONFIG_MACH_TRIZEPS4_CONXS +#ifdef CONFIG_IDE_PXA_CF + /* if boot direct from compact flash dont disable power */ + trizeps_conxs_bcr = 0x0009; +#else + /* this is the reset value */ + trizeps_conxs_bcr = 0x00A0; +#endif + ConXS_BCR = trizeps_conxs_bcr; +#endif + + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x0158C000; + PGSR1 = 0x00FF0080; + PGSR2 = 0x0001C004; + /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ + PCFR |= PCFR_OPDE; +} + +MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module") + /* MAINTAINER("Jürgen Schindele") */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = TRIZEPS4_SDRAM_BASE + 0x100, + .fixup = trizeps4_fixup, + .init_machine = trizeps4_init, + .map_io = trizeps4_map_io, + .init_irq = pxa_init_irq, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index eb09d3859d6..da028697382 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -536,7 +536,7 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id, struct pt_reg static struct irqaction realview_timer_irq = { .name = "RealView Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = realview_timer_interrupt, }; diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c index bd86ffba881..ac511d41d4d 100644 --- a/arch/arm/mach-rpc/dma.c +++ b/arch/arm/mach-rpc/dma.c @@ -128,7 +128,7 @@ static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) static int iomd_request_dma(dmach_t channel, dma_t *dma) { return request_irq(dma->dma_irq, iomd_dma_handle, - SA_INTERRUPT, dma->device_id, dma); + IRQF_DISABLED, dma->device_id, dma); } static void iomd_free_dma(dmach_t channel, dma_t *dma) diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c index fbbeb055300..def4441d244 100644 --- a/arch/arm/mach-s3c2410/bast-irq.c +++ b/arch/arm/mach-s3c2410/bast-irq.c @@ -136,8 +136,8 @@ bast_irq_pc104_demux(unsigned int irq, for (i = 0; stat != 0; i++, stat >>= 1) { if (stat & 1) { irqno = bast_pc104_irqs[i]; - - desc_handle_irq(irqno, irq_desc + irqno, regs); + desc = irq_desc + irqno; + desc_handle_irq(irqno, desc, regs); } } } @@ -156,7 +156,7 @@ static __init int bast_irq_init(void) set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux); - /* reigster our IRQs */ + /* register our IRQs */ for (i = 0; i < 4; i++) { unsigned int irqno = bast_pc104_irqs[i]; diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index b0aaf432873..094cc52745c 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -718,7 +718,7 @@ int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client, pr_debug("dma%d: %s : requesting irq %d\n", channel, __FUNCTION__, chan->irq); - err = request_irq(chan->irq, s3c2410_dma_irq, SA_INTERRUPT, + err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED, client->name, (void *)chan); if (err) { diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c index 47387c5b972..00d1cfca971 100644 --- a/arch/arm/mach-s3c2410/time.c +++ b/arch/arm/mach-s3c2410/time.c @@ -22,6 +22,7 @@ #include <linux/sched.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/err.h> #include <linux/clk.h> @@ -137,7 +138,7 @@ s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction s3c2410_timer_irq = { .name = "S3C2410 Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = s3c2410_timer_interrupt, }; diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c index 495f8c6ffcb..6b22d8f0a00 100644 --- a/arch/arm/mach-s3c2410/usb-simtec.c +++ b/arch/arm/mach-s3c2410/usb-simtec.c @@ -85,8 +85,8 @@ static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on) if (on) { ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, - SA_INTERRUPT | SA_TRIGGER_RISING | - SA_TRIGGER_FALLING, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, "USB Over-current", info); if (ret != 0) { printk(KERN_ERR "failed to request usb oc irq\n"); diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index e0f6d57b506..31afe50d7cd 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/tty.h> #include <linux/platform_device.h> +#include <linux/irq.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c index 696d7d29c8a..45b1e71f111 100644 --- a/arch/arm/mach-sa1100/collie_pm.c +++ b/arch/arm/mach-sa1100/collie_pm.c @@ -45,12 +45,12 @@ static void collie_charger_init(void) } /* Register interrupt handler. */ - if ((err = request_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr, SA_INTERRUPT, + if ((err = request_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr, IRQF_DISABLED, "ACIN", sharpsl_ac_isr))) { printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_AC_IN); return; } - if ((err = request_irq(COLLIE_IRQ_GPIO_CO, sharpsl_chrg_full_isr, SA_INTERRUPT, + if ((err = request_irq(COLLIE_IRQ_GPIO_CO, sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr))) { free_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr); printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_CO); diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 04c94ab6c18..63959772993 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -15,7 +15,10 @@ * SDRAM reads (rev A0, B0, B1) * * We ignore rev. A0 and B0 devices; I don't think they're worth supporting. + * + * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type */ +#include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -35,6 +38,7 @@ static struct cpufreq_driver sa1110_driver; struct sdram_params { + const char name[16]; u_char rows; /* bits */ u_char cas_latency; /* cycles */ u_char tck; /* clock cycle time (ns) */ @@ -50,54 +54,53 @@ struct sdram_info { u_int mdcas[3]; }; -static struct sdram_params tc59sm716_cl2_params __initdata = { - .rows = 12, - .tck = 10, - .trcd = 20, - .trp = 20, - .twr = 10, - .refresh = 64000, - .cas_latency = 2, -}; - -static struct sdram_params tc59sm716_cl3_params __initdata = { - .rows = 12, - .tck = 8, - .trcd = 20, - .trp = 20, - .twr = 8, - .refresh = 64000, - .cas_latency = 3, -}; - -static struct sdram_params samsung_k4s641632d_tc75 __initdata = { - .rows = 14, - .tck = 9, - .trcd = 27, - .trp = 20, - .twr = 9, - .refresh = 64000, - .cas_latency = 3, -}; - -static struct sdram_params samsung_km416s4030ct __initdata = { - .rows = 13, - .tck = 8, - .trcd = 24, /* 3 CLKs */ - .trp = 24, /* 3 CLKs */ - .twr = 16, /* Trdl: 2 CLKs */ - .refresh = 64000, - .cas_latency = 3, -}; - -static struct sdram_params wbond_w982516ah75l_cl3_params __initdata = { - .rows = 16, - .tck = 8, - .trcd = 20, - .trp = 20, - .twr = 8, - .refresh = 64000, - .cas_latency = 3, +static struct sdram_params sdram_tbl[] __initdata = { + { /* Toshiba TC59SM716 CL2 */ + .name = "TC59SM716-CL2", + .rows = 12, + .tck = 10, + .trcd = 20, + .trp = 20, + .twr = 10, + .refresh = 64000, + .cas_latency = 2, + }, { /* Toshiba TC59SM716 CL3 */ + .name = "TC59SM716-CL3", + .rows = 12, + .tck = 8, + .trcd = 20, + .trp = 20, + .twr = 8, + .refresh = 64000, + .cas_latency = 3, + }, { /* Samsung K4S641632D TC75 */ + .name = "K4S641632D", + .rows = 14, + .tck = 9, + .trcd = 27, + .trp = 20, + .twr = 9, + .refresh = 64000, + .cas_latency = 3, + }, { /* Samsung KM416S4030CT */ + .name = "KM416S4030CT", + .rows = 13, + .tck = 8, + .trcd = 24, /* 3 CLKs */ + .trp = 24, /* 3 CLKs */ + .twr = 16, /* Trdl: 2 CLKs */ + .refresh = 64000, + .cas_latency = 3, + }, { /* Winbond W982516AH75L CL3 */ + .name = "W982516AH75L", + .rows = 16, + .tck = 8, + .trcd = 20, + .trp = 20, + .twr = 8, + .refresh = 64000, + .cas_latency = 3, + }, }; static struct sdram_params sdram_params; @@ -336,19 +339,36 @@ static struct cpufreq_driver sa1110_driver = { .name = "sa1110", }; +static struct sdram_params *sa1110_find_sdram(const char *name) +{ + struct sdram_params *sdram; + + for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); sdram++) + if (strcmp(name, sdram->name) == 0) + return sdram; + + return NULL; +} + +static char sdram_name[16]; + static int __init sa1110_clk_init(void) { - struct sdram_params *sdram = NULL; + struct sdram_params *sdram; + const char *name = sdram_name; - if (machine_is_assabet()) - sdram = &tc59sm716_cl3_params; + if (!name[0]) { + if (machine_is_assabet()) + name = "TC59SM716-CL3"; - if (machine_is_pt_system3()) - sdram = &samsung_k4s641632d_tc75; + if (machine_is_pt_system3()) + name = "K4S641632D"; - if (machine_is_h3100()) - sdram = &samsung_km416s4030ct; + if (machine_is_h3100()) + name = "KM416S4030CT"; + } + sdram = sa1110_find_sdram(name); if (sdram) { printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d" " twr: %d refresh: %d cas_latency: %d\n", @@ -363,4 +383,5 @@ static int __init sa1110_clk_init(void) return 0; } +module_param_string(sdram, sdram_name, sizeof(sdram_name), 0); arch_initcall(sa1110_clk_init); diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c index be0e4427bec..3c6441d4bc5 100644 --- a/arch/arm/mach-sa1100/dma.c +++ b/arch/arm/mach-sa1100/dma.c @@ -124,7 +124,7 @@ int sa1100_request_dma (dma_device_t device, const char *device_id, i = dma - dma_chan; regs = (dma_regs_t *)&DDAR(i); - err = request_irq(IRQ_DMA0 + i, dma_irq_handler, SA_INTERRUPT, + err = request_irq(IRQ_DMA0 + i, dma_irq_handler, IRQF_DISABLED, device_id, regs); if (err) { printk(KERN_ERR diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index e727ba87b9f..7364478cec1 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -740,7 +740,7 @@ static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc, struct pt_re static struct irqaction h3800_irq = { .name = "h3800_asic", .handler = h3800_IRQ_demux, - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, }; u32 kpio_int_shadow = 0; @@ -835,7 +835,7 @@ static void __init h3800_init_irq(void) } #endif set_irq_type(IRQ_GPIO_H3800_ASIC, IRQT_RISING); - set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, &h3800_IRQ_demux); + set_irq_chained_handler(IRQ_GPIO_H3800_ASIC, h3800_IRQ_demux); } diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index b3a56024182..2891b8ca86d 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -11,12 +11,13 @@ */ #include <linux/init.h> #include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/ioport.h> #include <linux/ptrace.h> #include <linux/sysdev.h> #include <asm/hardware.h> -#include <asm/irq.h> #include <asm/mach/irq.h> #include "generic.h" diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c index 0709ebab531..c7bf7e0038f 100644 --- a/arch/arm/mach-sa1100/pleb.c +++ b/arch/arm/mach-sa1100/pleb.c @@ -7,6 +7,7 @@ #include <linux/tty.h> #include <linux/ioport.h> #include <linux/platform_device.h> +#include <linux/irq.h> #include <linux/mtd/partitions.h> diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index e4b435e634e..49ae716e16c 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -11,6 +11,7 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/timex.h> #include <linux/signal.h> @@ -110,7 +111,7 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction sa1100_timer_irq = { .name = "SA11xx Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = sa1100_timer_interrupt, }; diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index 877600e212d..1095df34fec 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c @@ -6,6 +6,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/sched.h> #include <linux/serial_8250.h> @@ -89,7 +90,7 @@ shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction shark_timer_irq = { .name = "Shark Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = shark_timer_interrupt, }; diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 08de8490fb6..a432539cc1b 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -869,7 +869,7 @@ static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_re static struct irqaction versatile_timer_irq = { .name = "Versatile Timer Tick", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = versatile_timer_interrupt, }; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c4bca753165..5f80f184cd3 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -121,8 +121,8 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 + depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 + default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_CACHE_VIVT diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 7691cfdba56..dba7dddfe57 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -27,7 +27,16 @@ #include <asm/cacheflush.h> #include <asm/io.h> +#include <asm/mmu_context.h> +#include <asm/pgalloc.h> #include <asm/tlbflush.h> +#include <asm/sizes.h> + +/* + * Used by ioremap() and iounmap() code to mark (super)section-mapped + * I/O regions in vm_struct->flags field. + */ +#define VM_ARM_SECTION_MAPPING 0x80000000 static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, @@ -113,10 +122,168 @@ remap_area_pages(unsigned long start, unsigned long pfn, dir++; } while (address && (address < end)); - flush_cache_vmap(start, end); return err; } + +void __check_kvm_seq(struct mm_struct *mm) +{ + unsigned int seq; + + do { + seq = init_mm.context.kvm_seq; + memcpy(pgd_offset(mm, VMALLOC_START), + pgd_offset_k(VMALLOC_START), + sizeof(pgd_t) * (pgd_index(VMALLOC_END) - + pgd_index(VMALLOC_START))); + mm->context.kvm_seq = seq; + } while (seq != init_mm.context.kvm_seq); +} + +#ifndef CONFIG_SMP +/* + * Section support is unsafe on SMP - If you iounmap and ioremap a region, + * the other CPUs will not see this change until their next context switch. + * Meanwhile, (eg) if an interrupt comes in on one of those other CPUs + * which requires the new ioremap'd region to be referenced, the CPU will + * reference the _old_ region. + * + * Note that get_vm_area() allocates a guard 4K page, so we need to mask + * the size back to 1MB aligned or we will overflow in the loop below. + */ +static void unmap_area_sections(unsigned long virt, unsigned long size) +{ + unsigned long addr = virt, end = virt + (size & ~SZ_1M); + pgd_t *pgd; + + flush_cache_vunmap(addr, end); + pgd = pgd_offset_k(addr); + do { + pmd_t pmd, *pmdp = pmd_offset(pgd, addr); + + pmd = *pmdp; + if (!pmd_none(pmd)) { + /* + * Clear the PMD from the page table, and + * increment the kvm sequence so others + * notice this change. + * + * Note: this is still racy on SMP machines. + */ + pmd_clear(pmdp); + init_mm.context.kvm_seq++; + + /* + * Free the page table, if there was one. + */ + if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) + pte_free_kernel(pmd_page_kernel(pmd)); + } + + addr += PGDIR_SIZE; + pgd++; + } while (addr < end); + + /* + * Ensure that the active_mm is up to date - we want to + * catch any use-after-iounmap cases. + */ + if (current->active_mm->context.kvm_seq != init_mm.context.kvm_seq) + __check_kvm_seq(current->active_mm); + + flush_tlb_kernel_range(virt, end); +} + +static int +remap_area_sections(unsigned long virt, unsigned long pfn, + unsigned long size, unsigned long flags) +{ + unsigned long prot, addr = virt, end = virt + size; + pgd_t *pgd; + + /* + * Remove and free any PTE-based mapping, and + * sync the current kernel mapping. + */ + unmap_area_sections(virt, size); + + prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO) | + (flags & (L_PTE_CACHEABLE | L_PTE_BUFFERABLE)); + + /* + * ARMv6 and above need XN set to prevent speculative prefetches + * hitting IO. + */ + if (cpu_architecture() >= CPU_ARCH_ARMv6) + prot |= PMD_SECT_XN; + + pgd = pgd_offset_k(addr); + do { + pmd_t *pmd = pmd_offset(pgd, addr); + + pmd[0] = __pmd(__pfn_to_phys(pfn) | prot); + pfn += SZ_1M >> PAGE_SHIFT; + pmd[1] = __pmd(__pfn_to_phys(pfn) | prot); + pfn += SZ_1M >> PAGE_SHIFT; + flush_pmd_entry(pmd); + + addr += PGDIR_SIZE; + pgd++; + } while (addr < end); + + return 0; +} + +static int +remap_area_supersections(unsigned long virt, unsigned long pfn, + unsigned long size, unsigned long flags) +{ + unsigned long prot, addr = virt, end = virt + size; + pgd_t *pgd; + + /* + * Remove and free any PTE-based mapping, and + * sync the current kernel mapping. + */ + unmap_area_sections(virt, size); + + prot = PMD_TYPE_SECT | PMD_SECT_SUPER | PMD_SECT_AP_WRITE | + PMD_DOMAIN(DOMAIN_IO) | + (flags & (L_PTE_CACHEABLE | L_PTE_BUFFERABLE)); + + /* + * ARMv6 and above need XN set to prevent speculative prefetches + * hitting IO. + */ + if (cpu_architecture() >= CPU_ARCH_ARMv6) + prot |= PMD_SECT_XN; + + pgd = pgd_offset_k(virt); + do { + unsigned long super_pmd_val, i; + + super_pmd_val = __pfn_to_phys(pfn) | prot; + super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20; + + for (i = 0; i < 8; i++) { + pmd_t *pmd = pmd_offset(pgd, addr); + + pmd[0] = __pmd(super_pmd_val); + pmd[1] = __pmd(super_pmd_val); + flush_pmd_entry(pmd); + + addr += PGDIR_SIZE; + pgd++; + } + + pfn += SUPERSECTION_SIZE >> PAGE_SHIFT; + } while (addr < end); + + return 0; +} +#endif + + /* * Remap an arbitrary physical address space into the kernel virtual * address space. Needed when the kernel wants to access high addresses @@ -133,18 +300,41 @@ void __iomem * __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, unsigned long flags) { + int err; unsigned long addr; struct vm_struct * area; + /* + * High mappings must be supersection aligned + */ + if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) + return NULL; + area = get_vm_area(size, VM_IOREMAP); if (!area) return NULL; addr = (unsigned long)area->addr; - if (remap_area_pages(addr, pfn, size, flags)) { + +#ifndef CONFIG_SMP + if ((((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) || + cpu_is_xsc3()) && + !((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) { + area->flags |= VM_ARM_SECTION_MAPPING; + err = remap_area_supersections(addr, pfn, size, flags); + } else if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) { + area->flags |= VM_ARM_SECTION_MAPPING; + err = remap_area_sections(addr, pfn, size, flags); + } else +#endif + err = remap_area_pages(addr, pfn, size, flags); + + if (err) { vunmap((void *)addr); return NULL; } - return (void __iomem *) (offset + (char *)addr); + + flush_cache_vmap(addr, addr + size); + return (void __iomem *) (offset + addr); } EXPORT_SYMBOL(__ioremap_pfn); @@ -173,6 +363,36 @@ EXPORT_SYMBOL(__ioremap); void __iounmap(void __iomem *addr) { - vunmap((void *)(PAGE_MASK & (unsigned long)addr)); + struct vm_struct **p, *tmp; + unsigned int section_mapping = 0; + + addr = (void __iomem *)(PAGE_MASK & (unsigned long)addr); + +#ifndef CONFIG_SMP + /* + * If this is a section based mapping we need to handle it + * specially as the VM subysystem does not know how to handle + * such a beast. We need the lock here b/c we need to clear + * all the mappings before the area can be reclaimed + * by someone else. + */ + write_lock(&vmlist_lock); + for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { + if((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { + if (tmp->flags & VM_ARM_SECTION_MAPPING) { + *p = tmp->next; + unmap_area_sections((unsigned long)tmp->addr, + tmp->size); + kfree(tmp); + section_mapping = 1; + } + break; + } + } + write_unlock(&vmlist_lock); +#endif + + if (!section_mapping) + vunmap(addr); } EXPORT_SYMBOL(__iounmap); diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index b0242c6ea06..38769f5862b 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -302,16 +302,16 @@ static struct mem_types mem_types[] __initdata = { .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE, .prot_l1 = PMD_TYPE_TABLE, - .prot_sect = PMD_TYPE_SECT | PMD_SECT_UNCACHED | + .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED | PMD_SECT_AP_WRITE, .domain = DOMAIN_IO, }, [MT_CACHECLEAN] = { - .prot_sect = PMD_TYPE_SECT, + .prot_sect = PMD_TYPE_SECT | PMD_BIT4, .domain = DOMAIN_KERNEL, }, [MT_MINICLEAN] = { - .prot_sect = PMD_TYPE_SECT | PMD_SECT_MINICACHE, + .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_MINICACHE, .domain = DOMAIN_KERNEL, }, [MT_LOW_VECTORS] = { @@ -327,25 +327,25 @@ static struct mem_types mem_types[] __initdata = { .domain = DOMAIN_USER, }, [MT_MEMORY] = { - .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE, + .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_AP_WRITE, .domain = DOMAIN_KERNEL, }, [MT_ROM] = { - .prot_sect = PMD_TYPE_SECT, + .prot_sect = PMD_TYPE_SECT | PMD_BIT4, .domain = DOMAIN_KERNEL, }, [MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE, .prot_l1 = PMD_TYPE_TABLE, - .prot_sect = PMD_TYPE_SECT | PMD_SECT_UNCACHED | + .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_UNCACHED | PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE | PMD_SECT_TEX(1), .domain = DOMAIN_IO, }, [MT_NONSHARED_DEVICE] = { .prot_l1 = PMD_TYPE_TABLE, - .prot_sect = PMD_TYPE_SECT | PMD_SECT_NONSHARED_DEV | + .prot_sect = PMD_TYPE_SECT | PMD_BIT4 | PMD_SECT_NONSHARED_DEV | PMD_SECT_AP_WRITE, .domain = DOMAIN_IO, } @@ -375,14 +375,21 @@ void __init build_mem_type_table(void) ecc_mask = 0; } - if (cpu_arch <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) { - for (i = 0; i < ARRAY_SIZE(mem_types); i++) { + /* + * Xscale must not have PMD bit 4 set for section mappings. + */ + if (cpu_is_xscale()) + for (i = 0; i < ARRAY_SIZE(mem_types); i++) + mem_types[i].prot_sect &= ~PMD_BIT4; + + /* + * ARMv5 and lower, excluding Xscale, bit 4 must be set for + * page tables. + */ + if (cpu_arch < CPU_ARCH_ARMv6 && !cpu_is_xscale()) + for (i = 0; i < ARRAY_SIZE(mem_types); i++) if (mem_types[i].prot_l1) mem_types[i].prot_l1 |= PMD_BIT4; - if (mem_types[i].prot_sect) - mem_types[i].prot_sect |= PMD_BIT4; - } - } cp = &cache_policies[cachepolicy]; kern_pgprot = user_pgprot = cp->pte; @@ -406,8 +413,8 @@ void __init build_mem_type_table(void) * bit 4 becomes XN which we must clear for the * kernel memory mapping. */ - mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; - mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; + mem_types[MT_MEMORY].prot_sect &= ~PMD_SECT_XN; + mem_types[MT_ROM].prot_sect &= ~PMD_SECT_XN; /* * Mark cache clean areas and XIP ROM read only diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index cc609666df0..1d8316f3cec 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -34,6 +34,8 @@ #include <asm/procinfo.h> #include <asm/ptrace.h> +#include "proc-macros.S" + /* * This is the maximum size of an area which will be invalidated * using the single invalidate entry instructions. Anything larger @@ -439,11 +441,12 @@ __arm1020_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 #endif + + adr r5, arm1020_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm1020_cr1_clear bic r0, r0, r5 - ldr r5, arm1020_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .R.. .... .... .... #endif @@ -455,12 +458,9 @@ __arm1020_setup: * .RVI ZFRS BLDP WCAM * .011 1001 ..11 0101 */ - .type arm1020_cr1_clear, #object - .type arm1020_cr1_set, #object -arm1020_cr1_clear: - .word 0x593f -arm1020_cr1_set: - .word 0x3935 + .type arm1020_crval, #object +arm1020_crval: + crval clear=0x0000593f, mmuset=0x00003935, ucset=0x00001930 __INITDATA @@ -526,6 +526,9 @@ __arm1020_proc_info: .long PMD_TYPE_SECT | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm1020_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 117a946c28c..89b1d6d3d7c 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -34,6 +34,8 @@ #include <asm/procinfo.h> #include <asm/ptrace.h> +#include "proc-macros.S" + /* * This is the maximum size of an area which will be invalidated * using the single invalidate entry instructions. Anything larger @@ -421,11 +423,11 @@ __arm1020e_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 #endif + adr r5, arm1020e_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm1020e_cr1_clear bic r0, r0, r5 - ldr r5, arm1020e_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .R.. .... .... .... #endif @@ -437,12 +439,9 @@ __arm1020e_setup: * .RVI ZFRS BLDP WCAM * .011 1001 ..11 0101 */ - .type arm1020e_cr1_clear, #object - .type arm1020e_cr1_set, #object -arm1020e_cr1_clear: - .word 0x5f3f -arm1020e_cr1_set: - .word 0x3935 + .type arm1020e_crval, #object +arm1020e_crval: + crval clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001930 __INITDATA @@ -476,25 +475,7 @@ cpu_elf_name: .type cpu_arm1020e_name, #object cpu_arm1020e_name: - .ascii "ARM1020E" -#ifndef CONFIG_CPU_ICACHE_DISABLE - .ascii "i" -#endif -#ifndef CONFIG_CPU_DCACHE_DISABLE - .ascii "d" -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - .ascii "(wt)" -#else - .ascii "(wb)" -#endif -#endif -#ifndef CONFIG_CPU_BPREDICT_DISABLE - .ascii "B" -#endif -#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN - .ascii "RR" -#endif - .ascii "\0" + .asciz "ARM1020E" .size cpu_arm1020e_name, . - cpu_arm1020e_name .align @@ -509,6 +490,10 @@ __arm1020e_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm1020e_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 39b7c102180..a089528e6bc 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -23,6 +23,8 @@ #include <asm/procinfo.h> #include <asm/ptrace.h> +#include "proc-macros.S" + /* * This is the maximum size of an area which will be invalidated * using the single invalidate entry instructions. Anything larger @@ -403,11 +405,11 @@ __arm1022_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 #endif + adr r5, arm1022_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm1022_cr1_clear bic r0, r0, r5 - ldr r5, arm1022_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .R.............. #endif @@ -420,12 +422,9 @@ __arm1022_setup: * .011 1001 ..11 0101 * */ - .type arm1022_cr1_clear, #object - .type arm1022_cr1_set, #object -arm1022_cr1_clear: - .word 0x7f3f -arm1022_cr1_set: - .word 0x3935 + .type arm1022_crval, #object +arm1022_crval: + crval clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001930 __INITDATA @@ -459,25 +458,7 @@ cpu_elf_name: .type cpu_arm1022_name, #object cpu_arm1022_name: - .ascii "arm1022" -#ifndef CONFIG_CPU_ICACHE_DISABLE - .ascii "i" -#endif -#ifndef CONFIG_CPU_DCACHE_DISABLE - .ascii "d" -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - .ascii "(wt)" -#else - .ascii "(wb)" -#endif -#endif -#ifndef CONFIG_CPU_BPREDICT_DISABLE - .ascii "B" -#endif -#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN - .ascii "RR" -#endif - .ascii "\0" + .asciz "ARM1022" .size cpu_arm1022_name, . - cpu_arm1022_name .align @@ -492,6 +473,10 @@ __arm1022_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm1022_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 33e1ab8eb1d..d6d84d92c7c 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -23,6 +23,8 @@ #include <asm/procinfo.h> #include <asm/ptrace.h> +#include "proc-macros.S" + /* * This is the maximum size of an area which will be invalidated * using the single invalidate entry instructions. Anything larger @@ -398,11 +400,11 @@ __arm1026_setup: mov r0, #4 @ explicitly disable writeback mcr p15, 7, r0, c15, c0, 0 #endif + adr r5, arm1026_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm1026_cr1_clear bic r0, r0, r5 - ldr r5, arm1026_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .R.. .... .... .... #endif @@ -415,12 +417,9 @@ __arm1026_setup: * .011 1001 ..11 0101 * */ - .type arm1026_cr1_clear, #object - .type arm1026_cr1_set, #object -arm1026_cr1_clear: - .word 0x7f3f -arm1026_cr1_set: - .word 0x3935 + .type arm1026_crval, #object +arm1026_crval: + crval clear=0x00007f3f, mmuset=0x00003935, ucset=0x00001934 __INITDATA @@ -455,25 +454,7 @@ cpu_elf_name: .type cpu_arm1026_name, #object cpu_arm1026_name: - .ascii "ARM1026EJ-S" -#ifndef CONFIG_CPU_ICACHE_DISABLE - .ascii "i" -#endif -#ifndef CONFIG_CPU_DCACHE_DISABLE - .ascii "d" -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - .ascii "(wt)" -#else - .ascii "(wb)" -#endif -#endif -#ifndef CONFIG_CPU_BPREDICT_DISABLE - .ascii "B" -#endif -#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN - .ascii "RR" -#endif - .ascii "\0" + .asciz "ARM1026EJ-S" .size cpu_arm1026_name, . - cpu_arm1026_name .align @@ -488,6 +469,10 @@ __arm1026_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm1026_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index 7a705edfa4b..0432e480688 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S @@ -355,6 +355,10 @@ __arm6_proc_info: .long 0x41560600 .long 0xfffffff0 .long 0x00000c1e + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm6_setup .long cpu_arch_name .long cpu_elf_name @@ -371,6 +375,10 @@ __arm610_proc_info: .long 0x41560610 .long 0xfffffff0 .long 0x00000c1e + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm6_setup .long cpu_arch_name .long cpu_elf_name @@ -387,6 +395,10 @@ __arm7_proc_info: .long 0x41007000 .long 0xffffff00 .long 0x00000c1e + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm7_setup .long cpu_arch_name .long cpu_elf_name @@ -408,6 +420,10 @@ __arm710_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm7_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index 86102467d37..c2f0705bfd4 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -41,6 +41,8 @@ #include <asm/procinfo.h> #include <asm/ptrace.h> +#include "proc-macros.S" + /* * Function: arm720_proc_init (void) * : arm720_proc_fin (void) @@ -169,11 +171,11 @@ __arm720_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ flush TLB (v4) #endif + adr r5, arm720_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register - ldr r5, arm720_cr1_clear bic r0, r0, r5 - ldr r5, arm720_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 mov pc, lr @ __ret (head.S) .size __arm720_setup, . - __arm720_setup @@ -183,12 +185,9 @@ __arm720_setup: * ..1. 1001 ..11 1101 * */ - .type arm720_cr1_clear, #object - .type arm720_cr1_set, #object -arm720_cr1_clear: - .word 0x2f3f -arm720_cr1_set: - .word 0x213d + .type arm720_crval, #object +arm720_crval: + crval clear=0x00002f3f, mmuset=0x0000213d, ucset=0x00000130 __INITDATA @@ -246,6 +245,10 @@ __arm710_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm710_setup @ cpu_flush .long cpu_arch_name @ arch_name .long cpu_elf_name @ elf_name @@ -267,6 +270,10 @@ __arm720_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm720_setup @ cpu_flush .long cpu_arch_name @ arch_name .long cpu_elf_name @ elf_name diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 6f0db29ab84..4adb46b3a4e 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -390,11 +390,11 @@ __arm920_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 #endif + adr r5, arm920_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm920_cr1_clear bic r0, r0, r5 - ldr r5, arm920_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 mov pc, lr .size __arm920_setup, . - __arm920_setup @@ -404,12 +404,9 @@ __arm920_setup: * ..11 0001 ..11 0101 * */ - .type arm920_cr1_clear, #object - .type arm920_cr1_set, #object -arm920_cr1_clear: - .word 0x3f3f -arm920_cr1_set: - .word 0x3135 + .type arm920_crval, #object +arm920_crval: + crval clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130 __INITDATA @@ -443,19 +440,7 @@ cpu_elf_name: .type cpu_arm920_name, #object cpu_arm920_name: - .ascii "ARM920T" -#ifndef CONFIG_CPU_ICACHE_DISABLE - .ascii "i" -#endif -#ifndef CONFIG_CPU_DCACHE_DISABLE - .ascii "d" -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - .ascii "(wt)" -#else - .ascii "(wb)" -#endif -#endif - .ascii "\0" + .asciz "ARM920T" .size cpu_arm920_name, . - cpu_arm920_name .align @@ -472,6 +457,10 @@ __arm920_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm920_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 1ad464cc7bc..571f082f024 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -394,11 +394,11 @@ __arm922_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 #endif + adr r5, arm922_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm922_cr1_clear bic r0, r0, r5 - ldr r5, arm922_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 mov pc, lr .size __arm922_setup, . - __arm922_setup @@ -408,12 +408,9 @@ __arm922_setup: * ..11 0001 ..11 0101 * */ - .type arm922_cr1_clear, #object - .type arm922_cr1_set, #object -arm922_cr1_clear: - .word 0x3f3f -arm922_cr1_set: - .word 0x3135 + .type arm922_crval, #object +arm922_crval: + crval clear=0x00003f3f, mmuset=0x00003135, ucset=0x00001130 __INITDATA @@ -447,19 +444,7 @@ cpu_elf_name: .type cpu_arm922_name, #object cpu_arm922_name: - .ascii "ARM922T" -#ifndef CONFIG_CPU_ICACHE_DISABLE - .ascii "i" -#endif -#ifndef CONFIG_CPU_DCACHE_DISABLE - .ascii "d" -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - .ascii "(wt)" -#else - .ascii "(wb)" -#endif -#endif - .ascii "\0" + .asciz "ARM922T" .size cpu_arm922_name, . - cpu_arm922_name .align @@ -476,6 +461,10 @@ __arm922_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm922_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index a55d56ce226..8d9a9f93b01 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -454,11 +454,11 @@ __arm925_setup: mcr p15, 7, r0, c15, c0, 0 #endif + adr r5, arm925_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm925_cr1_clear bic r0, r0, r5 - ldr r5, arm925_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .1.. .... .... .... #endif @@ -471,12 +471,9 @@ __arm925_setup: * .011 0001 ..11 1101 * */ - .type arm925_cr1_clear, #object - .type arm925_cr1_set, #object -arm925_cr1_clear: - .word 0x7f3f -arm925_cr1_set: - .word 0x313d + .type arm925_crval, #object +arm925_crval: + crval clear=0x00007f3f, mmuset=0x0000313d, ucset=0x00001130 __INITDATA @@ -510,22 +507,7 @@ cpu_elf_name: .type cpu_arm925_name, #object cpu_arm925_name: - .ascii "ARM925T" -#ifndef CONFIG_CPU_ICACHE_DISABLE - .ascii "i" -#endif -#ifndef CONFIG_CPU_DCACHE_DISABLE - .ascii "d" -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - .ascii "(wt)" -#else - .ascii "(wb)" -#endif -#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN - .ascii "RR" -#endif -#endif - .ascii "\0" + .asciz "ARM925T" .size cpu_arm925_name, . - cpu_arm925_name .align @@ -540,6 +522,10 @@ __arm925_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm925_setup .long cpu_arch_name .long cpu_elf_name @@ -559,6 +545,10 @@ __arm915_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm925_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 20275967663..1e89d408047 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -403,11 +403,11 @@ __arm926_setup: mcr p15, 7, r0, c15, c0, 0 #endif + adr r5, arm926_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, arm926_cr1_clear bic r0, r0, r5 - ldr r5, arm926_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 #ifdef CONFIG_CPU_CACHE_ROUND_ROBIN orr r0, r0, #0x4000 @ .1.. .... .... .... #endif @@ -420,12 +420,9 @@ __arm926_setup: * .011 0001 ..11 0101 * */ - .type arm926_cr1_clear, #object - .type arm926_cr1_set, #object -arm926_cr1_clear: - .word 0x7f3f -arm926_cr1_set: - .word 0x3135 + .type arm926_crval, #object +arm926_crval: + crval clear=0x00007f3f, mmuset=0x00003135, ucset=0x00001134 __INITDATA @@ -459,22 +456,7 @@ cpu_elf_name: .type cpu_arm926_name, #object cpu_arm926_name: - .ascii "ARM926EJ-S" -#ifndef CONFIG_CPU_ICACHE_DISABLE - .ascii "i" -#endif -#ifndef CONFIG_CPU_DCACHE_DISABLE - .ascii "d" -#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH - .ascii "(wt)" -#else - .ascii "(wb)" -#endif -#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN - .ascii "RR" -#endif -#endif - .ascii "\0" + .asciz "ARM926EJ-S" .size cpu_arm926_name, . - cpu_arm926_name .align @@ -491,6 +473,10 @@ __arm926_proc_info: PMD_BIT4 | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_BIT4 | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __arm926_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 7cfc2604a1e..9e2c89eb211 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -49,3 +49,13 @@ .macro asid, rd, rn and \rd, \rn, #255 .endm + + .macro crval, clear, mmuset, ucset +#ifdef CONFIG_MMU + .word \clear + .word \mmuset +#else + .word \clear + .word \ucset +#endif + .endm diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 5a760a2c629..c878064e9b8 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -23,6 +23,8 @@ #include <asm/pgtable.h> #include <asm/ptrace.h> +#include "proc-macros.S" + /* * the cache line size of the I and D cache */ @@ -185,11 +187,12 @@ __sa110_setup: #ifdef CONFIG_MMU mcr p15, 0, r10, c8, c7 @ invalidate I,D TLBs on v4 #endif + + adr r5, sa110_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, sa110_cr1_clear bic r0, r0, r5 - ldr r5, sa110_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 mov pc, lr .size __sa110_setup, . - __sa110_setup @@ -199,12 +202,9 @@ __sa110_setup: * ..01 0001 ..11 1101 * */ - .type sa110_cr1_clear, #object - .type sa110_cr1_set, #object -sa110_cr1_clear: - .word 0x3f3f -sa110_cr1_set: - .word 0x113d + .type sa110_crval, #object +sa110_crval: + crval clear=0x00003f3f, mmuset=0x0000113d, ucset=0x00001130 __INITDATA @@ -255,6 +255,9 @@ __sa110_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __sa110_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index 0a2107ad4c3..b23b66a6155 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -27,6 +27,8 @@ #include <asm/pgtable-hwdef.h> #include <asm/pgtable.h> +#include "proc-macros.S" + /* * the cache line size of the I and D cache */ @@ -198,11 +200,11 @@ __sa1100_setup: #ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 #endif + adr r5, sa1100_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0 @ get control register v4 - ldr r5, sa1100_cr1_clear bic r0, r0, r5 - ldr r5, sa1100_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 mov pc, lr .size __sa1100_setup, . - __sa1100_setup @@ -212,12 +214,9 @@ __sa1100_setup: * ..11 0001 ..11 1101 * */ - .type sa1100_cr1_clear, #object - .type sa1100_cr1_set, #object -sa1100_cr1_clear: - .word 0x3f3f -sa1100_cr1_set: - .word 0x313d + .type sa1100_crval, #object +sa1100_crval: + crval clear=0x00003f3f, mmuset=0x0000313d, ucset=0x00001130 __INITDATA @@ -276,6 +275,9 @@ __sa1100_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __sa1100_setup .long cpu_arch_name .long cpu_elf_name @@ -296,6 +298,9 @@ __sa1110_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __sa1100_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index ca13d4d05f6..6f72549f884 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -212,11 +212,11 @@ __v6_setup: orr r0, r0, #(0xf << 20) mcr p15, 0, r0, c1, c0, 2 @ Enable full access to VFP #endif + adr r5, v6_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0, 0 @ read control register - ldr r5, v6_cr1_clear @ get mask for bits to clear bic r0, r0, r5 @ clear bits them - ldr r5, v6_cr1_set @ get mask for bits to set - orr r0, r0, r5 @ set them + orr r0, r0, r6 @ set them mov pc, lr @ return to head.S:__ret /* @@ -225,12 +225,9 @@ __v6_setup: * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced * 0 110 0011 1.00 .111 1101 < we want */ - .type v6_cr1_clear, #object - .type v6_cr1_set, #object -v6_cr1_clear: - .word 0x01e0fb7f -v6_cr1_set: - .word 0x00c0387d + .type v6_crval, #object +v6_crval: + crval clear=0x01e0fb7f, mmuset=0x00c0387d, ucset=0x00c0187c .type v6_processor_functions, #object ENTRY(v6_processor_functions) @@ -269,6 +266,10 @@ __v6_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_XN | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __v6_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 8d32e21fe15..4ace2d8090c 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -426,23 +426,26 @@ __xsc3_setup: orr r0, r0, #(1 << 10) @ enable L2 for LLR cache #endif mcr p15, 0, r0, c1, c0, 1 @ set auxiliary control reg + + adr r5, xsc3_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0, 0 @ get control register - bic r0, r0, #0x0002 @ .... .... .... ..A. - orr r0, r0, #0x0005 @ .... .... .... .C.M + bic r0, r0, r5 @ .... .... .... ..A. + orr r0, r0, r6 @ .... .... .... .C.M #if BTB_ENABLE - bic r0, r0, #0x0200 @ .... ..R. .... .... - orr r0, r0, #0x3900 @ ..VI Z..S .... .... -#else - bic r0, r0, #0x0a00 @ .... Z.R. .... .... - orr r0, r0, #0x3100 @ ..VI ...S .... .... + orr r0, r0, #0x00000800 @ ..VI Z..S .... .... #endif #if L2_CACHE_ENABLE - orr r0, r0, #0x4000000 @ L2 enable + orr r0, r0, #0x04000000 @ L2 enable #endif mov pc, lr .size __xsc3_setup, . - __xsc3_setup + .type xsc3_crval, #object +xsc3_crval: + crval clear=0x04003b02, mmuset=0x00003105, ucset=0x00001100 + __INITDATA /* @@ -487,7 +490,14 @@ cpu_xsc3_name: __xsc3_proc_info: .long 0x69056000 .long 0xffffe000 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xsc3_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 29bcc4dd651..521538671f4 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -138,17 +138,23 @@ ENTRY(cpu_xscale_proc_fin) * to what would be the reset vector. * * loc: location to jump to for soft reset + * + * Beware PXA270 erratum E7. */ .align 5 ENTRY(cpu_xscale_reset) mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE msr cpsr_c, r1 @ reset CPSR + mcr p15, 0, r1, c10, c4, 1 @ unlock I-TLB + mcr p15, 0, r1, c8, c5, 0 @ invalidate I-TLB mrc p15, 0, r1, c1, c0, 0 @ ctrl register bic r1, r1, #0x0086 @ ........B....CA. bic r1, r1, #0x3900 @ ..VIZ..S........ + sub pc, pc, #4 @ flush pipeline + @ *** cache line aligned *** mcr p15, 0, r1, c1, c0, 0 @ ctrl register - mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB bic r1, r1, #0x0001 @ ...............M + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB mcr p15, 0, r1, c1, c0, 0 @ ctrl register @ CAUTION: MMU turned off from this point. We count on the pipeline @ already containing those two last instructions to survive. @@ -475,11 +481,12 @@ __xscale_setup: orr r0, r0, #1 << 6 @ cp6 for IOP3xx and Bulverde orr r0, r0, #1 << 13 @ Its undefined whether this mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes + + adr r5, xscale_crval + ldmia r5, {r5, r6} mrc p15, 0, r0, c1, c0, 0 @ get control register - ldr r5, xscale_cr1_clear bic r0, r0, r5 - ldr r5, xscale_cr1_set - orr r0, r0, r5 + orr r0, r0, r6 mov pc, lr .size __xscale_setup, . - __xscale_setup @@ -489,12 +496,9 @@ __xscale_setup: * ..11 1.01 .... .101 * */ - .type xscale_cr1_clear, #object - .type xscale_cr1_set, #object -xscale_cr1_clear: - .word 0x3b07 -xscale_cr1_set: - .word 0x3905 + .type xscale_crval, #object +xscale_crval: + crval clear=0x00003b07, mmuset=0x00003905, ucset=0x00001900 __INITDATA @@ -595,6 +599,9 @@ __80200_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -615,6 +622,9 @@ __8032x_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -635,6 +645,9 @@ __8033x_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -655,6 +668,9 @@ __pxa250_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -675,6 +691,9 @@ __pxa210_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -695,6 +714,9 @@ __ixp2400_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -715,6 +737,9 @@ __ixp2800_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -735,6 +760,9 @@ __ixp42x_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -750,7 +778,14 @@ __ixp42x_proc_info: __ixp46x_proc_info: .long 0x69054200 .long 0xffffff00 - .long 0x00000c0e + .long PMD_TYPE_SECT | \ + PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -771,6 +806,9 @@ __pxa255_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name @@ -791,6 +829,9 @@ __pxa270_proc_info: PMD_SECT_CACHEABLE | \ PMD_SECT_AP_WRITE | \ PMD_SECT_AP_READ + .long PMD_TYPE_SECT | \ + PMD_SECT_AP_WRITE | \ + PMD_SECT_AP_READ b __xscale_setup .long cpu_arch_name .long cpu_elf_name diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c index e0f0b320d76..34fdc733743 100644 --- a/arch/arm/oprofile/op_model_xscale.c +++ b/arch/arm/oprofile/op_model_xscale.c @@ -384,7 +384,7 @@ static int xscale_pmu_start(void) int ret; u32 pmnc = read_pmnc(); - ret = request_irq(XSCALE_PMU_IRQ, xscale_pmu_interrupt, SA_INTERRUPT, + ret = request_irq(XSCALE_PMU_IRQ, xscale_pmu_interrupt, IRQF_DISABLED, "XScale PMU", (void *)results); if (ret < 0) { diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index ec49495e651..ec752e16d61 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -91,7 +91,7 @@ config OMAP_32K_TIMER_HZ config OMAP_DM_TIMER bool "Use dual-mode timer" - depends on ARCH_OMAP16XX + depends on ARCH_OMAP16XX || ARCH_OMAP24XX help Select this option if you want to use OMAP Dual-Mode timers. diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index c520e9dcdd8..7f45c7c3e67 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -27,9 +27,9 @@ #include <asm/arch/clock.h> -LIST_HEAD(clocks); +static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); -DEFINE_SPINLOCK(clockfw_lock); +static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index 98edc9fdd6d..a0c71dca237 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c @@ -25,6 +25,14 @@ #include <asm/io.h> #include <asm/system.h> +#define VERY_HI_RATE 900000000 + +#ifdef CONFIG_ARCH_OMAP1 +#define MPU_CLK "mpu" +#else +#define MPU_CLK "virt_prcm_set" +#endif + /* TODO: Add support for SDRAM timing changes */ int omap_verify_speed(struct cpufreq_policy *policy) @@ -36,7 +44,7 @@ int omap_verify_speed(struct cpufreq_policy *policy) cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - mpu_clk = clk_get(NULL, "mpu"); + mpu_clk = clk_get(NULL, MPU_CLK); if (IS_ERR(mpu_clk)) return PTR_ERR(mpu_clk); policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000; @@ -56,7 +64,7 @@ unsigned int omap_getspeed(unsigned int cpu) if (cpu) return 0; - mpu_clk = clk_get(NULL, "mpu"); + mpu_clk = clk_get(NULL, MPU_CLK); if (IS_ERR(mpu_clk)) return 0; rate = clk_get_rate(mpu_clk) / 1000; @@ -73,7 +81,7 @@ static int omap_target(struct cpufreq_policy *policy, struct cpufreq_freqs freqs; int ret = 0; - mpu_clk = clk_get(NULL, "mpu"); + mpu_clk = clk_get(NULL, MPU_CLK); if (IS_ERR(mpu_clk)) return PTR_ERR(mpu_clk); @@ -93,7 +101,7 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) { struct clk * mpu_clk; - mpu_clk = clk_get(NULL, "mpu"); + mpu_clk = clk_get(NULL, MPU_CLK); if (IS_ERR(mpu_clk)) return PTR_ERR(mpu_clk); @@ -102,7 +110,7 @@ static int __init omap_cpu_init(struct cpufreq_policy *policy) policy->cur = policy->min = policy->max = omap_getspeed(0); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000; - policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, 216000000) / 1000; + policy->cpuinfo.max_freq = clk_round_rate(mpu_clk, VERY_HI_RATE) / 1000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; clk_put(mpu_clk); diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index ca486c9f36b..1812f237d12 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -104,7 +104,7 @@ static void omap_init_kp(void) omap_cfg_reg(E20_1610_KBR3); omap_cfg_reg(E19_1610_KBR4); omap_cfg_reg(N19_1610_KBR5); - } else if (machine_is_omap_perseus2()) { + } else if (machine_is_omap_perseus2() || machine_is_omap_fsample()) { omap_cfg_reg(E2_730_KBR0); omap_cfg_reg(J7_730_KBR1); omap_cfg_reg(E1_730_KBR2); @@ -161,8 +161,8 @@ static u64 mmc1_dmamask = 0xffffffff; static struct resource mmc1_resources[] = { { - .start = IO_ADDRESS(OMAP_MMC1_BASE), - .end = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f, + .start = OMAP_MMC1_BASE, + .end = OMAP_MMC1_BASE + 0x7f, .flags = IORESOURCE_MEM, }, { @@ -190,8 +190,8 @@ static u64 mmc2_dmamask = 0xffffffff; static struct resource mmc2_resources[] = { { - .start = IO_ADDRESS(OMAP_MMC2_BASE), - .end = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f, + .start = OMAP_MMC2_BASE, + .end = OMAP_MMC2_BASE + 0x7f, .flags = IORESOURCE_MEM, }, { diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 5dac4230360..9eddc950714 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -24,9 +24,9 @@ #include <linux/spinlock.h> #include <linux/errno.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <asm/system.h> -#include <asm/irq.h> #include <asm/hardware.h> #include <asm/dma.h> #include <asm/io.h> @@ -43,6 +43,7 @@ #define OMAP_DMA_ACTIVE 0x01 #define OMAP_DMA_CCR_EN (1 << 7) +#define OMAP2_DMA_CSR_CLEAR_MASK 0xffe #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) @@ -166,18 +167,24 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, if (cpu_is_omap24xx() && dma_trigger) { u32 val = OMAP_DMA_CCR_REG(lch); + val &= ~(3 << 19); if (dma_trigger > 63) val |= 1 << 20; if (dma_trigger > 31) val |= 1 << 19; + val &= ~(0x1f); val |= (dma_trigger & 0x1f); if (sync_mode & OMAP_DMA_SYNC_FRAME) val |= 1 << 5; + else + val &= ~(1 << 5); if (sync_mode & OMAP_DMA_SYNC_BLOCK) val |= 1 << 18; + else + val &= ~(1 << 18); if (src_or_dst_synch) val |= 1 << 24; /* source synch */ @@ -286,22 +293,39 @@ void omap_set_dma_src_data_pack(int lch, int enable) void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) { + unsigned int burst = 0; OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 7); switch (burst_mode) { case OMAP_DMA_DATA_BURST_DIS: break; case OMAP_DMA_DATA_BURST_4: - OMAP_DMA_CSDP_REG(lch) |= (0x02 << 7); + if (cpu_is_omap24xx()) + burst = 0x1; + else + burst = 0x2; break; case OMAP_DMA_DATA_BURST_8: - /* not supported by current hardware + if (cpu_is_omap24xx()) { + burst = 0x2; + break; + } + /* not supported by current hardware on OMAP1 * w |= (0x03 << 7); * fall through */ + case OMAP_DMA_DATA_BURST_16: + if (cpu_is_omap24xx()) { + burst = 0x3; + break; + } + /* OMAP1 don't support burst 16 + * fall through + */ default: BUG(); } + OMAP_DMA_CSDP_REG(lch) |= (burst << 7); } /* Note that dest_port is only for OMAP1 */ @@ -348,30 +372,49 @@ void omap_set_dma_dest_data_pack(int lch, int enable) void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) { + unsigned int burst = 0; OMAP_DMA_CSDP_REG(lch) &= ~(0x03 << 14); switch (burst_mode) { case OMAP_DMA_DATA_BURST_DIS: break; case OMAP_DMA_DATA_BURST_4: - OMAP_DMA_CSDP_REG(lch) |= (0x02 << 14); + if (cpu_is_omap24xx()) + burst = 0x1; + else + burst = 0x2; break; case OMAP_DMA_DATA_BURST_8: - OMAP_DMA_CSDP_REG(lch) |= (0x03 << 14); + if (cpu_is_omap24xx()) + burst = 0x2; + else + burst = 0x3; break; + case OMAP_DMA_DATA_BURST_16: + if (cpu_is_omap24xx()) { + burst = 0x3; + break; + } + /* OMAP1 don't support burst 16 + * fall through + */ default: printk(KERN_ERR "Invalid DMA burst mode\n"); BUG(); return; } + OMAP_DMA_CSDP_REG(lch) |= (burst << 14); } static inline void omap_enable_channel_irq(int lch) { u32 status; - /* Read CSR to make sure it's cleared. */ - status = OMAP_DMA_CSR_REG(lch); + /* Clear CSR */ + if (cpu_class_is_omap1()) + status = OMAP_DMA_CSR_REG(lch); + else if (cpu_is_omap24xx()) + OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK; /* Enable some nice interrupts. */ OMAP_DMA_CICR_REG(lch) = dma_chan[lch].enabled_irqs; @@ -470,11 +513,13 @@ int omap_request_dma(int dev_id, const char *dev_name, chan->dev_name = dev_name; chan->callback = callback; chan->data = data; - chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | - OMAP_DMA_BLOCK_IRQ; + chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; - if (cpu_is_omap24xx()) - chan->enabled_irqs |= OMAP2_DMA_TRANS_ERR_IRQ; + if (cpu_class_is_omap1()) + chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ; + else if (cpu_is_omap24xx()) + chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ | + OMAP2_DMA_TRANS_ERR_IRQ; if (cpu_is_omap16xx()) { /* If the sync device is set, configure it dynamically. */ @@ -494,7 +539,7 @@ int omap_request_dma(int dev_id, const char *dev_name, omap_enable_channel_irq(free_ch); /* Clear the CSR register and IRQ status register */ - OMAP_DMA_CSR_REG(free_ch) = 0x0; + OMAP_DMA_CSR_REG(free_ch) = OMAP2_DMA_CSR_CLEAR_MASK; omap_writel(~0x0, OMAP_DMA4_IRQSTATUS_L0); } @@ -534,7 +579,7 @@ void omap_free_dma(int lch) omap_writel(val, OMAP_DMA4_IRQENABLE_L0); /* Clear the CSR register and IRQ status register */ - OMAP_DMA_CSR_REG(lch) = 0x0; + OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK; val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); val |= 1 << lch; @@ -798,7 +843,7 @@ static int omap1_dma_handle_ch(int ch) "%d (CSR %04x)\n", ch, csr); return 0; } - if (unlikely(csr & OMAP_DMA_TOUT_IRQ)) + if (unlikely(csr & OMAP1_DMA_TOUT_IRQ)) printk(KERN_WARNING "DMA timeout with device %d\n", dma_chan[ch].dev_id); if (unlikely(csr & OMAP_DMA_DROP_IRQ)) @@ -846,20 +891,21 @@ static int omap2_dma_handle_ch(int ch) return 0; if (unlikely(dma_chan[ch].dev_id == -1)) return 0; - /* REVISIT: According to 24xx TRM, there's no TOUT_IE */ - if (unlikely(status & OMAP_DMA_TOUT_IRQ)) - printk(KERN_INFO "DMA timeout with device %d\n", - dma_chan[ch].dev_id); if (unlikely(status & OMAP_DMA_DROP_IRQ)) printk(KERN_INFO "DMA synchronization event drop occurred with device " "%d\n", dma_chan[ch].dev_id); - if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) printk(KERN_INFO "DMA transaction error with device %d\n", dma_chan[ch].dev_id); + if (unlikely(status & OMAP2_DMA_SECURE_ERR_IRQ)) + printk(KERN_INFO "DMA secure error with device %d\n", + dma_chan[ch].dev_id); + if (unlikely(status & OMAP2_DMA_MISALIGNED_ERR_IRQ)) + printk(KERN_INFO "DMA misaligned error with device %d\n", + dma_chan[ch].dev_id); - OMAP_DMA_CSR_REG(ch) = 0x20; + OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK; val = omap_readl(OMAP_DMA4_IRQSTATUS_L0); /* ch in this function is from 0-31 while in register it is 1-32 */ @@ -893,7 +939,7 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id, static struct irqaction omap24xx_dma_irq = { .name = "DMA", .handler = omap2_dma_irq_handler, - .flags = SA_INTERRUPT + .flags = IRQF_DISABLED }; #else diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index eba3cb52ad8..50524436de6 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -4,7 +4,8 @@ * OMAP Dual-Mode Timers * * Copyright (C) 2005 Nokia Corporation - * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com> + * OMAP2 support by Juha Yrjola + * API improvements and OMAP2 clock framework support by Timo Teras * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,15 +27,17 @@ */ #include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/errno.h> +#include <linux/list.h> +#include <linux/clk.h> +#include <linux/delay.h> #include <asm/hardware.h> #include <asm/arch/dmtimer.h> #include <asm/io.h> #include <asm/arch/irqs.h> -#include <linux/spinlock.h> -#include <linux/list.h> - -#define OMAP_TIMER_COUNT 8 +/* register offsets */ #define OMAP_TIMER_ID_REG 0x00 #define OMAP_TIMER_OCP_CFG_REG 0x10 #define OMAP_TIMER_SYS_STAT_REG 0x14 @@ -50,52 +53,196 @@ #define OMAP_TIMER_CAPTURE_REG 0x3c #define OMAP_TIMER_IF_CTRL_REG 0x40 +/* timer control reg bits */ +#define OMAP_TIMER_CTRL_GPOCFG (1 << 14) +#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13) +#define OMAP_TIMER_CTRL_PT (1 << 12) +#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8) +#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8) +#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8) +#define OMAP_TIMER_CTRL_SCPWM (1 << 7) +#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */ +#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */ +#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */ +#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */ +#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */ + +struct omap_dm_timer { + unsigned long phys_base; + int irq; +#ifdef CONFIG_ARCH_OMAP2 + struct clk *iclk, *fclk; +#endif + void __iomem *io_base; + unsigned reserved:1; +}; -static struct dmtimer_info_struct { - struct list_head unused_timers; - struct list_head reserved_timers; -} dm_timer_info; +#ifdef CONFIG_ARCH_OMAP1 static struct omap_dm_timer dm_timers[] = { - { .base=0xfffb1400, .irq=INT_1610_GPTIMER1 }, - { .base=0xfffb1c00, .irq=INT_1610_GPTIMER2 }, - { .base=0xfffb2400, .irq=INT_1610_GPTIMER3 }, - { .base=0xfffb2c00, .irq=INT_1610_GPTIMER4 }, - { .base=0xfffb3400, .irq=INT_1610_GPTIMER5 }, - { .base=0xfffb3c00, .irq=INT_1610_GPTIMER6 }, - { .base=0xfffb4400, .irq=INT_1610_GPTIMER7 }, - { .base=0xfffb4c00, .irq=INT_1610_GPTIMER8 }, - { .base=0x0 }, + { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, + { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 }, + { .phys_base = 0xfffb2400, .irq = INT_1610_GPTIMER3 }, + { .phys_base = 0xfffb2c00, .irq = INT_1610_GPTIMER4 }, + { .phys_base = 0xfffb3400, .irq = INT_1610_GPTIMER5 }, + { .phys_base = 0xfffb3c00, .irq = INT_1610_GPTIMER6 }, + { .phys_base = 0xfffb4400, .irq = INT_1610_GPTIMER7 }, + { .phys_base = 0xfffb4c00, .irq = INT_1610_GPTIMER8 }, }; +#elif defined(CONFIG_ARCH_OMAP2) + +static struct omap_dm_timer dm_timers[] = { + { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, + { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, + { .phys_base = 0x48078000, .irq = INT_24XX_GPTIMER3 }, + { .phys_base = 0x4807a000, .irq = INT_24XX_GPTIMER4 }, + { .phys_base = 0x4807c000, .irq = INT_24XX_GPTIMER5 }, + { .phys_base = 0x4807e000, .irq = INT_24XX_GPTIMER6 }, + { .phys_base = 0x48080000, .irq = INT_24XX_GPTIMER7 }, + { .phys_base = 0x48082000, .irq = INT_24XX_GPTIMER8 }, + { .phys_base = 0x48084000, .irq = INT_24XX_GPTIMER9 }, + { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 }, + { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 }, + { .phys_base = 0x4808a000, .irq = INT_24XX_GPTIMER12 }, +}; + +static const char *dm_source_names[] = { + "sys_ck", + "func_32k_ck", + "alt_ck" +}; +static struct clk *dm_source_clocks[3]; + +#else + +#error OMAP architecture not supported! + +#endif + +static const int dm_timer_count = ARRAY_SIZE(dm_timers); static spinlock_t dm_timer_lock; +static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) +{ + return readl(timer->io_base + reg); +} -inline void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value) +static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value) { - omap_writel(value, timer->base + reg); + writel(value, timer->io_base + reg); while (omap_dm_timer_read_reg(timer, OMAP_TIMER_WRITE_PEND_REG)) ; } -u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg) +static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) { - return omap_readl(timer->base + reg); + int c; + + c = 0; + while (!(omap_dm_timer_read_reg(timer, OMAP_TIMER_SYS_STAT_REG) & 1)) { + c++; + if (c > 100000) { + printk(KERN_ERR "Timer failed to reset\n"); + return; + } + } } -int omap_dm_timers_active(void) +static void omap_dm_timer_reset(struct omap_dm_timer *timer) +{ + u32 l; + + if (timer != &dm_timers[0]) { + omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); + omap_dm_timer_wait_for_reset(timer); + } + omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK); + + /* Set to smart-idle mode */ + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG); + l |= 0x02 << 3; + omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); +} + +static void omap_dm_timer_prepare(struct omap_dm_timer *timer) +{ +#ifdef CONFIG_ARCH_OMAP2 + clk_enable(timer->iclk); + clk_enable(timer->fclk); +#endif + omap_dm_timer_reset(timer); +} + +struct omap_dm_timer *omap_dm_timer_request(void) +{ + struct omap_dm_timer *timer = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&dm_timer_lock, flags); + for (i = 0; i < dm_timer_count; i++) { + if (dm_timers[i].reserved) + continue; + + timer = &dm_timers[i]; + timer->reserved = 1; + break; + } + spin_unlock_irqrestore(&dm_timer_lock, flags); + + if (timer != NULL) + omap_dm_timer_prepare(timer); + + return timer; +} + +struct omap_dm_timer *omap_dm_timer_request_specific(int id) { struct omap_dm_timer *timer; + unsigned long flags; - for (timer = &dm_timers[0]; timer->base; ++timer) - if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & - OMAP_TIMER_CTRL_ST) - return 1; + spin_lock_irqsave(&dm_timer_lock, flags); + if (id <= 0 || id > dm_timer_count || dm_timers[id-1].reserved) { + spin_unlock_irqrestore(&dm_timer_lock, flags); + printk("BUG: warning at %s:%d/%s(): unable to get timer %d\n", + __FILE__, __LINE__, __FUNCTION__, id); + dump_stack(); + return NULL; + } - return 0; + timer = &dm_timers[id-1]; + timer->reserved = 1; + spin_unlock_irqrestore(&dm_timer_lock, flags); + + omap_dm_timer_prepare(timer); + + return timer; } +void omap_dm_timer_free(struct omap_dm_timer *timer) +{ + omap_dm_timer_reset(timer); +#ifdef CONFIG_ARCH_OMAP2 + clk_disable(timer->iclk); + clk_disable(timer->fclk); +#endif + WARN_ON(!timer->reserved); + timer->reserved = 0; +} + +int omap_dm_timer_get_irq(struct omap_dm_timer *timer) +{ + return timer->irq; +} + +#if defined(CONFIG_ARCH_OMAP1) + +struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) +{ + BUG(); +} /** * omap_dm_timer_modify_idlect_mask - Check if any running timers use ARMXOR @@ -103,184 +250,229 @@ int omap_dm_timers_active(void) */ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) { - int n; + int i; /* If ARMXOR cannot be idled this function call is unnecessary */ if (!(inputmask & (1 << 1))) return inputmask; /* If any active timer is using ARMXOR return modified mask */ - for (n = 0; dm_timers[n].base; ++n) - if (omap_dm_timer_read_reg(&dm_timers[n], OMAP_TIMER_CTRL_REG)& - OMAP_TIMER_CTRL_ST) { - if (((omap_readl(MOD_CONF_CTRL_1)>>(n*2)) & 0x03) == 0) + for (i = 0; i < dm_timer_count; i++) { + u32 l; + + l = omap_dm_timer_read_reg(&dm_timers[i], OMAP_TIMER_CTRL_REG); + if (l & OMAP_TIMER_CTRL_ST) { + if (((omap_readl(MOD_CONF_CTRL_1) >> (i * 2)) & 0x03) == 0) inputmask &= ~(1 << 1); else inputmask &= ~(1 << 2); } + } return inputmask; } +#elif defined(CONFIG_ARCH_OMAP2) -void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) +struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) { - int n = (timer - dm_timers) << 1; - u32 l; + return timer->fclk; +} - l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); - l |= source << n; - omap_writel(l, MOD_CONF_CTRL_1); +__u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) +{ + BUG(); } +#endif -static void omap_dm_timer_reset(struct omap_dm_timer *timer) +void omap_dm_timer_trigger(struct omap_dm_timer *timer) { - /* Reset and set posted mode */ - omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); - omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, 0x02); - - omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_ARMXOR); + omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); } +void omap_dm_timer_start(struct omap_dm_timer *timer) +{ + u32 l; + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + if (!(l & OMAP_TIMER_CTRL_ST)) { + l |= OMAP_TIMER_CTRL_ST; + omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + } +} -struct omap_dm_timer * omap_dm_timer_request(void) +void omap_dm_timer_stop(struct omap_dm_timer *timer) { - struct omap_dm_timer *timer = NULL; - unsigned long flags; + u32 l; - spin_lock_irqsave(&dm_timer_lock, flags); - if (!list_empty(&dm_timer_info.unused_timers)) { - timer = (struct omap_dm_timer *) - dm_timer_info.unused_timers.next; - list_move_tail((struct list_head *)timer, - &dm_timer_info.reserved_timers); + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); + if (l & OMAP_TIMER_CTRL_ST) { + l &= ~0x1; + omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } - spin_unlock_irqrestore(&dm_timer_lock, flags); - - return timer; } +#ifdef CONFIG_ARCH_OMAP1 -void omap_dm_timer_free(struct omap_dm_timer *timer) +void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) { - unsigned long flags; - - omap_dm_timer_reset(timer); + int n = (timer - dm_timers) << 1; + u32 l; - spin_lock_irqsave(&dm_timer_lock, flags); - list_move_tail((struct list_head *)timer, &dm_timer_info.unused_timers); - spin_unlock_irqrestore(&dm_timer_lock, flags); + l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); + l |= source << n; + omap_writel(l, MOD_CONF_CTRL_1); } -void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, - unsigned int value) -{ - omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); -} +#else -unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) +void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) { - return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); -} + if (source < 0 || source >= 3) + return; -void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) -{ - omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); + clk_disable(timer->fclk); + clk_set_parent(timer->fclk, dm_source_clocks[source]); + clk_enable(timer->fclk); + + /* When the functional clock disappears, too quick writes seem to + * cause an abort. */ + __delay(15000); } -void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer) +#endif + +void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, + unsigned int load) { u32 l; + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); - l |= OMAP_TIMER_CTRL_AR; + if (autoreload) + l |= OMAP_TIMER_CTRL_AR; + else + l &= ~OMAP_TIMER_CTRL_AR; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); + omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); } -void omap_dm_timer_trigger(struct omap_dm_timer *timer) -{ - omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 1); -} - -void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value) +void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, + unsigned int match) { u32 l; l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); - l |= value & 0x3; + if (enable) + l |= OMAP_TIMER_CTRL_CE; + else + l &= ~OMAP_TIMER_CTRL_CE; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); } -void omap_dm_timer_start(struct omap_dm_timer *timer) + +void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, + int toggle, int trigger) { u32 l; l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); - l |= OMAP_TIMER_CTRL_ST; + l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | + OMAP_TIMER_CTRL_PT | (0x03 << 10)); + if (def_on) + l |= OMAP_TIMER_CTRL_SCPWM; + if (toggle) + l |= OMAP_TIMER_CTRL_PT; + l |= trigger << 10; omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } -void omap_dm_timer_stop(struct omap_dm_timer *timer) +void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) { u32 l; l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); - l &= ~0x1; + l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); + if (prescaler >= 0x00 && prescaler <= 0x07) { + l |= OMAP_TIMER_CTRL_PRE; + l |= prescaler << 2; + } omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); } -unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) +void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, + unsigned int value) { - return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); + omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); } -void omap_dm_timer_reset_counter(struct omap_dm_timer *timer) +unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) { - omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, 0); + return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); } -void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load) +void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) { - omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); + omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value); } -void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match) +unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) { - omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); + return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); } -void omap_dm_timer_enable_compare(struct omap_dm_timer *timer) +void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) { - u32 l; - - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); - l |= OMAP_TIMER_CTRL_CE; - omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); + return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); } +int omap_dm_timers_active(void) +{ + int i; + + for (i = 0; i < dm_timer_count; i++) { + struct omap_dm_timer *timer; + + timer = &dm_timers[i]; + if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & + OMAP_TIMER_CTRL_ST) + return 1; + } + return 0; +} -static inline void __dm_timer_init(void) +int omap_dm_timer_init(void) { struct omap_dm_timer *timer; + int i; + + if (!(cpu_is_omap16xx() || cpu_is_omap24xx())) + return -ENODEV; spin_lock_init(&dm_timer_lock); - INIT_LIST_HEAD(&dm_timer_info.unused_timers); - INIT_LIST_HEAD(&dm_timer_info.reserved_timers); - - timer = &dm_timers[0]; - while (timer->base) { - list_add_tail((struct list_head *)timer, &dm_timer_info.unused_timers); - omap_dm_timer_reset(timer); - timer++; +#ifdef CONFIG_ARCH_OMAP2 + for (i = 0; i < ARRAY_SIZE(dm_source_names); i++) { + dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]); + BUG_ON(dm_source_clocks[i] == NULL); + } +#endif + + for (i = 0; i < dm_timer_count; i++) { +#ifdef CONFIG_ARCH_OMAP2 + char clk_name[16]; +#endif + + timer = &dm_timers[i]; + timer->io_base = (void __iomem *) io_p2v(timer->phys_base); +#ifdef CONFIG_ARCH_OMAP2 + sprintf(clk_name, "gpt%d_ick", i + 1); + timer->iclk = clk_get(NULL, clk_name); + sprintf(clk_name, "gpt%d_fck", i + 1); + timer->fclk = clk_get(NULL, clk_name); +#endif } -} -static int __init omap_dm_timer_init(void) -{ - if (cpu_is_omap16xx()) - __dm_timer_init(); return 0; } - -arch_initcall(omap_dm_timer_init); diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 418b88fbea8..fec7970e564 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -536,6 +536,49 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); } +static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) +{ + void __iomem *reg = bank->base; + int inv = 0; + u32 l; + u32 mask; + + switch (bank->method) { + case METHOD_MPUIO: + reg += OMAP_MPUIO_GPIO_MASKIT; + mask = 0xffff; + inv = 1; + break; + case METHOD_GPIO_1510: + reg += OMAP1510_GPIO_INT_MASK; + mask = 0xffff; + inv = 1; + break; + case METHOD_GPIO_1610: + reg += OMAP1610_GPIO_IRQENABLE1; + mask = 0xffff; + break; + case METHOD_GPIO_730: + reg += OMAP730_GPIO_INT_MASK; + mask = 0xffffffff; + inv = 1; + break; + case METHOD_GPIO_24XX: + reg += OMAP24XX_GPIO_IRQENABLE1; + mask = 0xffffffff; + break; + default: + BUG(); + return 0; + } + + l = __raw_readl(reg); + if (inv) + l = ~l; + l &= mask; + return l; +} + static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) { void __iomem *reg = bank->base; @@ -735,10 +778,12 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, u32 isr; unsigned int gpio_irq; struct gpio_bank *bank; + u32 retrigger = 0; + int unmasked = 0; desc->chip->ack(irq); - bank = (struct gpio_bank *) desc->data; + bank = get_irq_data(irq); if (bank->method == METHOD_MPUIO) isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; #ifdef CONFIG_ARCH_OMAP15XX @@ -759,18 +804,22 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, #endif while(1) { u32 isr_saved, level_mask = 0; + u32 enabled; - isr_saved = isr = __raw_readl(isr_reg); + enabled = _get_gpio_irqbank_mask(bank); + isr_saved = isr = __raw_readl(isr_reg) & enabled; if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) isr &= 0x0000ffff; - if (cpu_is_omap24xx()) + if (cpu_is_omap24xx()) { level_mask = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) | __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); + level_mask &= enabled; + } /* clear edge sensitive interrupts before handler(s) are called so that we don't miss any interrupt occurred while @@ -781,19 +830,55 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, /* if there is only edge sensitive GPIO pin interrupts configured, we could unmask GPIO bank interrupt immediately */ - if (!level_mask) + if (!level_mask && !unmasked) { + unmasked = 1; desc->chip->unmask(irq); + } + isr |= retrigger; + retrigger = 0; if (!isr) break; gpio_irq = bank->virtual_irq_start; for (; isr != 0; isr >>= 1, gpio_irq++) { struct irqdesc *d; + int irq_mask; if (!(isr & 1)) continue; d = irq_desc + gpio_irq; + /* Don't run the handler if it's already running + * or was disabled lazely. + */ + if (unlikely((d->depth || + (d->status & IRQ_INPROGRESS)))) { + irq_mask = 1 << + (gpio_irq - bank->virtual_irq_start); + /* The unmasking will be done by + * enable_irq in case it is disabled or + * after returning from the handler if + * it's already running. + */ + _enable_gpio_irqbank(bank, irq_mask, 0); + if (!d->depth) { + /* Level triggered interrupts + * won't ever be reentered + */ + BUG_ON(level_mask & irq_mask); + d->status |= IRQ_PENDING; + } + continue; + } + desc_handle_irq(gpio_irq, d, regs); + + if (unlikely((d->status & IRQ_PENDING) && !d->depth)) { + irq_mask = 1 << + (gpio_irq - bank->virtual_irq_start); + d->status &= ~IRQ_PENDING; + _enable_gpio_irqbank(bank, irq_mask, 1); + retrigger |= irq_mask; + } } if (cpu_is_omap24xx()) { @@ -803,13 +888,14 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, _enable_gpio_irqbank(bank, isr_saved & level_mask, 1); } - /* if bank has any level sensitive GPIO pin interrupt - configured, we must unmask the bank interrupt only after - handler(s) are executed in order to avoid spurious bank - interrupt */ - if (level_mask) - desc->chip->unmask(irq); } + /* if bank has any level sensitive GPIO pin interrupt + configured, we must unmask the bank interrupt only after + handler(s) are executed in order to avoid spurious bank + interrupt */ + if (!unmasked) + desc->chip->unmask(irq); + } static void gpio_ack_irq(unsigned int irq) diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c index 1a24e2c1071..04b4102727a 100644 --- a/arch/arm/plat-omap/pm.c +++ b/arch/arm/plat-omap/pm.c @@ -580,7 +580,7 @@ static irqreturn_t omap_wakeup_interrupt(int irq, void * dev, static struct irqaction omap_wakeup_irq = { .name = "peripheral wakeup", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .handler = omap_wakeup_interrupt }; diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 72ce52ce815..e75718301b0 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -157,14 +157,12 @@ static struct map_desc omap_sram_io_desc[] __initdata = { { /* .length gets filled in at runtime */ .virtual = OMAP1_SRAM_VA, .pfn = __phys_to_pfn(OMAP1_SRAM_PA), - .type = MT_DEVICE + .type = MT_MEMORY } }; /* - * In order to use last 2kB of SRAM on 1611b, we must round the size - * up to multiple of PAGE_SIZE. We cannot use ioremap for SRAM, as - * clock init needs SRAM early. + * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early. */ void __init omap_map_sram(void) { @@ -184,8 +182,7 @@ void __init omap_map_sram(void) omap_sram_io_desc[0].pfn = __phys_to_pfn(base); } - omap_sram_io_desc[0].length = (omap_sram_size + PAGE_SIZE-1)/PAGE_SIZE; - omap_sram_io_desc[0].length *= PAGE_SIZE; + omap_sram_io_desc[0].length = 1024 * 1024; /* Use section desc */ iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); printk(KERN_INFO "SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx\n", diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c index 053c18132ef..281ecc7fcdf 100644 --- a/arch/arm/plat-omap/timer32k.c +++ b/arch/arm/plat-omap/timer32k.c @@ -7,6 +7,7 @@ * Partial timer rewrite and additional dynamic tick timer support by * Tony Lindgen <tony@atomide.com> and * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> + * OMAP Dual-mode timer framework support by Timo Teras * * MPU timer code based on the older MPU timer code for OMAP * Copyright (C) 2000 RidgeRun, Inc. @@ -49,6 +50,7 @@ #include <asm/irq.h> #include <asm/mach/irq.h> #include <asm/mach/time.h> +#include <asm/arch/dmtimer.h> struct sys_timer omap_timer; @@ -78,18 +80,6 @@ struct sys_timer omap_timer; #define OMAP1_32K_TIMER_TVR 0x00 #define OMAP1_32K_TIMER_TCR 0x04 -/* 24xx specific defines */ -#define OMAP2_GP_TIMER_BASE 0x48028000 -#define CM_CLKSEL_WKUP 0x48008440 -#define GP_TIMER_TIDR 0x00 -#define GP_TIMER_TISR 0x18 -#define GP_TIMER_TIER 0x1c -#define GP_TIMER_TCLR 0x24 -#define GP_TIMER_TCRR 0x28 -#define GP_TIMER_TLDR 0x2c -#define GP_TIMER_TTGR 0x30 -#define GP_TIMER_TSICR 0x40 - #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) /* @@ -101,54 +91,62 @@ struct sys_timer omap_timer; #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \ (((nr_jiffies) * (clock_rate)) / HZ) +#if defined(CONFIG_ARCH_OMAP1) + static inline void omap_32k_timer_write(int val, int reg) { - if (cpu_class_is_omap1()) - omap_writew(val, OMAP1_32K_TIMER_BASE + reg); - - if (cpu_is_omap24xx()) - omap_writel(val, OMAP2_GP_TIMER_BASE + reg); + omap_writew(val, OMAP1_32K_TIMER_BASE + reg); } static inline unsigned long omap_32k_timer_read(int reg) { - if (cpu_class_is_omap1()) - return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; + return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; +} - if (cpu_is_omap24xx()) - return omap_readl(OMAP2_GP_TIMER_BASE + reg); +static inline void omap_32k_timer_start(unsigned long load_val) +{ + omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); + omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); } -/* - * The 32KHz synchronized timer is an additional timer on 16xx. - * It is always running. - */ -static inline unsigned long omap_32k_sync_timer_read(void) +static inline void omap_32k_timer_stop(void) { - return omap_readl(TIMER_32K_SYNCHRONIZED); + omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR); } +#define omap_32k_timer_ack_irq() + +#elif defined(CONFIG_ARCH_OMAP2) + +static struct omap_dm_timer *gptimer; + static inline void omap_32k_timer_start(unsigned long load_val) { - if (cpu_class_is_omap1()) { - omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); - omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); - } - - if (cpu_is_omap24xx()) { - omap_32k_timer_write(0xffffffff - load_val, GP_TIMER_TCRR); - omap_32k_timer_write((1 << 1), GP_TIMER_TIER); - omap_32k_timer_write((1 << 1) | 1, GP_TIMER_TCLR); - } + omap_dm_timer_set_load(gptimer, 1, 0xffffffff - load_val); + omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); + omap_dm_timer_start(gptimer); } static inline void omap_32k_timer_stop(void) { - if (cpu_class_is_omap1()) - omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR); + omap_dm_timer_stop(gptimer); +} - if (cpu_is_omap24xx()) - omap_32k_timer_write(0x0, GP_TIMER_TCLR); +static inline void omap_32k_timer_ack_irq(void) +{ + u32 status = omap_dm_timer_read_status(gptimer); + omap_dm_timer_write_status(gptimer, status); +} + +#endif + +/* + * The 32KHz synchronized timer is an additional timer on 16xx. + * It is always running. + */ +static inline unsigned long omap_32k_sync_timer_read(void) +{ + return omap_readl(TIMER_32K_SYNCHRONIZED); } /* @@ -202,11 +200,7 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, write_seqlock_irqsave(&xtime_lock, flags); - if (cpu_is_omap24xx()) { - u32 status = omap_32k_timer_read(GP_TIMER_TISR); - omap_32k_timer_write(status, GP_TIMER_TISR); - } - + omap_32k_timer_ack_irq(); now = omap_32k_sync_timer_read(); while ((signed long)(now - omap_32k_last_tick) @@ -264,13 +258,10 @@ static struct dyn_tick_timer omap_dyn_tick_timer = { static struct irqaction omap_32k_timer_irq = { .name = "32KHz timer", - .flags = SA_INTERRUPT | SA_TIMER, + .flags = IRQF_DISABLED | IRQF_TIMER, .handler = omap_32k_timer_interrupt, }; -static struct clk * gpt1_ick; -static struct clk * gpt1_fck; - static __init void omap_init_32k_timer(void) { #ifdef CONFIG_NO_IDLE_HZ @@ -279,32 +270,22 @@ static __init void omap_init_32k_timer(void) if (cpu_class_is_omap1()) setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); - if (cpu_is_omap24xx()) - setup_irq(37, &omap_32k_timer_irq); omap_timer.offset = omap_32k_timer_gettimeoffset; omap_32k_last_tick = omap_32k_sync_timer_read(); +#ifdef CONFIG_ARCH_OMAP2 /* REVISIT: Check 24xx TIOCP_CFG settings after idle works */ if (cpu_is_omap24xx()) { - omap_32k_timer_write(0, GP_TIMER_TCLR); - omap_writel(0, CM_CLKSEL_WKUP); /* 32KHz clock source */ - - gpt1_ick = clk_get(NULL, "gpt1_ick"); - if (IS_ERR(gpt1_ick)) - printk(KERN_ERR "Could not get gpt1_ick\n"); - else - clk_enable(gpt1_ick); - - gpt1_fck = clk_get(NULL, "gpt1_fck"); - if (IS_ERR(gpt1_fck)) - printk(KERN_ERR "Could not get gpt1_fck\n"); - else - clk_enable(gpt1_fck); - - mdelay(100); /* Wait for clocks to stabilize */ - - omap_32k_timer_write(0x7, GP_TIMER_TISR); + gptimer = omap_dm_timer_request_specific(1); + BUG_ON(gptimer == NULL); + + omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ); + setup_irq(omap_dm_timer_get_irq(gptimer), &omap_32k_timer_irq); + omap_dm_timer_set_int_enable(gptimer, + OMAP_TIMER_INT_CAPTURE | OMAP_TIMER_INT_OVERFLOW | + OMAP_TIMER_INT_MATCH); } +#endif omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); } @@ -316,6 +297,9 @@ static __init void omap_init_32k_timer(void) */ static void __init omap_timer_init(void) { +#ifdef CONFIG_OMAP_DM_TIMER + omap_dm_timer_init(); +#endif omap_init_32k_timer(); } diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c index e08ba2955ec..d87d68b77d6 100644 --- a/arch/arm26/kernel/irq.c +++ b/arch/arm26/kernel/irq.c @@ -190,7 +190,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) int ret; spin_unlock(&irq_controller_lock); - if (!(action->flags & SA_INTERRUPT)) + if (!(action->flags & IRQF_DISABLED)) local_irq_enable(); status = 0; @@ -201,7 +201,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) action = action->next; } while (action); - if (status & SA_SAMPLE_RANDOM) + if (status & IRQF_SAMPLE_RANDOM) add_interrupt_randomness(irq); spin_lock_irq(&irq_controller_lock); @@ -451,7 +451,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) * so we have to be careful not to interfere with a * running system. */ - if (new->flags & SA_SAMPLE_RANDOM) { + if (new->flags & IRQF_SAMPLE_RANDOM) { /* * This function might sleep, we want to call it first, * outside of the atomic block. @@ -471,7 +471,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) p = &desc->action; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { + if (!(old->flags & new->flags & IRQF_SHARED)) { spin_unlock_irqrestore(&irq_controller_lock, flags); return -EBUSY; } @@ -526,11 +526,11 @@ int setup_irq(unsigned int irq, struct irqaction *new) * * Flags: * - * SA_SHIRQ Interrupt is shared + * IRQF_SHARED Interrupt is shared * - * SA_INTERRUPT Disable local interrupts while processing + * IRQF_DISABLED Disable local interrupts while processing * - * SA_SAMPLE_RANDOM The interrupt can be used for entropy + * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy * */ @@ -542,7 +542,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_ struct irqaction *action; if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler || - (irq_flags & SA_SHIRQ && !dev_id)) + (irq_flags & IRQF_SHARED && !dev_id)) return -EINVAL; action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c index 718de9bed95..db63d75d071 100644 --- a/arch/arm26/kernel/time.c +++ b/arch/arm26/kernel/time.c @@ -205,7 +205,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction timer_irq = { .name = "timer", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .handler = timer_interrupt, }; diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c index 25df4ada951..48fd801792d 100644 --- a/arch/cris/arch-v10/drivers/gpio.c +++ b/arch/cris/arch-v10/drivers/gpio.c @@ -937,11 +937,11 @@ gpio_init(void) * in some tests. */ if (request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt, - SA_SHIRQ | SA_INTERRUPT,"gpio poll", NULL)) { + IRQF_SHARED | IRQF_DISABLED,"gpio poll", NULL)) { printk(KERN_CRIT "err: timer0 irq for gpio\n"); } if (request_irq(PA_IRQ_NBR, gpio_pa_interrupt, - SA_SHIRQ | SA_INTERRUPT,"gpio PA", NULL)) { + IRQF_SHARED | IRQF_DISABLED,"gpio PA", NULL)) { printk(KERN_CRIT "err: PA irq for gpio\n"); } diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c index fe65cb89f54..9c22b76e129 100644 --- a/arch/cris/arch-v10/kernel/time.c +++ b/arch/cris/arch-v10/kernel/time.c @@ -251,11 +251,11 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -/* timer is SA_SHIRQ so drivers can add stuff to the timer irq chain - * it needs to be SA_INTERRUPT to make the jiffies update work properly +/* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain + * it needs to be IRQF_DISABLED to make the jiffies update work properly */ -static struct irqaction irq2 = { timer_interrupt, SA_SHIRQ | SA_INTERRUPT, +static struct irqaction irq2 = { timer_interrupt, IRQF_SHARED | IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL}; void __init diff --git a/arch/cris/arch-v32/drivers/gpio.c b/arch/cris/arch-v32/drivers/gpio.c index 113bdff4fd3..00e9167de53 100644 --- a/arch/cris/arch-v32/drivers/gpio.c +++ b/arch/cris/arch-v32/drivers/gpio.c @@ -744,11 +744,11 @@ gpio_init(void) * in some tests. */ if (request_irq(TIMER_INTR_VECT, gpio_poll_timer_interrupt, - SA_SHIRQ | SA_INTERRUPT,"gpio poll", &alarmlist)) { + IRQF_SHARED | IRQF_DISABLED,"gpio poll", &alarmlist)) { printk("err: timer0 irq for gpio\n"); } if (request_irq(GEN_IO_INTR_VECT, gpio_pa_interrupt, - SA_SHIRQ | SA_INTERRUPT,"gpio PA", &alarmlist)) { + IRQF_SHARED | IRQF_DISABLED,"gpio PA", &alarmlist)) { printk("err: PA irq for gpio\n"); } /* enable the gio and timer irq in global config */ diff --git a/arch/cris/arch-v32/kernel/arbiter.c b/arch/cris/arch-v32/kernel/arbiter.c index 82d44c9afc1..420a5312ed0 100644 --- a/arch/cris/arch-v32/kernel/arbiter.c +++ b/arch/cris/arch-v32/kernel/arbiter.c @@ -119,7 +119,7 @@ static void crisv32_arbiter_init(void) crisv32_arbiter_config(EXT_REGION); crisv32_arbiter_config(INT_REGION); - if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, SA_INTERRUPT, + if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, IRQF_DISABLED, "arbiter", NULL)) printk(KERN_ERR "Couldn't allocate arbiter IRQ\n"); diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c index caaa86bd5e8..5daeb6f7f3b 100644 --- a/arch/cris/arch-v32/kernel/fasttimer.c +++ b/arch/cris/arch-v32/kernel/fasttimer.c @@ -981,7 +981,7 @@ void fast_timer_init(void) proc_register_dynamic(&proc_root, &fasttimer_proc_entry); #endif #endif /* PROC_FS */ - if(request_irq(TIMER_INTR_VECT, timer_trig_interrupt, SA_INTERRUPT, + if(request_irq(TIMER_INTR_VECT, timer_trig_interrupt, IRQF_DISABLED, "fast timer int", NULL)) { printk("err: timer1 irq\n"); diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c index e2d2b3fdb5b..cc361bf578a 100644 --- a/arch/cris/arch-v32/kernel/irq.c +++ b/arch/cris/arch-v32/kernel/irq.c @@ -268,7 +268,7 @@ void crisv32_do_IRQ(int irq, int block, struct pt_regs* regs) { /* Interrupts that may not be moved to another CPU and - * are SA_INTERRUPT may skip blocking. This is currently + * are IRQF_DISABLED may skip blocking. This is currently * only valid for the timer IRQ and the IPI and is used * for the timer interrupt to avoid watchdog starvation. */ diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index da40d19a151..464ecaec3bc 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -62,7 +62,7 @@ static unsigned long irq_regs[NR_CPUS] = static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs); static int send_ipi(int vector, int wait, cpumask_t cpu_mask); -static struct irqaction irq_ipi = { crisv32_ipi_interrupt, SA_INTERRUPT, +static struct irqaction irq_ipi = { crisv32_ipi_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "ipi", NULL, NULL}; extern void cris_mmu_init(void); diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c index 4bac1d6c37f..50f3f93293d 100644 --- a/arch/cris/arch-v32/kernel/time.c +++ b/arch/cris/arch-v32/kernel/time.c @@ -241,12 +241,16 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -/* timer is SA_SHIRQ so drivers can add stuff to the timer irq chain - * it needs to be SA_INTERRUPT to make the jiffies update work properly +/* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain + * it needs to be IRQF_DISABLED to make the jiffies update work properly */ -static struct irqaction irq_timer = { timer_interrupt, SA_SHIRQ | SA_INTERRUPT, - CPU_MASK_NONE, "timer", NULL, NULL}; +static struct irqaction irq_timer = { + .mask = timer_interrupt, + .flags = IRQF_SHARED | IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "timer" +}; void __init cris_timer_init(void) diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c index 1f9099627a7..903ea62c6e2 100644 --- a/arch/cris/kernel/irq.c +++ b/arch/cris/kernel/irq.c @@ -85,7 +85,7 @@ skip: /* called by the assembler IRQ entry functions defined in irq.h * to dispatch the interrupts to registred handlers * interrupts are disabled upon entry - depending on if the - * interrupt was registred with SA_INTERRUPT or not, interrupts + * interrupt was registred with IRQF_DISABLED or not, interrupts * are re-enabled or not. */ diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c index b90b70a761d..53886adf47d 100644 --- a/arch/frv/kernel/irq-routing.c +++ b/arch/frv/kernel/irq-routing.c @@ -81,7 +81,7 @@ void distribute_irqs(struct irq_group *group, unsigned long irqmask) if (action) { int status = 0; -// if (!(action->flags & SA_INTERRUPT)) +// if (!(action->flags & IRQF_DISABLED)) // local_irq_enable(); do { @@ -90,7 +90,7 @@ void distribute_irqs(struct irq_group *group, unsigned long irqmask) action = action->next; } while (action); - if (status & SA_SAMPLE_RANDOM) + if (status & IRQF_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); } diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 5920f52bf9c..08967010be0 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -341,11 +341,11 @@ asmlinkage void do_NMI(void) * * Flags: * - * SA_SHIRQ Interrupt is shared + * IRQF_SHARED Interrupt is shared * - * SA_INTERRUPT Disable local interrupts while processing + * IRQF_DISABLED Disable local interrupts while processing * - * SA_SAMPLE_RANDOM The interrupt can be used for entropy + * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy * */ @@ -365,7 +365,7 @@ int request_irq(unsigned int irq, * to figure out which interrupt is which (messes up the * interrupt freeing logic etc). */ - if (irqflags & SA_SHIRQ) { + if (irqflags & IRQF_SHARED) { if (!dev_id) printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); @@ -576,7 +576,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) * so we have to be careful not to interfere with a * running system. */ - if (new->flags & SA_SAMPLE_RANDOM) { + if (new->flags & IRQF_SAMPLE_RANDOM) { /* * This function might sleep, we want to call it first, * outside of the atomic block. @@ -592,7 +592,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) spin_lock_irqsave(&level->lock, flags); /* can't share interrupts unless all parties agree to */ - if (level->usage != 0 && !(level->flags & new->flags & SA_SHIRQ)) { + if (level->usage != 0 && !(level->flags & new->flags & IRQF_SHARED)) { spin_unlock_irqrestore(&level->lock,flags); return -EBUSY; } diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 5db3d4eff90..af08ccd4ed6 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/delay.h> diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c index 24cf85f89e4..d5b64e193d9 100644 --- a/arch/frv/kernel/time.c +++ b/arch/frv/kernel/time.c @@ -47,7 +47,7 @@ unsigned long __delay_loops_MHz; static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs *regs); static struct irqaction timer_irq = { - timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL + timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL }; static inline int set_rtc_mmss(unsigned long nowtime) diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c index edb3c417001..1488b6ace18 100644 --- a/arch/h8300/kernel/ints.c +++ b/arch/h8300/kernel/ints.c @@ -158,7 +158,7 @@ int request_irq(unsigned int irq, irq_handle->devname = devname; irq_list[irq] = irq_handle; - if (irq_handle->flags & SA_SAMPLE_RANDOM) + if (irq_handle->flags & IRQF_SAMPLE_RANDOM) rand_initialize_irq(irq); enable_irq(irq); @@ -222,7 +222,7 @@ asmlinkage void process_int(int irq, struct pt_regs *fp) if (irq_list[irq]) { irq_list[irq]->handler(irq, irq_list[irq]->dev_id, fp); irq_list[irq]->count++; - if (irq_list[irq]->flags & SA_SAMPLE_RANDOM) + if (irq_list[irq]->flags & IRQF_SAMPLE_RANDOM) add_interrupt_randomness(irq); } } else { diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c index f6ed663bdde..270440de461 100644 --- a/arch/h8300/platform/h8s/ints.c +++ b/arch/h8300/platform/h8s/ints.c @@ -192,7 +192,7 @@ int request_irq(unsigned int irq, irq_handle->dev_id = dev_id; irq_handle->devname = devname; irq_list[irq] = irq_handle; - if (irq_handle->flags & SA_SAMPLE_RANDOM) + if (irq_handle->flags & IRQF_SAMPLE_RANDOM) rand_initialize_irq(irq); /* enable interrupt */ @@ -270,7 +270,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) if (irq_list[vec]) { irq_list[vec]->handler(vec, irq_list[vec]->dev_id, fp); irq_list[vec]->count++; - if (irq_list[vec]->flags & SA_SAMPLE_RANDOM) + if (irq_list[vec]->flags & IRQF_SAMPLE_RANDOM) add_interrupt_randomness(vec); } } else { diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 27d8dddbaa4..daa75ce4b77 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -18,6 +18,14 @@ config GENERIC_TIME bool default y +config LOCKDEP_SUPPORT + bool + default y + +config STACKTRACE_SUPPORT + bool + default y + config SEMAPHORE_SLEEPERS bool default y diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug index c92191b1fb6..b31c0802e1c 100644 --- a/arch/i386/Kconfig.debug +++ b/arch/i386/Kconfig.debug @@ -1,5 +1,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + source "lib/Kconfig.debug" config EARLY_PRINTK @@ -31,15 +35,6 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. -config STACK_BACKTRACE_COLS - int "Stack backtraces per line" if DEBUG_KERNEL - range 1 3 - default 2 - help - Selects how many stack backtrace entries per line to display. - - This can save screen space when displaying traces. - comment "Page alloc debug is incompatible with Software Suspend on i386" depends on DEBUG_KERNEL && SOFTWARE_SUSPEND diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index 0a5a3be6d69..d2b684cd620 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -47,7 +47,7 @@ */ #include <asm/segment.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/compile.h> #include <asm/boot.h> #include <asm/e820.h> diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index cbc1184e947..1b452a1665c 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -9,6 +9,7 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ pci-dma.o i386_ksyms.o i387.o bootflag.o \ quirks.o i8237.o topology.o alternative.o i8253.o tsc.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += cpu/ obj-y += acpi/ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 7b421b3a053..28ab8064976 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c @@ -303,6 +303,16 @@ void alternatives_smp_switch(int smp) struct smp_alt_module *mod; unsigned long flags; +#ifdef CONFIG_LOCKDEP + /* + * A not yet fixed binutils section handling bug prevents + * alternatives-replacement from working reliably, so turn + * it off: + */ + printk("lockdep: not fixing up alternatives.\n"); + return; +#endif + if (no_replacement || smp_alt_once) return; BUG_ON(!smp && (num_online_cpus() > 1)); diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c index a8d3ecdc389..fde8bea85ce 100644 --- a/arch/i386/kernel/cpuid.c +++ b/arch/i386/kernel/cpuid.c @@ -167,6 +167,7 @@ static int cpuid_class_device_create(int i) return err; } +#ifdef CONFIG_HOTPLUG_CPU static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -186,6 +187,7 @@ static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier = { .notifier_call = cpuid_class_cpu_callback, }; +#endif /* !CONFIG_HOTPLUG_CPU */ static int __init cpuid_init(void) { @@ -208,7 +210,7 @@ static int __init cpuid_init(void) if (err != 0) goto out_class; } - register_cpu_notifier(&cpuid_class_cpu_notifier); + register_hotcpu_notifier(&cpuid_class_cpu_notifier); err = 0; goto out; @@ -233,7 +235,7 @@ static void __exit cpuid_exit(void) class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); class_destroy(cpuid_class); unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); - unregister_cpu_notifier(&cpuid_class_cpu_notifier); + unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); } module_init(cpuid_init); diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 787190c45fd..d9a260f2efb 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -42,6 +42,7 @@ #include <linux/linkage.h> #include <asm/thread_info.h> +#include <asm/irqflags.h> #include <asm/errno.h> #include <asm/segment.h> #include <asm/smp.h> @@ -76,12 +77,21 @@ NT_MASK = 0x00004000 VM_MASK = 0x00020000 #ifdef CONFIG_PREEMPT -#define preempt_stop cli +#define preempt_stop cli; TRACE_IRQS_OFF #else #define preempt_stop #define resume_kernel restore_nocheck #endif +.macro TRACE_IRQS_IRET +#ifdef CONFIG_TRACE_IRQFLAGS + testl $IF_MASK,EFLAGS(%esp) # interrupts off? + jz 1f + TRACE_IRQS_ON +1: +#endif +.endm + #ifdef CONFIG_VM86 #define resume_userspace_sig check_userspace #else @@ -257,6 +267,10 @@ ENTRY(sysenter_entry) CFI_REGISTER esp, ebp movl TSS_sysenter_esp0(%esp),%esp sysenter_past_esp: + /* + * No need to follow this irqs on/off section: the syscall + * disabled irqs and here we enable it straight after entry: + */ sti pushl $(__USER_DS) CFI_ADJUST_CFA_OFFSET 4 @@ -303,6 +317,7 @@ sysenter_past_esp: call *sys_call_table(,%eax,4) movl %eax,EAX(%esp) cli + TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testw $_TIF_ALLWORK_MASK, %cx jne syscall_exit_work @@ -310,6 +325,7 @@ sysenter_past_esp: movl EIP(%esp), %edx movl OLDESP(%esp), %ecx xorl %ebp,%ebp + TRACE_IRQS_ON sti sysexit CFI_ENDPROC @@ -339,6 +355,7 @@ syscall_exit: cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret + TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testw $_TIF_ALLWORK_MASK, %cx # current->work jne syscall_exit_work @@ -355,12 +372,15 @@ restore_all: CFI_REMEMBER_STATE je ldt_ss # returning to user-space with LDT SS restore_nocheck: + TRACE_IRQS_IRET +restore_nocheck_notrace: RESTORE_REGS addl $4, %esp CFI_ADJUST_CFA_OFFSET -4 1: iret .section .fixup,"ax" iret_exc: + TRACE_IRQS_ON sti pushl $0 # no error code pushl $do_iret_error @@ -386,11 +406,13 @@ ldt_ss: subl $8, %esp # reserve space for switch16 pointer CFI_ADJUST_CFA_OFFSET 8 cli + TRACE_IRQS_OFF movl %esp, %eax /* Set up the 16bit stack frame with switch32 pointer on top, * and a switch16 pointer on top of the current frame. */ call setup_x86_bogus_stack CFI_ADJUST_CFA_OFFSET -8 # frame has moved + TRACE_IRQS_IRET RESTORE_REGS lss 20+4(%esp), %esp # switch to 16bit stack 1: iret @@ -411,6 +433,7 @@ work_resched: cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret + TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx andl $_TIF_WORK_MASK, %ecx # is there any work to be done other # than syscall tracing? @@ -462,6 +485,7 @@ syscall_trace_entry: syscall_exit_work: testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl jz work_pending + TRACE_IRQS_ON sti # could let do_syscall_trace() call # schedule() instead movl %esp, %eax @@ -535,9 +559,14 @@ ENTRY(irq_entries_start) vector=vector+1 .endr +/* + * the CPU automatically disables interrupts when executing an IRQ vector, + * so IRQ-flags tracing has to follow that: + */ ALIGN common_interrupt: SAVE_ALL + TRACE_IRQS_OFF movl %esp,%eax call do_IRQ jmp ret_from_intr @@ -549,9 +578,10 @@ ENTRY(name) \ pushl $~(nr); \ CFI_ADJUST_CFA_OFFSET 4; \ SAVE_ALL; \ + TRACE_IRQS_OFF \ movl %esp,%eax; \ call smp_/**/name; \ - jmp ret_from_intr; \ + jmp ret_from_intr; \ CFI_ENDPROC /* The include is where all of the SMP etc. interrupts come from */ @@ -726,7 +756,7 @@ nmi_stack_correct: xorl %edx,%edx # zero error code movl %esp,%eax # pt_regs pointer call do_nmi - jmp restore_all + jmp restore_nocheck_notrace CFI_ENDPROC nmi_stack_fixup: diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index 16b49170396..6cb529f60dc 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -166,7 +166,7 @@ void irq_ctx_init(int cpu) irqctx->tinfo.task = NULL; irqctx->tinfo.exec_domain = NULL; irqctx->tinfo.cpu = cpu; - irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; + irqctx->tinfo.preempt_count = 0; irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); softirq_ctx[cpu] = irqctx; @@ -211,6 +211,10 @@ asmlinkage void do_softirq(void) : "0"(isp) : "memory", "cc", "edx", "ecx", "eax" ); + /* + * Shouldnt happen, we returned above if in_interrupt(): + */ + WARN_ON_ONCE(softirq_count()); } local_irq_restore(flags); diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index a76e9314658..2dd928a8464 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -107,7 +107,7 @@ int nmi_active; static __init void nmi_cpu_busy(void *data) { volatile int *endflag = data; - local_irq_enable(); + local_irq_enable_in_hardirq(); /* Intentionally don't use cpu_relax here. This is to make sure that the performance counter really ticks, even if there is a simulator or similar that catches the diff --git a/arch/i386/kernel/stacktrace.c b/arch/i386/kernel/stacktrace.c new file mode 100644 index 00000000000..e62a037ab39 --- /dev/null +++ b/arch/i386/kernel/stacktrace.c @@ -0,0 +1,98 @@ +/* + * arch/i386/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> + +static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) +{ + return p > (void *)tinfo && + p < (void *)tinfo + THREAD_SIZE - 3; +} + +/* + * Save stack-backtrace addresses into a stack_trace buffer: + */ +static inline unsigned long +save_context_stack(struct stack_trace *trace, unsigned int skip, + struct thread_info *tinfo, unsigned long *stack, + unsigned long ebp) +{ + unsigned long addr; + +#ifdef CONFIG_FRAME_POINTER + while (valid_stack_ptr(tinfo, (void *)ebp)) { + addr = *(unsigned long *)(ebp + 4); + if (!skip) + trace->entries[trace->nr_entries++] = addr; + else + skip--; + if (trace->nr_entries >= trace->max_entries) + break; + /* + * break out of recursive entries (such as + * end_of_stack_stop_unwind_function): + */ + if (ebp == *(unsigned long *)ebp) + break; + + ebp = *(unsigned long *)ebp; + } +#else + while (valid_stack_ptr(tinfo, stack)) { + addr = *stack++; + if (__kernel_text_address(addr)) { + if (!skip) + trace->entries[trace->nr_entries++] = addr; + else + skip--; + if (trace->nr_entries >= trace->max_entries) + break; + } + } +#endif + + return ebp; +} + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + * If all_contexts is set, all contexts (hardirq, softirq and process) + * are saved. If not set then only the current context is saved. + */ +void save_stack_trace(struct stack_trace *trace, + struct task_struct *task, int all_contexts, + unsigned int skip) +{ + unsigned long ebp; + unsigned long *stack = &ebp; + + WARN_ON(trace->nr_entries || !trace->max_entries); + + if (!task || task == current) { + /* Grab ebp right from our regs: */ + asm ("movl %%ebp, %0" : "=r" (ebp)); + } else { + /* ebp is the last reg pushed by switch_to(): */ + ebp = *(unsigned long *) task->thread.esp; + } + + while (1) { + struct thread_info *context = (struct thread_info *) + ((unsigned long)stack & (~(THREAD_SIZE - 1))); + + ebp = save_context_stack(trace, skip, context, stack, ebp); + stack = (unsigned long *)context->previous_esp; + if (!all_contexts || !stack || + trace->nr_entries >= trace->max_entries) + break; + trace->entries[trace->nr_entries++] = ULONG_MAX; + if (trace->nr_entries >= trace->max_entries) + break; + } +} + diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index e8c6086b2aa..2bf8b55b91f 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -115,28 +115,13 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) } /* - * Print CONFIG_STACK_BACKTRACE_COLS address/symbol entries per line. + * Print one address/symbol entries per line. */ -static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl, - int printed) +static inline void print_addr_and_symbol(unsigned long addr, char *log_lvl) { - if (!printed) - printk(log_lvl); - -#if CONFIG_STACK_BACKTRACE_COLS == 1 printk(" [<%08lx>] ", addr); -#else - printk(" <%08lx> ", addr); -#endif - print_symbol("%s", addr); - printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS; - if (printed) - printk(" "); - else - printk("\n"); - - return printed; + print_symbol("%s\n", addr); } static inline unsigned long print_context_stack(struct thread_info *tinfo, @@ -144,12 +129,11 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, char *log_lvl) { unsigned long addr; - int printed = 0; /* nr of entries already printed on current line */ #ifdef CONFIG_FRAME_POINTER while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); - printed = print_addr_and_symbol(addr, log_lvl, printed); + print_addr_and_symbol(addr, log_lvl); /* * break out of recursive entries (such as * end_of_stack_stop_unwind_function): @@ -162,28 +146,23 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, while (valid_stack_ptr(tinfo, stack)) { addr = *stack++; if (__kernel_text_address(addr)) - printed = print_addr_and_symbol(addr, log_lvl, printed); + print_addr_and_symbol(addr, log_lvl); } #endif - if (printed) - printk("\n"); - return ebp; } -static asmlinkage int show_trace_unwind(struct unwind_frame_info *info, void *log_lvl) +static asmlinkage int +show_trace_unwind(struct unwind_frame_info *info, void *log_lvl) { int n = 0; - int printed = 0; /* nr of entries already printed on current line */ while (unwind(info) == 0 && UNW_PC(info)) { - ++n; - printed = print_addr_and_symbol(UNW_PC(info), log_lvl, printed); + n++; + print_addr_and_symbol(UNW_PC(info), log_lvl); if (arch_unw_user_mode(info)) break; } - if (printed) - printk("\n"); return n; } diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c index 77c8c83815c..c511705c386 100644 --- a/arch/i386/mach-default/setup.c +++ b/arch/i386/mach-default/setup.c @@ -79,7 +79,7 @@ void __init trap_init_hook(void) { } -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL}; +static struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL}; /** * time_init_hook - do any specific initialisations for the system timer. diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c index 1f84cdb2477..885c7cbfd47 100644 --- a/arch/i386/mach-visws/setup.c +++ b/arch/i386/mach-visws/setup.c @@ -115,7 +115,7 @@ void __init pre_setup_arch_hook() static struct irqaction irq0 = { .handler = timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "timer", }; diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c index 9da9ef09068..cfa16c151c8 100644 --- a/arch/i386/mach-voyager/setup.c +++ b/arch/i386/mach-voyager/setup.c @@ -40,7 +40,7 @@ void __init trap_init_hook(void) { } -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL}; +static struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL}; void __init time_init_hook(void) { diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index bdb4896c56e..4a8995c9c76 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -864,7 +864,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) for (i = 0; i < 16; i++) { if (!(mask & (1 << i))) continue; - if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, SA_SHIRQ)) + if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, IRQF_SHARED)) newirq = i; } } diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 33a3bbc8f67..0daacc20ed3 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c @@ -46,7 +46,7 @@ #define NR_PORTS 1 /* only one port for now */ -#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) +#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) #define SSC_GETCHAR 21 diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 3e6fcb056bc..a041367f043 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -235,7 +235,7 @@ extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs); static struct irqaction ipi_irqaction = { .handler = handle_IPI, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "IPI" }; #endif diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 584df177284..2fbe4536fe1 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -678,7 +678,7 @@ copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat) */ static void -ia64_mca_modify_comm(const task_t *previous_current) +ia64_mca_modify_comm(const struct task_struct *previous_current) { char *p, comm[sizeof(current->comm)]; if (previous_current->pid) @@ -709,7 +709,7 @@ ia64_mca_modify_comm(const task_t *previous_current) * that we can do backtrace on the MCA/INIT handler code itself. */ -static task_t * +static struct task_struct * ia64_mca_modify_original_stack(struct pt_regs *regs, const struct switch_stack *sw, struct ia64_sal_os_state *sos, @@ -719,7 +719,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, ia64_va va; extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */ const pal_min_state_area_t *ms = sos->pal_min_state; - task_t *previous_current; + struct task_struct *previous_current; struct pt_regs *old_regs; struct switch_stack *old_sw; unsigned size = sizeof(struct pt_regs) + @@ -1023,7 +1023,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, pal_processor_state_info_t *psp = (pal_processor_state_info_t *) &sos->proc_state_param; int recover, cpu = smp_processor_id(); - task_t *previous_current; + struct task_struct *previous_current; struct ia64_mca_notify_die nd = { .sos = sos, .monarch_cpu = &monarch_cpu }; @@ -1352,7 +1352,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw, { static atomic_t slaves; static atomic_t monarchs; - task_t *previous_current; + struct task_struct *previous_current; int cpu = smp_processor_id(); struct ia64_mca_notify_die nd = { .sos = sos, .monarch_cpu = &monarch_cpu }; @@ -1457,38 +1457,38 @@ __setup("disable_cpe_poll", ia64_mca_disable_cpe_polling); static struct irqaction cmci_irqaction = { .handler = ia64_mca_cmc_int_handler, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "cmc_hndlr" }; static struct irqaction cmcp_irqaction = { .handler = ia64_mca_cmc_int_caller, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "cmc_poll" }; static struct irqaction mca_rdzv_irqaction = { .handler = ia64_mca_rendez_int_handler, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "mca_rdzv" }; static struct irqaction mca_wkup_irqaction = { .handler = ia64_mca_wakeup_int_handler, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "mca_wkup" }; #ifdef CONFIG_ACPI static struct irqaction mca_cpe_irqaction = { .handler = ia64_mca_cpe_int_handler, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "cpe_hndlr" }; static struct irqaction mca_cpep_irqaction = { .handler = ia64_mca_cpe_int_caller, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "cpe_poll" }; #endif /* CONFIG_ACPI */ diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 92b815d1341..c7ccd6ee1dd 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -6439,7 +6439,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) static struct irqaction perfmon_irqaction = { .handler = pfm_interrupt_handler, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "perfmon" }; diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index e1960979be2..6203ed4ec8c 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -124,7 +124,7 @@ extern void __devinit calibrate_delay (void); extern void start_ap (void); extern unsigned long ia64_iobase; -task_t *task_for_booting_cpu; +struct task_struct *task_for_booting_cpu; /* * State for each CPU diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 71ccddabc71..6928ef0d64d 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -231,7 +231,7 @@ ia64_init_itm (void) static struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "timer" }; diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index 56ab6bae00e..96fb81e6321 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c @@ -178,7 +178,7 @@ void hubiio_crb_error_handler(struct hubdev_info *hubdev_info) */ void hub_error_init(struct hubdev_info *hubdev_info) { - if (request_irq(SGI_II_ERROR, (void *)hub_eint_handler, SA_SHIRQ, + if (request_irq(SGI_II_ERROR, (void *)hub_eint_handler, IRQF_SHARED, "SN_hub_error", (void *)hubdev_info)) printk("hub_error_init: Failed to request_irq for 0x%p\n", hubdev_info); @@ -196,7 +196,7 @@ void hub_error_init(struct hubdev_info *hubdev_info) void ice_error_init(struct hubdev_info *hubdev_info) { if (request_irq - (SGI_TIO_ERROR, (void *)hub_eint_handler, SA_SHIRQ, "SN_TIO_error", + (SGI_TIO_ERROR, (void *)hub_eint_handler, IRQF_SHARED, "SN_TIO_error", (void *)hubdev_info)) printk("ice_error_init: request_irq() error hubdev_info 0x%p\n", hubdev_info); diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 8255a9be463..c2f69f7942a 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -202,7 +202,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) init_waitqueue_head(&part->channel_mgr_wq); sprintf(part->IPI_owner, "xpc%02d", partid); - ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ, + ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, IRQF_SHARED, part->IPI_owner, (void *) (u64) partid); if (ret != 0) { dev_err(xpc_chan, "can't register NOTIFY IRQ handler, " diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index ab1211ef017..838c93c9a16 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -139,7 +139,7 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont * register the bridge's error interrupt handler */ if (request_irq(SGI_PCIASIC_ERROR, (void *)pcibr_error_intr_handler, - SA_SHIRQ, "PCIBR error", (void *)(soft))) { + IRQF_SHARED, "PCIBR error", (void *)(soft))) { printk(KERN_WARNING "pcibr cannot allocate interrupt for error handler\n"); } diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index e4aa839d018..c36b0f5affb 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -646,7 +646,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont if (request_irq(SGI_TIOCA_ERROR, tioca_error_intr_handler, - SA_SHIRQ, "TIOCA error", (void *)tioca_common)) + IRQF_SHARED, "TIOCA error", (void *)tioca_common)) printk(KERN_WARNING "%s: Unable to get irq %d. " "Error interrupts won't be routed for TIOCA bus %d\n", diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 2d7948567eb..17cd3428488 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -1027,7 +1027,7 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont if (request_irq(SGI_PCIASIC_ERROR, tioce_error_intr_handler, - SA_SHIRQ, "TIOCE error", (void *)tioce_common)) + IRQF_SHARED, "TIOCE error", (void *)tioce_common)) printk(KERN_WARNING "%s: Unable to get irq %d. " "Error interrupts won't be routed for " diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c index efff6f5151d..ded0be07a47 100644 --- a/arch/m32r/kernel/time.c +++ b/arch/m32r/kernel/time.c @@ -237,7 +237,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } -struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, +struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "MFT2", NULL, NULL }; void __init time_init(void) diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c index f9403f4640a..96c79d840cf 100644 --- a/arch/m68k/amiga/amiints.c +++ b/arch/m68k/amiga/amiints.c @@ -22,7 +22,7 @@ * * 07/08/99: rewamp of the interrupt handling - we now have two types of * interrupts, normal and fast handlers, fast handlers being - * marked with SA_INTERRUPT and runs with all other interrupts + * marked with IRQF_DISABLED and runs with all other interrupts * disabled. Normal interrupts disable their own source but * run with all other interrupt sources enabled. * PORTS and EXTER interrupts are always shared even if the diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 0956e45399e..dbad3005472 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c @@ -176,5 +176,5 @@ void __init cia_init_IRQ(struct ciabase *base) /* override auto int and install CIA handler */ m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1); m68k_irq_startup(base->handler_irq); - request_irq(base->handler_irq, cia_handler, SA_SHIRQ, base->name, base); + request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base); } diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index e969f047764..b33e37fb7b0 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -192,7 +192,7 @@ int setup_irq(unsigned int irq, struct irq_node *node) prev = irq_list + irq; if (*prev) { /* Can't share interrupts unless both agree to */ - if (!((*prev)->flags & node->flags & SA_SHIRQ)) { + if (!((*prev)->flags & node->flags & IRQF_SHARED)) { spin_unlock_irqrestore(&contr->lock, flags); return -EBUSY; } diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c index 994c893df1a..9dc5688f71b 100644 --- a/arch/m68knommu/platform/5307/pit.c +++ b/arch/m68knommu/platform/5307/pit.c @@ -48,7 +48,7 @@ void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) volatile unsigned char *icrp; volatile unsigned long *imrp; - request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, SA_INTERRUPT, + request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, IRQF_DISABLED, "ColdFire Timer", NULL); icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 + diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c index c3a9755c2d1..24781f00933 100644 --- a/arch/m68knommu/platform/5307/timers.c +++ b/arch/m68knommu/platform/5307/timers.c @@ -61,7 +61,7 @@ void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); - request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL); + request_irq(mcf_timervector, handler, IRQF_DISABLED, "timer", NULL); mcf_settimericr(1, mcf_timerlevel); #ifdef CONFIG_HIGHPROFILE @@ -125,7 +125,7 @@ void coldfire_profile_init(void) MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); request_irq(mcf_profilevector, coldfire_profile_tick, - (SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL); + (IRQF_DISABLED | IRQ_FLG_FAST), "profile timer", NULL); mcf_settimericr(2, 7); } diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c index 69cabb7463f..98244d51c15 100644 --- a/arch/mips/au1000/common/dbdma.c +++ b/arch/mips/au1000/common/dbdma.c @@ -892,7 +892,7 @@ static void au1xxx_dbdma_init(void) #error Unknown Au1x00 SOC #endif - if (request_irq(irq_nr, dbdma_interrupt, SA_INTERRUPT, + if (request_irq(irq_nr, dbdma_interrupt, IRQF_DISABLED, "Au1xxx dbdma", (void *)dbdma_gptr)) printk("Can't get 1550 dbdma irq"); } diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index c0d56c130a5..29d6f8178ba 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -309,7 +309,7 @@ void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_reg * can avoid it. --cgray */ action.dev_id = handler; - action.flags = SA_INTERRUPT; + action.flags = IRQF_DISABLED; cpus_clear(action.mask); action.name = "Au1xxx TOY"; action.handler = handler; diff --git a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c index 2cab7629702..63bcb3a95dc 100644 --- a/arch/mips/au1000/common/usbdev.c +++ b/arch/mips/au1000/common/usbdev.c @@ -1465,14 +1465,14 @@ usbdev_init(struct usb_device_descriptor* dev_desc, */ /* request the USB device transfer complete interrupt */ - if (request_irq(AU1000_USB_DEV_REQ_INT, req_sus_intr, SA_INTERRUPT, + if (request_irq(AU1000_USB_DEV_REQ_INT, req_sus_intr, IRQF_DISABLED, "USBdev req", &usbdev)) { err("Can't get device request intr"); ret = -ENXIO; goto out; } /* request the USB device suspend interrupt */ - if (request_irq(AU1000_USB_DEV_SUS_INT, req_sus_intr, SA_INTERRUPT, + if (request_irq(AU1000_USB_DEV_SUS_INT, req_sus_intr, IRQF_DISABLED, "USBdev sus", &usbdev)) { err("Can't get device suspend intr"); ret = -ENXIO; @@ -1483,7 +1483,7 @@ usbdev_init(struct usb_device_descriptor* dev_desc, if ((ep0->indma = request_au1000_dma(ep_dma_id[0].id, ep_dma_id[0].str, dma_done_ep0_intr, - SA_INTERRUPT, + IRQF_DISABLED, &usbdev)) < 0) { err("Can't get %s DMA", ep_dma_id[0].str); ret = -ENXIO; @@ -1516,7 +1516,7 @@ usbdev_init(struct usb_device_descriptor* dev_desc, request_au1000_dma(ep_dma_id[ep->address].id, ep_dma_id[ep->address].str, dma_done_ep_intr, - SA_INTERRUPT, + IRQF_DISABLED, &usbdev); if (ep->indma < 0) { err("Can't get %s DMA", diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c index 91121e52304..b288151b532 100644 --- a/arch/mips/basler/excite/excite_iodev.c +++ b/arch/mips/basler/excite/excite_iodev.c @@ -113,7 +113,7 @@ static int __exit iodev_remove(struct device *dev) static int iodev_open(struct inode *i, struct file *f) { - return request_irq(iodev_irq, iodev_irqhdl, SA_INTERRUPT, + return request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED, iodev_name, &miscdev); } diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index 9c707b9ceb6..2684f121784 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -105,7 +105,7 @@ static struct irqaction fpuirq = { }; static struct irqaction busirq = { - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "bus error", }; @@ -124,7 +124,7 @@ static void __init dec_be_init(void) case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */ board_be_handler = dec_kn01_be_handler; busirq.handler = dec_kn01_be_interrupt; - busirq.flags |= SA_SHIRQ; + busirq.flags |= IRQF_SHARED; dec_kn01_be_init(); break; case MACH_DS5000_1XX: /* DS5000/1xx 3min */ diff --git a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c index c64a7723caf..d837b26fbe5 100644 --- a/arch/mips/gt64120/common/time.c +++ b/arch/mips/gt64120/common/time.c @@ -77,7 +77,7 @@ void gt64120_time_init(void) * the values to the correct interrupt line. */ timer.handler = gt64120_irq; - timer.flags = SA_SHIRQ | SA_INTERRUPT; + timer.flags = IRQF_SHARED | IRQF_DISABLED; timer.name = "timer"; timer.dev_id = NULL; timer.next = NULL; diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index ecfd637d702..01e7fa86aa4 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -65,7 +65,7 @@ need_resched: #endif FEXPORT(ret_from_fork) - jal schedule_tail # a0 = task_t *prev + jal schedule_tail # a0 = struct task_struct *prev FEXPORT(syscall_exit) local_irq_disable # make sure need_resched and diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c index 02237a685ec..4dcc39f4295 100644 --- a/arch/mips/kernel/mips-mt.c +++ b/arch/mips/kernel/mips-mt.c @@ -47,7 +47,7 @@ unsigned long mt_fpemul_threshold = 0; * used in sys_sched_set/getaffinity() in kernel/sched.c, so * cloned here. */ -static inline task_t *find_process_by_pid(pid_t pid) +static inline struct task_struct *find_process_by_pid(pid_t pid) { return pid ? find_task_by_pid(pid) : current; } @@ -62,7 +62,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, cpumask_t new_mask; cpumask_t effective_mask; int retval; - task_t *p; + struct task_struct *p; if (len < sizeof(new_mask)) return -EINVAL; @@ -127,7 +127,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len, unsigned int real_len; cpumask_t mask; int retval; - task_t *p; + struct task_struct *p; real_len = sizeof(mask); if (len < real_len) diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index caf777f8328..cdab1b2cd13 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -487,7 +487,7 @@ static struct file_operations rtlx_fops = { static struct irqaction rtlx_irq = { .handler = rtlx_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "RTLX", }; diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 57770902b9a..93429a4d301 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -130,13 +130,13 @@ irqreturn_t ipi_call_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction irq_resched = { .handler = ipi_resched_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "IPI_resched" }; static struct irqaction irq_call = { .handler = ipi_call_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "IPI_call" }; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 70cf09afdf5..a48d9e55308 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -1002,7 +1002,7 @@ void setup_cross_vpe_interrupts(void) set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch); irq_ipi.handler = ipi_interrupt; - irq_ipi.flags = SA_INTERRUPT; + irq_ipi.flags = IRQF_DISABLED; irq_ipi.name = "SMTC_IPI"; setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ)); diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index c2b1fcf6024..2393c11d5a2 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -579,7 +579,7 @@ unsigned int mips_hpt_frequency; static struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "timer", }; diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c index ec4032b38f1..f9067469a65 100644 --- a/arch/mips/momentum/jaguar_atx/irq.c +++ b/arch/mips/momentum/jaguar_atx/irq.c @@ -71,7 +71,7 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs) } static struct irqaction cascade_mv64340 = { - no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL + no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL }; void __init arch_init_irq(void) diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c index 87c63c340ae..793782a9c19 100644 --- a/arch/mips/momentum/ocelot_3/irq.c +++ b/arch/mips/momentum/ocelot_3/irq.c @@ -54,7 +54,7 @@ #include <asm/system.h> static struct irqaction cascade_mv64340 = { - no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL + no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL }; void __init arch_init_irq(void) diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c index 86f61ce59e5..9d44ae1e156 100644 --- a/arch/mips/momentum/ocelot_c/irq.c +++ b/arch/mips/momentum/ocelot_c/irq.c @@ -52,11 +52,11 @@ extern void uart_irq_init(void); extern void cpci_irq_init(void); static struct irqaction cascade_fpga = { - no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via FPGA", NULL, NULL + no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via FPGA", NULL, NULL }; static struct irqaction cascade_mv64340 = { - no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL + no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL }; extern void ll_uart_irq(struct pt_regs *regs); diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c index 047457f3b97..9fb2493fff0 100644 --- a/arch/mips/momentum/ocelot_g/gt-irq.c +++ b/arch/mips/momentum/ocelot_g/gt-irq.c @@ -173,7 +173,7 @@ void gt64240_time_init(void) * the values to the correct interrupt line. */ timer.handler = >64240_p0int_irq; - timer.flags = SA_SHIRQ | SA_INTERRUPT; + timer.flags = IRQF_SHARED | IRQF_DISABLED; timer.name = "timer"; timer.dev_id = NULL; timer.next = NULL; diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c index 388a4df7304..8aca317d462 100644 --- a/arch/mips/philips/pnx8550/common/int.c +++ b/arch/mips/philips/pnx8550/common/int.c @@ -219,13 +219,13 @@ static struct hw_interrupt_type level_irq_type = { static struct irqaction gic_action = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "GIC", }; static struct irqaction timer_action = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "Timer", }; diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index aee567dc372..2d8762818d9 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -272,32 +272,32 @@ static void indy_buserror_irq(struct pt_regs *regs) static struct irqaction local0_cascade = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "local0 cascade", }; static struct irqaction local1_cascade = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "local1 cascade", }; static struct irqaction buserr = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "Bus Error", }; static struct irqaction map0_cascade = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "mapable0 cascade", }; #ifdef USE_LIO3_IRQ static struct irqaction map1_cascade = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "mapable1 cascade", }; #define SGI_INTERRUPTS SGINT_END diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index a94e4c78580..597ec73359b 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -118,7 +118,7 @@ static int ms1bit(unsigned long x) } /* - * This code is unnecessarily complex, because we do SA_INTERRUPT + * This code is unnecessarily complex, because we do IRQF_DISABLED * intr enabling. Basically, once we grab the set of intrs we need * to service, we must mask _all_ these interrupts; firstly, to make * sure the same intr does not intr again, causing recursion that diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 1fb860c7ac6..3ca614a851e 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -217,7 +217,7 @@ static struct hw_interrupt_type rt_irq_type = { static struct irqaction rt_irqaction = { .handler = ip27_rt_timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "timer" }; diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 00b94aaf637..3b7e74b6222 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c @@ -125,9 +125,9 @@ extern irqreturn_t crime_memerr_intr (int irq, void *dev_id, extern irqreturn_t crime_cpuerr_intr (int irq, void *dev_id, struct pt_regs *regs); -struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT, +struct irqaction memerr_irq = { crime_memerr_intr, IRQF_DISABLED, CPU_MASK_NONE, "CRIME memory error", NULL, NULL }; -struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, +struct irqaction cpuerr_irq = { crime_cpuerr_intr, IRQF_DISABLED, CPU_MASK_NONE, "CRIME CPU error", NULL, NULL }; /* @@ -316,9 +316,9 @@ static struct hw_interrupt_type ip32_macepci_interrupt = { MACEISA_KEYB_POLL_INT | \ MACEISA_MOUSE_INT | \ MACEISA_MOUSE_POLL_INT | \ - MACEISA_TIMER0_INT | \ - MACEISA_TIMER1_INT | \ - MACEISA_TIMER2_INT) + MACEIIRQF_TIMER0_INT | \ + MACEIIRQF_TIMER1_INT | \ + MACEIIRQF_TIMER2_INT) #define MACEISA_SUPERIO_INT (MACEISA_PARALLEL_INT | \ MACEISA_PAR_CTXA_INT | \ MACEISA_PAR_CTXB_INT | \ @@ -349,7 +349,7 @@ static void enable_maceisa_irq (unsigned int irq) case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: crime_int = MACE_AUDIO_INT; break; - case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ: + case MACEISA_RTC_IRQ ... MACEIIRQF_TIMER2_IRQ: crime_int = MACE_MISC_INT; break; case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ: diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c index ee943cb1328..ec0a0de3083 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c @@ -337,7 +337,7 @@ int toshiba_rbtx4927_irq_nested(int sw_irq) } //#define TOSHIBA_RBTX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL } -#define TOSHIBA_RBTX4927_PIC_ACTION(s) { no_action, SA_SHIRQ, CPU_MASK_NONE, s, NULL, NULL } +#define TOSHIBA_RBTX4927_PIC_ACTION(s) { no_action, IRQF_SHARED, CPU_MASK_NONE, s, NULL, NULL } static struct irqaction toshiba_rbtx4927_irq_ioc_action = TOSHIBA_RBTX4927_PIC_ACTION(TOSHIBA_RBTX4927_IOC_NAME); #ifdef CONFIG_TOSHIBA_FPCIB0 diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 52761d96f99..5b8803cc3d6 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -366,14 +366,14 @@ void do_cpu_irq_mask(struct pt_regs *regs) static struct irqaction timer_action = { .handler = timer_interrupt, .name = "timer", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, }; #ifdef CONFIG_SMP static struct irqaction ipi_action = { .handler = ipi_interrupt, .name = "IPI", - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, }; #endif diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig new file mode 100644 index 00000000000..0fa010a63a8 --- /dev/null +++ b/arch/powerpc/configs/chrp32_defconfig @@ -0,0 +1,1378 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17 +# Mon Jul 3 12:08:41 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +CONFIG_CLASSIC32=y +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +# CONFIG_ALTIVEC is not set +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Block layer +# +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Platform support +# +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_ISERIES is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set +CONFIG_PPC_CHRP=y +# CONFIG_PPC_PMAC is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +CONFIG_MPIC=y +CONFIG_PPC_RTAS=y +# CONFIG_RTAS_ERROR_LOGGING is not set +CONFIG_RTAS_PROC=y +# CONFIG_MMIO_NVRAM is not set +CONFIG_PPC_MPC106=y +# CONFIG_PPC_970_NAP is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_TAU is not set +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +# CONFIG_KEXEC is not set +CONFIG_IRQ_ALL_CPUS=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ISA=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +# CONFIG_IP_NF_SIP is not set +# CONFIG_IP_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +# CONFIG_TULIP is not set +CONFIG_DE4X5=y +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +CONFIG_8139CP=y +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +CONFIG_VIA_RHINE=y +# CONFIG_VIA_RHINE_MMIO is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_MV643XX_ETH=y +# CONFIG_MV643XX_ETH_0 is not set +# CONFIG_MV643XX_ETH_1 is not set +# CONFIG_MV643XX_ETH_2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_PCSPKR is not set +CONFIG_INPUT_UINPUT=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_HVC_RTAS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_NVRAM=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_HYDRA is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_MACMODES=y +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +# CONFIG_FB_MATROX_I2C is not set +# CONFIG_FB_MATROX_MULTIHEAD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +# CONFIG_FB_ATY128 is not set +CONFIG_FB_ATY=y +CONFIG_FB_ATY_CT=y +# CONFIG_FB_ATY_GENERIC_LCD is not set +CONFIG_FB_ATY_GX=y +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +CONFIG_FB_3DFX=y +# CONFIG_FB_3DFX_ACCEL is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUGGER=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +CONFIG_CRYPTO_SHA1=m +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig new file mode 100644 index 00000000000..fc2d9789adc --- /dev/null +++ b/arch/powerpc/configs/mpc834x_itx_defconfig @@ -0,0 +1,1336 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17 +# Fri Jun 30 17:53:25 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +CONFIG_PPC_83xx=y +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_83xx=y +CONFIG_PPC_FPU=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_PPC_GEN550=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC834x_SYS is not set +CONFIG_MPC834x_ITX=y +CONFIG_MPC834x=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SOFTWARE_SUSPEND is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_PARTITIONS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xfe000000 +CONFIG_MTD_PHYSMAP_LEN=0x1000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +# CONFIG_BLK_DEV_IDE is not set +# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set +# CONFIG_SCSI_SATA_NV is not set +# CONFIG_SCSI_PDC_ADMA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SX4 is not set +CONFIG_SCSI_SATA_SIL=y +# CONFIG_SCSI_SATA_SIL24 is not set +# CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_SATA_VITESSE is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set +# CONFIG_MD_RAID456 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +# CONFIG_BLK_DEV_DM is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +CONFIG_CICADA_PHY=y +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_83xx_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y +CONFIG_SPI_MPC83xx=y + +# +# SPI Protocol Masters +# + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_NET2280=y +CONFIG_USB_NET2280=y +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=y + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +CONFIG_BOOTX_TEXT=y +CONFIG_SERIAL_TEXT_DEBUG=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index a6920919d68..f4e5e14ee2b 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -111,7 +111,7 @@ void __init btext_setup_display(int width, int height, int depth, int pitch, logicalDisplayBase = (unsigned char *)address; dispDeviceBase = (unsigned char *)address; dispDeviceRowBytes = pitch; - dispDeviceDepth = depth; + dispDeviceDepth = depth == 15 ? 16 : depth; dispDeviceRect[0] = dispDeviceRect[1] = 0; dispDeviceRect[2] = width; dispDeviceRect[3] = height; @@ -160,20 +160,28 @@ int btext_initialize(struct device_node *np) unsigned long address = 0; u32 *prop; - prop = (u32 *)get_property(np, "width", NULL); + prop = (u32 *)get_property(np, "linux,bootx-width", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "width", NULL); if (prop == NULL) return -EINVAL; width = *prop; - prop = (u32 *)get_property(np, "height", NULL); + prop = (u32 *)get_property(np, "linux,bootx-height", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "height", NULL); if (prop == NULL) return -EINVAL; height = *prop; - prop = (u32 *)get_property(np, "depth", NULL); + prop = (u32 *)get_property(np, "linux,bootx-depth", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "depth", NULL); if (prop == NULL) return -EINVAL; depth = *prop; pitch = width * ((depth + 7) / 8); - prop = (u32 *)get_property(np, "linebytes", NULL); + prop = (u32 *)get_property(np, "linux,bootx-linebytes", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "linebytes", NULL); if (prop) pitch = *prop; if (pitch == 1) @@ -194,7 +202,7 @@ int btext_initialize(struct device_node *np) g_max_loc_Y = height / 16; dispDeviceBase = (unsigned char *)address; dispDeviceRowBytes = pitch; - dispDeviceDepth = depth; + dispDeviceDepth = depth == 15 ? 16 : depth; dispDeviceRect[0] = dispDeviceRect[1] = 0; dispDeviceRect[2] = width; dispDeviceRect[3] = height; diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index e47d40ac6f3..97ddc02a3d4 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -323,13 +323,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev, unsigned long irq_flags, const char * devname, void *dev_id) { - unsigned int irq = virt_irq_create_mapping(ist); + unsigned int irq = irq_create_mapping(NULL, ist, 0); if (irq == NO_IRQ) return -EINVAL; - irq = irq_offset_up(irq); - return request_irq(irq, handler, irq_flags, devname, dev_id); } @@ -337,12 +335,9 @@ EXPORT_SYMBOL(ibmebus_request_irq); void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id) { - unsigned int irq = virt_irq_create_mapping(ist); + unsigned int irq = irq_find_mapping(NULL, ist); - irq = irq_offset_up(irq); free_irq(irq, dev_id); - - return; } EXPORT_SYMBOL(ibmebus_free_irq); diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 525baab45d2..8cf987809c6 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -29,6 +29,8 @@ * to reduce code space and undefined function references. */ +#undef DEBUG + #include <linux/module.h> #include <linux/threads.h> #include <linux/kernel_stat.h> @@ -46,7 +48,10 @@ #include <linux/cpumask.h> #include <linux/profile.h> #include <linux/bitops.h> -#include <linux/pci.h> +#include <linux/list.h> +#include <linux/radix-tree.h> +#include <linux/mutex.h> +#include <linux/bootmem.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -57,39 +62,38 @@ #include <asm/prom.h> #include <asm/ptrace.h> #include <asm/machdep.h> +#include <asm/udbg.h> #ifdef CONFIG_PPC_ISERIES #include <asm/paca.h> #endif int __irq_offset_value; -#ifdef CONFIG_PPC32 -EXPORT_SYMBOL(__irq_offset_value); -#endif - static int ppc_spurious_interrupts; #ifdef CONFIG_PPC32 -#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) +EXPORT_SYMBOL(__irq_offset_value); +atomic_t ppc_n_lost_interrupts; +#ifndef CONFIG_PPC_MERGE +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; -atomic_t ppc_n_lost_interrupts; +#endif #ifdef CONFIG_TAU_INT extern int tau_initialized; extern int tau_interrupts(int); #endif +#endif /* CONFIG_PPC32 */ #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) extern atomic_t ipi_recv; extern atomic_t ipi_sent; #endif -#endif /* CONFIG_PPC32 */ #ifdef CONFIG_PPC64 EXPORT_SYMBOL(irq_desc); int distribute_irqs = 1; -u64 ppc64_interrupt_controller; #endif /* CONFIG_PPC64 */ int show_interrupts(struct seq_file *p, void *v) @@ -182,7 +186,7 @@ void fixup_irqs(cpumask_t map) void do_IRQ(struct pt_regs *regs) { - int irq; + unsigned int irq; #ifdef CONFIG_IRQSTACKS struct thread_info *curtp, *irqtp; #endif @@ -213,22 +217,26 @@ void do_IRQ(struct pt_regs *regs) */ irq = ppc_md.get_irq(regs); - if (irq >= 0) { + if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) { #ifdef CONFIG_IRQSTACKS /* Switch to the irq stack to handle this */ curtp = current_thread_info(); irqtp = hardirq_ctx[smp_processor_id()]; if (curtp != irqtp) { + struct irq_desc *desc = irq_desc + irq; + void *handler = desc->handle_irq; + if (handler == NULL) + handler = &__do_IRQ; irqtp->task = curtp->task; irqtp->flags = 0; - call___do_IRQ(irq, regs, irqtp); + call_handle_irq(irq, desc, regs, irqtp, handler); irqtp->task = NULL; if (irqtp->flags) set_bits(irqtp->flags, &curtp->flags); } else #endif - __do_IRQ(irq, regs); - } else if (irq != -2) + generic_handle_irq(irq, regs); + } else if (irq != NO_IRQ_IGNORE) /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; @@ -245,196 +253,562 @@ void do_IRQ(struct pt_regs *regs) void __init init_IRQ(void) { + ppc_md.init_IRQ(); #ifdef CONFIG_PPC64 - static int once = 0; + irq_ctx_init(); +#endif +} + + +#ifdef CONFIG_IRQSTACKS +struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; +struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly; + +void irq_ctx_init(void) +{ + struct thread_info *tp; + int i; + + for_each_possible_cpu(i) { + memset((void *)softirq_ctx[i], 0, THREAD_SIZE); + tp = softirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = SOFTIRQ_OFFSET; + + memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); + tp = hardirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = HARDIRQ_OFFSET; + } +} + +static inline void do_softirq_onstack(void) +{ + struct thread_info *curtp, *irqtp; + + curtp = current_thread_info(); + irqtp = softirq_ctx[smp_processor_id()]; + irqtp->task = curtp->task; + call_do_softirq(irqtp); + irqtp->task = NULL; +} - if (once) +#else +#define do_softirq_onstack() __do_softirq() +#endif /* CONFIG_IRQSTACKS */ + +void do_softirq(void) +{ + unsigned long flags; + + if (in_interrupt()) return; - once++; + local_irq_save(flags); -#endif - ppc_md.init_IRQ(); -#ifdef CONFIG_PPC64 - irq_ctx_init(); -#endif + if (local_softirq_pending()) + do_softirq_onstack(); + + local_irq_restore(flags); } +EXPORT_SYMBOL(do_softirq); + -#ifdef CONFIG_PPC64 /* - * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. + * IRQ controller and virtual interrupts */ -#define UNDEFINED_IRQ 0xffffffff -unsigned int virt_irq_to_real_map[NR_IRQS]; +#ifdef CONFIG_PPC_MERGE -/* - * Don't use virtual irqs 0, 1, 2 for devices. - * The pcnet32 driver considers interrupt numbers < 2 to be invalid, - * and 2 is the XICS IPI interrupt. - * We limit virtual irqs to __irq_offet_value less than virt_irq_max so - * that when we offset them we don't end up with an interrupt - * number >= virt_irq_max. - */ -#define MIN_VIRT_IRQ 3 +static LIST_HEAD(irq_hosts); +static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED; -unsigned int virt_irq_max; -static unsigned int max_virt_irq; -static unsigned int nr_virt_irqs; +struct irq_map_entry irq_map[NR_IRQS]; +static unsigned int irq_virq_count = NR_IRQS; +static struct irq_host *irq_default_host; -void -virt_irq_init(void) +struct irq_host *irq_alloc_host(unsigned int revmap_type, + unsigned int revmap_arg, + struct irq_host_ops *ops, + irq_hw_number_t inval_irq) { - int i; + struct irq_host *host; + unsigned int size = sizeof(struct irq_host); + unsigned int i; + unsigned int *rmap; + unsigned long flags; - if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1))) - virt_irq_max = NR_IRQS - 1; - max_virt_irq = virt_irq_max - __irq_offset_value; - nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1; + /* Allocate structure and revmap table if using linear mapping */ + if (revmap_type == IRQ_HOST_MAP_LINEAR) + size += revmap_arg * sizeof(unsigned int); + if (mem_init_done) + host = kzalloc(size, GFP_KERNEL); + else { + host = alloc_bootmem(size); + if (host) + memset(host, 0, size); + } + if (host == NULL) + return NULL; - for (i = 0; i < NR_IRQS; i++) - virt_irq_to_real_map[i] = UNDEFINED_IRQ; + /* Fill structure */ + host->revmap_type = revmap_type; + host->inval_irq = inval_irq; + host->ops = ops; + + spin_lock_irqsave(&irq_big_lock, flags); + + /* If it's a legacy controller, check for duplicates and + * mark it as allocated (we use irq 0 host pointer for that + */ + if (revmap_type == IRQ_HOST_MAP_LEGACY) { + if (irq_map[0].host != NULL) { + spin_unlock_irqrestore(&irq_big_lock, flags); + /* If we are early boot, we can't free the structure, + * too bad... + * this will be fixed once slab is made available early + * instead of the current cruft + */ + if (mem_init_done) + kfree(host); + return NULL; + } + irq_map[0].host = host; + } + + list_add(&host->link, &irq_hosts); + spin_unlock_irqrestore(&irq_big_lock, flags); + + /* Additional setups per revmap type */ + switch(revmap_type) { + case IRQ_HOST_MAP_LEGACY: + /* 0 is always the invalid number for legacy */ + host->inval_irq = 0; + /* setup us as the host for all legacy interrupts */ + for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { + irq_map[i].hwirq = 0; + smp_wmb(); + irq_map[i].host = host; + smp_wmb(); + + /* Clear some flags */ + get_irq_desc(i)->status + &= ~(IRQ_NOREQUEST | IRQ_LEVEL); + + /* Legacy flags are left to default at this point, + * one can then use irq_create_mapping() to + * explicitely change them + */ + ops->map(host, i, i, 0); + } + break; + case IRQ_HOST_MAP_LINEAR: + rmap = (unsigned int *)(host + 1); + for (i = 0; i < revmap_arg; i++) + rmap[i] = IRQ_NONE; + host->revmap_data.linear.size = revmap_arg; + smp_wmb(); + host->revmap_data.linear.revmap = rmap; + break; + default: + break; + } + + pr_debug("irq: Allocated host of type %d @0x%p\n", revmap_type, host); + + return host; } -/* Create a mapping for a real_irq if it doesn't already exist. - * Return the virtual irq as a convenience. - */ -int virt_irq_create_mapping(unsigned int real_irq) +struct irq_host *irq_find_host(struct device_node *node) { - unsigned int virq, first_virq; - static int warned; + struct irq_host *h, *found = NULL; + unsigned long flags; + + /* We might want to match the legacy controller last since + * it might potentially be set to match all interrupts in + * the absence of a device node. This isn't a problem so far + * yet though... + */ + spin_lock_irqsave(&irq_big_lock, flags); + list_for_each_entry(h, &irq_hosts, link) + if (h->ops->match == NULL || h->ops->match(h, node)) { + found = h; + break; + } + spin_unlock_irqrestore(&irq_big_lock, flags); + return found; +} +EXPORT_SYMBOL_GPL(irq_find_host); + +void irq_set_default_host(struct irq_host *host) +{ + pr_debug("irq: Default host set to @0x%p\n", host); + + irq_default_host = host; +} - if (ppc64_interrupt_controller == IC_OPEN_PIC) - return real_irq; /* no mapping for openpic (for now) */ +void irq_set_virq_count(unsigned int count) +{ + pr_debug("irq: Trying to set virq count to %d\n", count); - if (ppc64_interrupt_controller == IC_CELL_PIC) - return real_irq; /* no mapping for iic either */ + BUG_ON(count < NUM_ISA_INTERRUPTS); + if (count < NR_IRQS) + irq_virq_count = count; +} - /* don't map interrupts < MIN_VIRT_IRQ */ - if (real_irq < MIN_VIRT_IRQ) { - virt_irq_to_real_map[real_irq] = real_irq; - return real_irq; +unsigned int irq_create_mapping(struct irq_host *host, + irq_hw_number_t hwirq, + unsigned int flags) +{ + unsigned int virq, hint; + + pr_debug("irq: irq_create_mapping(0x%p, 0x%lx, 0x%x)\n", + host, hwirq, flags); + + /* Look for default host if nececssary */ + if (host == NULL) + host = irq_default_host; + if (host == NULL) { + printk(KERN_WARNING "irq_create_mapping called for" + " NULL host, hwirq=%lx\n", hwirq); + WARN_ON(1); + return NO_IRQ; } + pr_debug("irq: -> using host @%p\n", host); - /* map to a number between MIN_VIRT_IRQ and max_virt_irq */ - virq = real_irq; - if (virq > max_virt_irq) - virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ; - - /* search for this number or a free slot */ - first_virq = virq; - while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) { - if (virt_irq_to_real_map[virq] == real_irq) - return virq; - if (++virq > max_virt_irq) - virq = MIN_VIRT_IRQ; - if (virq == first_virq) - goto nospace; /* oops, no free slots */ + /* Check if mapping already exist, if it does, call + * host->ops->map() to update the flags + */ + virq = irq_find_mapping(host, hwirq); + if (virq != IRQ_NONE) { + pr_debug("irq: -> existing mapping on virq %d\n", virq); + host->ops->map(host, virq, hwirq, flags); + return virq; + } + + /* Get a virtual interrupt number */ + if (host->revmap_type == IRQ_HOST_MAP_LEGACY) { + /* Handle legacy */ + virq = (unsigned int)hwirq; + if (virq == 0 || virq >= NUM_ISA_INTERRUPTS) + return NO_IRQ; + return virq; + } else { + /* Allocate a virtual interrupt number */ + hint = hwirq % irq_virq_count; + virq = irq_alloc_virt(host, 1, hint); + if (virq == NO_IRQ) { + pr_debug("irq: -> virq allocation failed\n"); + return NO_IRQ; + } } + pr_debug("irq: -> obtained virq %d\n", virq); - virt_irq_to_real_map[virq] = real_irq; + /* Clear some flags */ + get_irq_desc(virq)->status &= ~(IRQ_NOREQUEST | IRQ_LEVEL); + + /* map it */ + if (host->ops->map(host, virq, hwirq, flags)) { + pr_debug("irq: -> mapping failed, freeing\n"); + irq_free_virt(virq, 1); + return NO_IRQ; + } + smp_wmb(); + irq_map[virq].hwirq = hwirq; + smp_mb(); return virq; +} +EXPORT_SYMBOL_GPL(irq_create_mapping); - nospace: - if (!warned) { - printk(KERN_CRIT "Interrupt table is full\n"); - printk(KERN_CRIT "Increase virt_irq_max (currently %d) " - "in your kernel sources and rebuild.\n", virt_irq_max); - warned = 1; +extern unsigned int irq_create_of_mapping(struct device_node *controller, + u32 *intspec, unsigned int intsize) +{ + struct irq_host *host; + irq_hw_number_t hwirq; + unsigned int flags = IRQ_TYPE_NONE; + + if (controller == NULL) + host = irq_default_host; + else + host = irq_find_host(controller); + if (host == NULL) + return NO_IRQ; + + /* If host has no translation, then we assume interrupt line */ + if (host->ops->xlate == NULL) + hwirq = intspec[0]; + else { + if (host->ops->xlate(host, controller, intspec, intsize, + &hwirq, &flags)) + return NO_IRQ; } - return NO_IRQ; + + return irq_create_mapping(host, hwirq, flags); } +EXPORT_SYMBOL_GPL(irq_create_of_mapping); -/* - * In most cases will get a hit on the very first slot checked in the - * virt_irq_to_real_map. Only when there are a large number of - * IRQs will this be expensive. - */ -unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) +unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { - unsigned int virq; - unsigned int first_virq; + struct of_irq oirq; - virq = real_irq; + if (of_irq_map_one(dev, index, &oirq)) + return NO_IRQ; - if (virq > max_virt_irq) - virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ; + return irq_create_of_mapping(oirq.controller, oirq.specifier, + oirq.size); +} +EXPORT_SYMBOL_GPL(irq_of_parse_and_map); - first_virq = virq; +void irq_dispose_mapping(unsigned int virq) +{ + struct irq_host *host = irq_map[virq].host; + irq_hw_number_t hwirq; + unsigned long flags; - do { - if (virt_irq_to_real_map[virq] == real_irq) - return virq; + WARN_ON (host == NULL); + if (host == NULL) + return; - virq++; + /* Never unmap legacy interrupts */ + if (host->revmap_type == IRQ_HOST_MAP_LEGACY) + return; - if (virq >= max_virt_irq) - virq = 0; + /* remove chip and handler */ + set_irq_chip_and_handler(virq, NULL, NULL); + + /* Make sure it's completed */ + synchronize_irq(virq); + + /* Tell the PIC about it */ + if (host->ops->unmap) + host->ops->unmap(host, virq); + smp_mb(); + + /* Clear reverse map */ + hwirq = irq_map[virq].hwirq; + switch(host->revmap_type) { + case IRQ_HOST_MAP_LINEAR: + if (hwirq < host->revmap_data.linear.size) + host->revmap_data.linear.revmap[hwirq] = IRQ_NONE; + break; + case IRQ_HOST_MAP_TREE: + /* Check if radix tree allocated yet */ + if (host->revmap_data.tree.gfp_mask == 0) + break; + /* XXX radix tree not safe ! remove lock whem it becomes safe + * and use some RCU sync to make sure everything is ok before we + * can re-use that map entry + */ + spin_lock_irqsave(&irq_big_lock, flags); + radix_tree_delete(&host->revmap_data.tree, hwirq); + spin_unlock_irqrestore(&irq_big_lock, flags); + break; + } - } while (first_virq != virq); + /* Destroy map */ + smp_mb(); + irq_map[virq].hwirq = host->inval_irq; - return NO_IRQ; + /* Set some flags */ + get_irq_desc(virq)->status |= IRQ_NOREQUEST; + /* Free it */ + irq_free_virt(virq, 1); } -#endif /* CONFIG_PPC64 */ +EXPORT_SYMBOL_GPL(irq_dispose_mapping); -#ifdef CONFIG_IRQSTACKS -struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; -struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly; +unsigned int irq_find_mapping(struct irq_host *host, + irq_hw_number_t hwirq) +{ + unsigned int i; + unsigned int hint = hwirq % irq_virq_count; + + /* Look for default host if nececssary */ + if (host == NULL) + host = irq_default_host; + if (host == NULL) + return NO_IRQ; + + /* legacy -> bail early */ + if (host->revmap_type == IRQ_HOST_MAP_LEGACY) + return hwirq; + + /* Slow path does a linear search of the map */ + if (hint < NUM_ISA_INTERRUPTS) + hint = NUM_ISA_INTERRUPTS; + i = hint; + do { + if (irq_map[i].host == host && + irq_map[i].hwirq == hwirq) + return i; + i++; + if (i >= irq_virq_count) + i = NUM_ISA_INTERRUPTS; + } while(i != hint); + return NO_IRQ; +} +EXPORT_SYMBOL_GPL(irq_find_mapping); -void irq_ctx_init(void) + +unsigned int irq_radix_revmap(struct irq_host *host, + irq_hw_number_t hwirq) { - struct thread_info *tp; - int i; + struct radix_tree_root *tree; + struct irq_map_entry *ptr; + unsigned int virq; + unsigned long flags; - for_each_possible_cpu(i) { - memset((void *)softirq_ctx[i], 0, THREAD_SIZE); - tp = softirq_ctx[i]; - tp->cpu = i; - tp->preempt_count = SOFTIRQ_OFFSET; + WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE); - memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); - tp = hardirq_ctx[i]; - tp->cpu = i; - tp->preempt_count = HARDIRQ_OFFSET; + /* Check if the radix tree exist yet. We test the value of + * the gfp_mask for that. Sneaky but saves another int in the + * structure. If not, we fallback to slow mode + */ + tree = &host->revmap_data.tree; + if (tree->gfp_mask == 0) + return irq_find_mapping(host, hwirq); + + /* XXX Current radix trees are NOT SMP safe !!! Remove that lock + * when that is fixed (when Nick's patch gets in + */ + spin_lock_irqsave(&irq_big_lock, flags); + + /* Now try to resolve */ + ptr = radix_tree_lookup(tree, hwirq); + /* Found it, return */ + if (ptr) { + virq = ptr - irq_map; + goto bail; } + + /* If not there, try to insert it */ + virq = irq_find_mapping(host, hwirq); + if (virq != NO_IRQ) + radix_tree_insert(tree, virq, &irq_map[virq]); + bail: + spin_unlock_irqrestore(&irq_big_lock, flags); + return virq; } -static inline void do_softirq_onstack(void) +unsigned int irq_linear_revmap(struct irq_host *host, + irq_hw_number_t hwirq) { - struct thread_info *curtp, *irqtp; + unsigned int *revmap; - curtp = current_thread_info(); - irqtp = softirq_ctx[smp_processor_id()]; - irqtp->task = curtp->task; - call_do_softirq(irqtp); - irqtp->task = NULL; + WARN_ON(host->revmap_type != IRQ_HOST_MAP_LINEAR); + + /* Check revmap bounds */ + if (unlikely(hwirq >= host->revmap_data.linear.size)) + return irq_find_mapping(host, hwirq); + + /* Check if revmap was allocated */ + revmap = host->revmap_data.linear.revmap; + if (unlikely(revmap == NULL)) + return irq_find_mapping(host, hwirq); + + /* Fill up revmap with slow path if no mapping found */ + if (unlikely(revmap[hwirq] == NO_IRQ)) + revmap[hwirq] = irq_find_mapping(host, hwirq); + + return revmap[hwirq]; } -#else -#define do_softirq_onstack() __do_softirq() -#endif /* CONFIG_IRQSTACKS */ +unsigned int irq_alloc_virt(struct irq_host *host, + unsigned int count, + unsigned int hint) +{ + unsigned long flags; + unsigned int i, j, found = NO_IRQ; + unsigned int limit = irq_virq_count - count; -void do_softirq(void) + if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS)) + return NO_IRQ; + + spin_lock_irqsave(&irq_big_lock, flags); + + /* Use hint for 1 interrupt if any */ + if (count == 1 && hint >= NUM_ISA_INTERRUPTS && + hint < irq_virq_count && irq_map[hint].host == NULL) { + found = hint; + goto hint_found; + } + + /* Look for count consecutive numbers in the allocatable + * (non-legacy) space + */ + for (i = NUM_ISA_INTERRUPTS; i <= limit; ) { + for (j = i; j < (i + count); j++) + if (irq_map[j].host != NULL) { + i = j + 1; + continue; + } + found = i; + break; + } + if (found == NO_IRQ) { + spin_unlock_irqrestore(&irq_big_lock, flags); + return NO_IRQ; + } + hint_found: + for (i = found; i < (found + count); i++) { + irq_map[i].hwirq = host->inval_irq; + smp_wmb(); + irq_map[i].host = host; + } + spin_unlock_irqrestore(&irq_big_lock, flags); + return found; +} + +void irq_free_virt(unsigned int virq, unsigned int count) { unsigned long flags; + unsigned int i; - if (in_interrupt()) - return; + WARN_ON (virq < NUM_ISA_INTERRUPTS); + WARN_ON (count == 0 || (virq + count) > irq_virq_count); - local_irq_save(flags); + spin_lock_irqsave(&irq_big_lock, flags); + for (i = virq; i < (virq + count); i++) { + struct irq_host *host; - if (local_softirq_pending()) { - account_system_vtime(current); - local_bh_disable(); - do_softirq_onstack(); - account_system_vtime(current); - __local_bh_enable(); + if (i < NUM_ISA_INTERRUPTS || + (virq + count) > irq_virq_count) + continue; + + host = irq_map[i].host; + irq_map[i].hwirq = host->inval_irq; + smp_wmb(); + irq_map[i].host = NULL; } + spin_unlock_irqrestore(&irq_big_lock, flags); +} - local_irq_restore(flags); +void irq_early_init(void) +{ + unsigned int i; + + for (i = 0; i < NR_IRQS; i++) + get_irq_desc(i)->status |= IRQ_NOREQUEST; } -EXPORT_SYMBOL(do_softirq); + +/* We need to create the radix trees late */ +static int irq_late_init(void) +{ + struct irq_host *h; + unsigned long flags; + + spin_lock_irqsave(&irq_big_lock, flags); + list_for_each_entry(h, &irq_hosts, link) { + if (h->revmap_type == IRQ_HOST_MAP_TREE) + INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC); + } + spin_unlock_irqrestore(&irq_big_lock, flags); + + return 0; +} +arch_initcall(irq_late_init); + +#endif /* CONFIG_PPC_MERGE */ #ifdef CONFIG_PCI_MSI int pci_enable_msi(struct pci_dev * pdev) diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 4cf0b971976..7e98e778b52 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -28,6 +28,7 @@ static struct legacy_serial_info { struct device_node *np; unsigned int speed; unsigned int clock; + int irq_check_parent; phys_addr_t taddr; } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS]; static unsigned int legacy_serial_count; @@ -36,7 +37,7 @@ static int legacy_serial_console = -1; static int __init add_legacy_port(struct device_node *np, int want_index, int iotype, phys_addr_t base, phys_addr_t taddr, unsigned long irq, - upf_t flags) + upf_t flags, int irq_check_parent) { u32 *clk, *spd, clock = BASE_BAUD * 16; int index; @@ -68,7 +69,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index, if (legacy_serial_infos[index].np != 0) { /* if we still have some room, move it, else override */ if (legacy_serial_count < MAX_LEGACY_SERIAL_PORTS) { - printk(KERN_INFO "Moved legacy port %d -> %d\n", + printk(KERN_DEBUG "Moved legacy port %d -> %d\n", index, legacy_serial_count); legacy_serial_ports[legacy_serial_count] = legacy_serial_ports[index]; @@ -76,7 +77,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index, legacy_serial_infos[index]; legacy_serial_count++; } else { - printk(KERN_INFO "Replacing legacy port %d\n", index); + printk(KERN_DEBUG "Replacing legacy port %d\n", index); } } @@ -95,10 +96,11 @@ static int __init add_legacy_port(struct device_node *np, int want_index, legacy_serial_infos[index].np = of_node_get(np); legacy_serial_infos[index].clock = clock; legacy_serial_infos[index].speed = spd ? *spd : 0; + legacy_serial_infos[index].irq_check_parent = irq_check_parent; - printk(KERN_INFO "Found legacy serial port %d for %s\n", + printk(KERN_DEBUG "Found legacy serial port %d for %s\n", index, np->full_name); - printk(KERN_INFO " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n", + printk(KERN_DEBUG " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n", (iotype == UPIO_PORT) ? "port" : "mem", (unsigned long long)base, (unsigned long long)taddr, irq, legacy_serial_ports[index].uartclk, @@ -126,11 +128,13 @@ static int __init add_legacy_soc_port(struct device_node *np, return -1; addr = of_translate_address(soc_dev, addrp); + if (addr == OF_BAD_ADDR) + return -1; /* Add port, irq will be dealt with later. We passed a translated * IO port value. It will be fixed up later along with the irq */ - return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags); + return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags, 0); } static int __init add_legacy_isa_port(struct device_node *np, @@ -141,6 +145,8 @@ static int __init add_legacy_isa_port(struct device_node *np, int index = -1; phys_addr_t taddr; + DBG(" -> add_legacy_isa_port(%s)\n", np->full_name); + /* Get the ISA port number */ reg = (u32 *)get_property(np, "reg", NULL); if (reg == NULL) @@ -161,9 +167,12 @@ static int __init add_legacy_isa_port(struct device_node *np, /* Translate ISA address */ taddr = of_translate_address(np, reg); + if (taddr == OF_BAD_ADDR) + return -1; /* Add port, irq will be dealt with later */ - return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, NO_IRQ, UPF_BOOT_AUTOCONF); + return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, + NO_IRQ, UPF_BOOT_AUTOCONF, 0); } @@ -176,6 +185,8 @@ static int __init add_legacy_pci_port(struct device_node *np, unsigned int flags; int iotype, index = -1, lindex = 0; + DBG(" -> add_legacy_pci_port(%s)\n", np->full_name); + /* We only support ports that have a clock frequency properly * encoded in the device-tree (that is have an fcode). Anything * else can't be used that early and will be normally probed by @@ -194,6 +205,8 @@ static int __init add_legacy_pci_port(struct device_node *np, /* We only support BAR 0 for now */ iotype = (flags & IORESOURCE_MEM) ? UPIO_MEM : UPIO_PORT; addr = of_translate_address(pci_dev, addrp); + if (addr == OF_BAD_ADDR) + return -1; /* Set the IO base to the same as the translated address for MMIO, * or to the domain local IO base for PIO (it will be fixed up later) @@ -231,7 +244,8 @@ static int __init add_legacy_pci_port(struct device_node *np, /* Add port, irq will be dealt with later. We passed a translated * IO port value. It will be fixed up later along with the irq */ - return add_legacy_port(np, index, iotype, base, addr, NO_IRQ, UPF_BOOT_AUTOCONF); + return add_legacy_port(np, index, iotype, base, addr, NO_IRQ, + UPF_BOOT_AUTOCONF, np != pci_dev); } #endif @@ -362,27 +376,22 @@ static void __init fixup_port_irq(int index, struct device_node *np, struct plat_serial8250_port *port) { + unsigned int virq; + DBG("fixup_port_irq(%d)\n", index); - /* Check for interrupts in that node */ - if (np->n_intrs > 0) { - port->irq = np->intrs[0].line; - DBG(" port %d (%s), irq=%d\n", - index, np->full_name, port->irq); - return; + virq = irq_of_parse_and_map(np, 0); + if (virq == NO_IRQ && legacy_serial_infos[index].irq_check_parent) { + np = of_get_parent(np); + if (np == NULL) + return; + virq = irq_of_parse_and_map(np, 0); + of_node_put(np); } - - /* Check for interrupts in the parent */ - np = of_get_parent(np); - if (np == NULL) + if (virq == NO_IRQ) return; - if (np->n_intrs > 0) { - port->irq = np->intrs[0].line; - DBG(" port %d (%s), irq=%d\n", - index, np->full_name, port->irq); - } - of_node_put(np); + port->irq = virq; } static void __init fixup_port_pio(int index, diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 0c3c70d115c..bfb407fc1aa 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -51,12 +51,14 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call___do_IRQ) +_GLOBAL(call_handle_irq) + ld r8,0(r7) mflr r0 std r0,16(r1) - stdu r1,THREAD_SIZE-112(r5) - mr r1,r5 - bl .__do_IRQ + mtctr r8 + stdu r1,THREAD_SIZE-112(r6) + mr r1,r6 + bctrl ld r1,0(r1) ld r0,16(r1) mtlr r0 diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 1333335c474..898dae8ab6d 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1404,6 +1404,43 @@ pcibios_update_irq(struct pci_dev *dev, int irq) /* XXX FIXME - update OF device tree node interrupt property */ } +#ifdef CONFIG_PPC_MERGE +/* XXX This is a copy of the ppc64 version. This is temporary until we start + * merging the 2 PCI layers + */ +/* + * Reads the interrupt pin to determine if interrupt is use by card. + * If the interrupt is used, then gets the interrupt line from the + * openfirmware and sets it in the pci_dev and pci_config line. + */ +int pci_read_irq_line(struct pci_dev *pci_dev) +{ + struct of_irq oirq; + unsigned int virq; + + DBG("Try to map irq for %s...\n", pci_name(pci_dev)); + + if (of_irq_map_pci(pci_dev, &oirq)) { + DBG(" -> failed !\n"); + return -1; + } + + DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.controller->full_name); + + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); + if(virq == NO_IRQ) { + DBG(" -> failed to map !\n"); + return -1; + } + pci_dev->irq = virq; + pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq); + + return 0; +} +EXPORT_SYMBOL(pci_read_irq_line); +#endif /* CONFIG_PPC_MERGE */ + int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index bea8451fb57..efc0b5559ee 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -398,12 +398,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, } else { dev->hdr_type = PCI_HEADER_TYPE_NORMAL; dev->rom_base_reg = PCI_ROM_ADDRESS; + /* Maybe do a default OF mapping here */ dev->irq = NO_IRQ; - if (node->n_intrs > 0) { - dev->irq = node->intrs[0].line; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - dev->irq); - } } pci_parse_of_addrs(node, dev); @@ -1288,23 +1284,26 @@ EXPORT_SYMBOL(pcibios_fixup_bus); */ int pci_read_irq_line(struct pci_dev *pci_dev) { - u8 intpin; - struct device_node *node; - - pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin); - if (intpin == 0) - return 0; + struct of_irq oirq; + unsigned int virq; - node = pci_device_to_OF_node(pci_dev); - if (node == NULL) - return -1; + DBG("Try to map irq for %s...\n", pci_name(pci_dev)); - if (node->n_intrs == 0) + if (of_irq_map_pci(pci_dev, &oirq)) { + DBG(" -> failed !\n"); return -1; + } - pci_dev->irq = node->intrs[0].line; + DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.controller->full_name); - pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq); + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); + if(virq == NO_IRQ) { + DBG(" -> failed to map !\n"); + return -1; + } + pci_dev->irq = virq; + pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq); return 0; } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 4c524cb5218..a1787ffb631 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -30,6 +30,7 @@ #include <linux/module.h> #include <linux/kexec.h> #include <linux/debugfs.h> +#include <linux/irq.h> #include <asm/prom.h> #include <asm/rtas.h> @@ -86,424 +87,6 @@ static DEFINE_RWLOCK(devtree_lock); /* export that to outside world */ struct device_node *of_chosen; -struct device_node *dflt_interrupt_controller; -int num_interrupt_controllers; - -/* - * Wrapper for allocating memory for various data that needs to be - * attached to device nodes as they are processed at boot or when - * added to the device tree later (e.g. DLPAR). At boot there is - * already a region reserved so we just increment *mem_start by size; - * otherwise we call kmalloc. - */ -static void * prom_alloc(unsigned long size, unsigned long *mem_start) -{ - unsigned long tmp; - - if (!mem_start) - return kmalloc(size, GFP_KERNEL); - - tmp = *mem_start; - *mem_start += size; - return (void *)tmp; -} - -/* - * Find the device_node with a given phandle. - */ -static struct device_node * find_phandle(phandle ph) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->linux_phandle == ph) - return np; - return NULL; -} - -/* - * Find the interrupt parent of a node. - */ -static struct device_node * __devinit intr_parent(struct device_node *p) -{ - phandle *parp; - - parp = (phandle *) get_property(p, "interrupt-parent", NULL); - if (parp == NULL) - return p->parent; - p = find_phandle(*parp); - if (p != NULL) - return p; - /* - * On a powermac booted with BootX, we don't get to know the - * phandles for any nodes, so find_phandle will return NULL. - * Fortunately these machines only have one interrupt controller - * so there isn't in fact any ambiguity. -- paulus - */ - if (num_interrupt_controllers == 1) - p = dflt_interrupt_controller; - return p; -} - -/* - * Find out the size of each entry of the interrupts property - * for a node. - */ -int __devinit prom_n_intr_cells(struct device_node *np) -{ - struct device_node *p; - unsigned int *icp; - - for (p = np; (p = intr_parent(p)) != NULL; ) { - icp = (unsigned int *) - get_property(p, "#interrupt-cells", NULL); - if (icp != NULL) - return *icp; - if (get_property(p, "interrupt-controller", NULL) != NULL - || get_property(p, "interrupt-map", NULL) != NULL) { - printk("oops, node %s doesn't have #interrupt-cells\n", - p->full_name); - return 1; - } - } -#ifdef DEBUG_IRQ - printk("prom_n_intr_cells failed for %s\n", np->full_name); -#endif - return 1; -} - -/* - * Map an interrupt from a device up to the platform interrupt - * descriptor. - */ -static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, - struct device_node *np, unsigned int *ints, - int nintrc) -{ - struct device_node *p, *ipar; - unsigned int *imap, *imask, *ip; - int i, imaplen, match; - int newintrc = 0, newaddrc = 0; - unsigned int *reg; - int naddrc; - - reg = (unsigned int *) get_property(np, "reg", NULL); - naddrc = prom_n_addr_cells(np); - p = intr_parent(np); - while (p != NULL) { - if (get_property(p, "interrupt-controller", NULL) != NULL) - /* this node is an interrupt controller, stop here */ - break; - imap = (unsigned int *) - get_property(p, "interrupt-map", &imaplen); - if (imap == NULL) { - p = intr_parent(p); - continue; - } - imask = (unsigned int *) - get_property(p, "interrupt-map-mask", NULL); - if (imask == NULL) { - printk("oops, %s has interrupt-map but no mask\n", - p->full_name); - return 0; - } - imaplen /= sizeof(unsigned int); - match = 0; - ipar = NULL; - while (imaplen > 0 && !match) { - /* check the child-interrupt field */ - match = 1; - for (i = 0; i < naddrc && match; ++i) - match = ((reg[i] ^ imap[i]) & imask[i]) == 0; - for (; i < naddrc + nintrc && match; ++i) - match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; - imap += naddrc + nintrc; - imaplen -= naddrc + nintrc; - /* grab the interrupt parent */ - ipar = find_phandle((phandle) *imap++); - --imaplen; - if (ipar == NULL && num_interrupt_controllers == 1) - /* cope with BootX not giving us phandles */ - ipar = dflt_interrupt_controller; - if (ipar == NULL) { - printk("oops, no int parent %x in map of %s\n", - imap[-1], p->full_name); - return 0; - } - /* find the parent's # addr and intr cells */ - ip = (unsigned int *) - get_property(ipar, "#interrupt-cells", NULL); - if (ip == NULL) { - printk("oops, no #interrupt-cells on %s\n", - ipar->full_name); - return 0; - } - newintrc = *ip; - ip = (unsigned int *) - get_property(ipar, "#address-cells", NULL); - newaddrc = (ip == NULL)? 0: *ip; - imap += newaddrc + newintrc; - imaplen -= newaddrc + newintrc; - } - if (imaplen < 0) { - printk("oops, error decoding int-map on %s, len=%d\n", - p->full_name, imaplen); - return 0; - } - if (!match) { -#ifdef DEBUG_IRQ - printk("oops, no match in %s int-map for %s\n", - p->full_name, np->full_name); -#endif - return 0; - } - p = ipar; - naddrc = newaddrc; - nintrc = newintrc; - ints = imap - nintrc; - reg = ints - naddrc; - } - if (p == NULL) { -#ifdef DEBUG_IRQ - printk("hmmm, int tree for %s doesn't have ctrler\n", - np->full_name); -#endif - return 0; - } - *irq = ints; - *ictrler = p; - return nintrc; -} - -static unsigned char map_isa_senses[4] = { - IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, - IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE, - IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE, - IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE -}; - -static unsigned char map_mpic_senses[4] = { - IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE, - IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, - /* 2 seems to be used for the 8259 cascade... */ - IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE, - IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE, -}; - -static int __devinit finish_node_interrupts(struct device_node *np, - unsigned long *mem_start, - int measure_only) -{ - unsigned int *ints; - int intlen, intrcells, intrcount; - int i, j, n, sense; - unsigned int *irq, virq; - struct device_node *ic; - int trace = 0; - - //#define TRACE(fmt...) do { if (trace) { printk(fmt); mdelay(1000); } } while(0) -#define TRACE(fmt...) - - if (!strcmp(np->name, "smu-doorbell")) - trace = 1; - - TRACE("Finishing SMU doorbell ! num_interrupt_controllers = %d\n", - num_interrupt_controllers); - - if (num_interrupt_controllers == 0) { - /* - * Old machines just have a list of interrupt numbers - * and no interrupt-controller nodes. - */ - ints = (unsigned int *) get_property(np, "AAPL,interrupts", - &intlen); - /* XXX old interpret_pci_props looked in parent too */ - /* XXX old interpret_macio_props looked for interrupts - before AAPL,interrupts */ - if (ints == NULL) - ints = (unsigned int *) get_property(np, "interrupts", - &intlen); - if (ints == NULL) - return 0; - - np->n_intrs = intlen / sizeof(unsigned int); - np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]), - mem_start); - if (!np->intrs) - return -ENOMEM; - if (measure_only) - return 0; - - for (i = 0; i < np->n_intrs; ++i) { - np->intrs[i].line = *ints++; - np->intrs[i].sense = IRQ_SENSE_LEVEL - | IRQ_POLARITY_NEGATIVE; - } - return 0; - } - - ints = (unsigned int *) get_property(np, "interrupts", &intlen); - TRACE("ints=%p, intlen=%d\n", ints, intlen); - if (ints == NULL) - return 0; - intrcells = prom_n_intr_cells(np); - intlen /= intrcells * sizeof(unsigned int); - TRACE("intrcells=%d, new intlen=%d\n", intrcells, intlen); - np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); - if (!np->intrs) - return -ENOMEM; - - if (measure_only) - return 0; - - intrcount = 0; - for (i = 0; i < intlen; ++i, ints += intrcells) { - n = map_interrupt(&irq, &ic, np, ints, intrcells); - TRACE("map, irq=%d, ic=%p, n=%d\n", irq, ic, n); - if (n <= 0) - continue; - - /* don't map IRQ numbers under a cascaded 8259 controller */ - if (ic && device_is_compatible(ic, "chrp,iic")) { - np->intrs[intrcount].line = irq[0]; - sense = (n > 1)? (irq[1] & 3): 3; - np->intrs[intrcount].sense = map_isa_senses[sense]; - } else { - virq = virt_irq_create_mapping(irq[0]); - TRACE("virq=%d\n", virq); -#ifdef CONFIG_PPC64 - if (virq == NO_IRQ) { - printk(KERN_CRIT "Could not allocate interrupt" - " number for %s\n", np->full_name); - continue; - } -#endif - np->intrs[intrcount].line = irq_offset_up(virq); - sense = (n > 1)? (irq[1] & 3): 1; - - /* Apple uses bits in there in a different way, let's - * only keep the real sense bit on macs - */ - if (machine_is(powermac)) - sense &= 0x1; - np->intrs[intrcount].sense = map_mpic_senses[sense]; - } - -#ifdef CONFIG_PPC64 - /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ - if (machine_is(powermac) && ic && ic->parent) { - char *name = get_property(ic->parent, "name", NULL); - if (name && !strcmp(name, "u3")) - np->intrs[intrcount].line += 128; - else if (!(name && (!strcmp(name, "mac-io") || - !strcmp(name, "u4")))) - /* ignore other cascaded controllers, such as - the k2-sata-root */ - break; - } -#endif /* CONFIG_PPC64 */ - if (n > 2) { - printk("hmmm, got %d intr cells for %s:", n, - np->full_name); - for (j = 0; j < n; ++j) - printk(" %d", irq[j]); - printk("\n"); - } - ++intrcount; - } - np->n_intrs = intrcount; - - return 0; -} - -static int __devinit finish_node(struct device_node *np, - unsigned long *mem_start, - int measure_only) -{ - struct device_node *child; - int rc = 0; - - rc = finish_node_interrupts(np, mem_start, measure_only); - if (rc) - goto out; - - for (child = np->child; child != NULL; child = child->sibling) { - rc = finish_node(child, mem_start, measure_only); - if (rc) - goto out; - } -out: - return rc; -} - -static void __init scan_interrupt_controllers(void) -{ - struct device_node *np; - int n = 0; - char *name, *ic; - int iclen; - - for (np = allnodes; np != NULL; np = np->allnext) { - ic = get_property(np, "interrupt-controller", &iclen); - name = get_property(np, "name", NULL); - /* checking iclen makes sure we don't get a false - match on /chosen.interrupt_controller */ - if ((name != NULL - && strcmp(name, "interrupt-controller") == 0) - || (ic != NULL && iclen == 0 - && strcmp(name, "AppleKiwi"))) { - if (n == 0) - dflt_interrupt_controller = np; - ++n; - } - } - num_interrupt_controllers = n; -} - -/** - * finish_device_tree is called once things are running normally - * (i.e. with text and data mapped to the address they were linked at). - * It traverses the device tree and fills in some of the additional, - * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt - * mapping is also initialized at this point. - */ -void __init finish_device_tree(void) -{ - unsigned long start, end, size = 0; - - DBG(" -> finish_device_tree\n"); - -#ifdef CONFIG_PPC64 - /* Initialize virtual IRQ map */ - virt_irq_init(); -#endif - scan_interrupt_controllers(); - - /* - * Finish device-tree (pre-parsing some properties etc...) - * We do this in 2 passes. One with "measure_only" set, which - * will only measure the amount of memory needed, then we can - * allocate that memory, and call finish_node again. However, - * we must be careful as most routines will fail nowadays when - * prom_alloc() returns 0, so we must make sure our first pass - * doesn't start at 0. We pre-initialize size to 16 for that - * reason and then remove those additional 16 bytes - */ - size = 16; - finish_node(allnodes, &size, 1); - size -= 16; - - if (0 == size) - end = start = 0; - else - end = start = (unsigned long)__va(lmb_alloc(size, 128)); - - finish_node(allnodes, &end, 0); - BUG_ON(end != start + size); - - DBG(" <- finish_device_tree\n"); -} - static inline char *find_flat_dt_string(u32 offset) { return ((char *)initial_boot_params) + @@ -1389,27 +972,6 @@ prom_n_size_cells(struct device_node* np) EXPORT_SYMBOL(prom_n_size_cells); /** - * Work out the sense (active-low level / active-high edge) - * of each interrupt from the device tree. - */ -void __init prom_get_irq_senses(unsigned char *senses, int off, int max) -{ - struct device_node *np; - int i, j; - - /* default to level-triggered */ - memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off); - - for (np = allnodes; np != 0; np = np->allnext) { - for (j = 0; j < np->n_intrs; j++) { - i = np->intrs[j].line; - if (i >= off && i < max) - senses[i-off] = np->intrs[j].sense; - } - } -} - -/** * Construct and return a list of the device_nodes with a given name. */ struct device_node *find_devices(const char *name) @@ -1808,7 +1370,6 @@ static void of_node_release(struct kref *kref) node->deadprops = NULL; } } - kfree(node->intrs); kfree(node->full_name); kfree(node->data); kfree(node); @@ -1881,13 +1442,7 @@ void of_detach_node(const struct device_node *np) #ifdef CONFIG_PPC_PSERIES /* * Fix up the uninitialized fields in a new device node: - * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields - * - * A lot of boot-time code is duplicated here, because functions such - * as finish_node_interrupts, interpret_pci_props, etc. cannot use the - * slab allocator. - * - * This should probably be split up into smaller chunks. + * name, type and pci-specific fields */ static int of_finish_dynamic_node(struct device_node *node) @@ -1928,8 +1483,6 @@ static int prom_reconfig_notifier(struct notifier_block *nb, switch (action) { case PSERIES_RECONFIG_ADD: err = of_finish_dynamic_node(node); - if (!err) - finish_node(node, NULL, 0); if (err < 0) { printk(KERN_ERR "finish_node returned %d\n", err); err = NOTIFY_BAD; @@ -1975,8 +1528,7 @@ struct property *of_find_property(struct device_node *np, const char *name, * Find a property with a given name for a given node * and return the value. */ -unsigned char *get_property(struct device_node *np, const char *name, - int *lenp) +void *get_property(struct device_node *np, const char *name, int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 1e95a9f8cda..ebd501a59ab 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1990,12 +1990,22 @@ static void __init flatten_device_tree(void) static void __init fixup_device_tree_maple(void) { phandle isa; + u32 rloc = 0x01002000; /* IO space; PCI device = 4 */ u32 isa_ranges[6]; - - isa = call_prom("finddevice", 1, 1, ADDR("/ht@0/isa@4")); + char *name; + + name = "/ht@0/isa@4"; + isa = call_prom("finddevice", 1, 1, ADDR(name)); + if (!PHANDLE_VALID(isa)) { + name = "/ht@0/isa@6"; + isa = call_prom("finddevice", 1, 1, ADDR(name)); + rloc = 0x01003000; /* IO space; PCI device = 6 */ + } if (!PHANDLE_VALID(isa)) return; + if (prom_getproplen(isa, "ranges") != 12) + return; if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges)) == PROM_ERROR) return; @@ -2005,15 +2015,15 @@ static void __init fixup_device_tree_maple(void) isa_ranges[2] != 0x00010000) return; - prom_printf("fixing up bogus ISA range on Maple...\n"); + prom_printf("Fixing up bogus ISA range on Maple/Apache...\n"); isa_ranges[0] = 0x1; isa_ranges[1] = 0x0; - isa_ranges[2] = 0x01002000; /* IO space; PCI device = 4 */ + isa_ranges[2] = rloc; isa_ranges[3] = 0x0; isa_ranges[4] = 0x0; isa_ranges[5] = 0x00010000; - prom_setprop(isa, "/ht@0/isa@4", "ranges", + prom_setprop(isa, name, "ranges", isa_ranges, sizeof(isa_ranges)); } #else diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 45df420383c..21009b1f786 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -38,14 +38,6 @@ static void of_dump_addr(const char *s, u32 *addr, int na) static void of_dump_addr(const char *s, u32 *addr, int na) { } #endif -/* Read a big address */ -static inline u64 of_read_addr(u32 *cell, int size) -{ - u64 r = 0; - while (size--) - r = (r << 32) | *(cell++); - return r; -} /* Callbacks for bus specific translators */ struct of_bus { @@ -77,9 +69,9 @@ static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) { u64 cp, s, da; - cp = of_read_addr(range, na); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr, na); + cp = of_read_number(range, na); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr, na); DBG("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); @@ -91,7 +83,7 @@ static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) static int of_bus_default_translate(u32 *addr, u64 offset, int na) { - u64 a = of_read_addr(addr, na); + u64 a = of_read_number(addr, na); memset(addr, 0, na * 4); a += offset; if (na > 1) @@ -135,9 +127,9 @@ static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) return OF_BAD_ADDR; /* Read address values, skipping high cell */ - cp = of_read_addr(range + 1, na - 1); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr + 1, na - 1); + cp = of_read_number(range + 1, na - 1); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr + 1, na - 1); DBG("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); @@ -195,9 +187,9 @@ static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna) return OF_BAD_ADDR; /* Read address values, skipping high cell */ - cp = of_read_addr(range + 1, na - 1); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr + 1, na - 1); + cp = of_read_number(range + 1, na - 1); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr + 1, na - 1); DBG("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); @@ -295,7 +287,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, */ ranges = (u32 *)get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { - offset = of_read_addr(addr, na); + offset = of_read_number(addr, na); memset(addr, 0, pna * 4); DBG("OF: no ranges, 1:1 translation\n"); goto finish; @@ -378,7 +370,7 @@ u64 of_translate_address(struct device_node *dev, u32 *in_addr) /* If root, we have finished */ if (parent == NULL) { DBG("OF: reached root node\n"); - result = of_read_addr(addr, na); + result = of_read_number(addr, na); break; } @@ -442,7 +434,7 @@ u32 *of_get_address(struct device_node *dev, int index, u64 *size, for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) if (i == index) { if (size) - *size = of_read_addr(prop + na, ns); + *size = of_read_number(prop + na, ns); if (flags) *flags = bus->get_flags(prop); return prop; @@ -484,7 +476,7 @@ u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { if (size) - *size = of_read_addr(prop + na, ns); + *size = of_read_number(prop + na, ns); if (flags) *flags = bus->get_flags(prop); return prop; @@ -565,11 +557,414 @@ void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, prop = get_property(dn, "#address-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); - *phys = of_read_addr(dma_window, cells); + *phys = of_read_number(dma_window, cells); dma_window += cells; prop = get_property(dn, "ibm,#dma-size-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); - *size = of_read_addr(dma_window, cells); + *size = of_read_number(dma_window, cells); +} + +/* + * Interrupt remapper + */ + +static unsigned int of_irq_workarounds; +static struct device_node *of_irq_dflt_pic; + +static struct device_node *of_irq_find_parent(struct device_node *child) +{ + struct device_node *p; + phandle *parp; + + if (!of_node_get(child)) + return NULL; + + do { + parp = (phandle *)get_property(child, "interrupt-parent", NULL); + if (parp == NULL) + p = of_get_parent(child); + else { + if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) + p = of_node_get(of_irq_dflt_pic); + else + p = of_find_node_by_phandle(*parp); + } + of_node_put(child); + child = p; + } while (p && get_property(p, "#interrupt-cells", NULL) == NULL); + + return p; +} + +static u8 of_irq_pci_swizzle(u8 slot, u8 pin) +{ + return (((pin - 1) + slot) % 4) + 1; } + +/* This doesn't need to be called if you don't have any special workaround + * flags to pass + */ +void of_irq_map_init(unsigned int flags) +{ + of_irq_workarounds = flags; + + /* OldWorld, don't bother looking at other things */ + if (flags & OF_IMAP_OLDWORLD_MAC) + return; + + /* If we don't have phandles, let's try to locate a default interrupt + * controller (happens when booting with BootX). We do a first match + * here, hopefully, that only ever happens on machines with one + * controller. + */ + if (flags & OF_IMAP_NO_PHANDLE) { + struct device_node *np; + + for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) { + if (get_property(np, "interrupt-controller", NULL) + == NULL) + continue; + /* Skip /chosen/interrupt-controller */ + if (strcmp(np->name, "chosen") == 0) + continue; + /* It seems like at least one person on this planet wants + * to use BootX on a machine with an AppleKiwi controller + * which happens to pretend to be an interrupt + * controller too. + */ + if (strcmp(np->name, "AppleKiwi") == 0) + continue; + /* I think we found one ! */ + of_irq_dflt_pic = np; + break; + } + } + +} + +int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, + struct of_irq *out_irq) +{ + struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; + u32 *tmp, *imap, *imask; + u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; + int imaplen, match, i; + + ipar = of_node_get(parent); + + /* First get the #interrupt-cells property of the current cursor + * that tells us how to interpret the passed-in intspec. If there + * is none, we are nice and just walk up the tree + */ + do { + tmp = (u32 *)get_property(ipar, "#interrupt-cells", NULL); + if (tmp != NULL) { + intsize = *tmp; + break; + } + tnode = ipar; + ipar = of_irq_find_parent(ipar); + of_node_put(tnode); + } while (ipar); + if (ipar == NULL) { + DBG(" -> no parent found !\n"); + goto fail; + } + + DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); + + /* Look for this #address-cells. We have to implement the old linux + * trick of looking for the parent here as some device-trees rely on it + */ + old = of_node_get(ipar); + do { + tmp = (u32 *)get_property(old, "#address-cells", NULL); + tnode = of_get_parent(old); + of_node_put(old); + old = tnode; + } while(old && tmp == NULL); + of_node_put(old); + old = NULL; + addrsize = (tmp == NULL) ? 2 : *tmp; + + DBG(" -> addrsize=%d\n", addrsize); + + /* Now start the actual "proper" walk of the interrupt tree */ + while (ipar != NULL) { + /* Now check if cursor is an interrupt-controller and if it is + * then we are done + */ + if (get_property(ipar, "interrupt-controller", NULL) != NULL) { + DBG(" -> got it !\n"); + memcpy(out_irq->specifier, intspec, + intsize * sizeof(u32)); + out_irq->size = intsize; + out_irq->controller = ipar; + of_node_put(old); + return 0; + } + + /* Now look for an interrupt-map */ + imap = (u32 *)get_property(ipar, "interrupt-map", &imaplen); + /* No interrupt map, check for an interrupt parent */ + if (imap == NULL) { + DBG(" -> no map, getting parent\n"); + newpar = of_irq_find_parent(ipar); + goto skiplevel; + } + imaplen /= sizeof(u32); + + /* Look for a mask */ + imask = (u32 *)get_property(ipar, "interrupt-map-mask", NULL); + + /* If we were passed no "reg" property and we attempt to parse + * an interrupt-map, then #address-cells must be 0. + * Fail if it's not. + */ + if (addr == NULL && addrsize != 0) { + DBG(" -> no reg passed in when needed !\n"); + goto fail; + } + + /* Parse interrupt-map */ + match = 0; + while (imaplen > (addrsize + intsize + 1) && !match) { + /* Compare specifiers */ + match = 1; + for (i = 0; i < addrsize && match; ++i) { + u32 mask = imask ? imask[i] : 0xffffffffu; + match = ((addr[i] ^ imap[i]) & mask) == 0; + } + for (; i < (addrsize + intsize) && match; ++i) { + u32 mask = imask ? imask[i] : 0xffffffffu; + match = + ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; + } + imap += addrsize + intsize; + imaplen -= addrsize + intsize; + + DBG(" -> match=%d (imaplen=%d)\n", match, imaplen); + + /* Get the interrupt parent */ + if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) + newpar = of_node_get(of_irq_dflt_pic); + else + newpar = of_find_node_by_phandle((phandle)*imap); + imap++; + --imaplen; + + /* Check if not found */ + if (newpar == NULL) { + DBG(" -> imap parent not found !\n"); + goto fail; + } + + /* Get #interrupt-cells and #address-cells of new + * parent + */ + tmp = (u32 *)get_property(newpar, "#interrupt-cells", + NULL); + if (tmp == NULL) { + DBG(" -> parent lacks #interrupt-cells !\n"); + goto fail; + } + newintsize = *tmp; + tmp = (u32 *)get_property(newpar, "#address-cells", + NULL); + newaddrsize = (tmp == NULL) ? 0 : *tmp; + + DBG(" -> newintsize=%d, newaddrsize=%d\n", + newintsize, newaddrsize); + + /* Check for malformed properties */ + if (imaplen < (newaddrsize + newintsize)) + goto fail; + + imap += newaddrsize + newintsize; + imaplen -= newaddrsize + newintsize; + + DBG(" -> imaplen=%d\n", imaplen); + } + if (!match) + goto fail; + + of_node_put(old); + old = of_node_get(newpar); + addrsize = newaddrsize; + intsize = newintsize; + intspec = imap - intsize; + addr = intspec - addrsize; + + skiplevel: + /* Iterate again with new parent */ + DBG(" -> new parent: %s\n", newpar ? newpar->full_name : "<>"); + of_node_put(ipar); + ipar = newpar; + newpar = NULL; + } + fail: + of_node_put(ipar); + of_node_put(old); + of_node_put(newpar); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(of_irq_map_raw); + +#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) +static int of_irq_map_oldworld(struct device_node *device, int index, + struct of_irq *out_irq) +{ + u32 *ints; + int intlen; + + /* + * Old machines just have a list of interrupt numbers + * and no interrupt-controller nodes. + */ + ints = (u32 *) get_property(device, "AAPL,interrupts", &intlen); + if (ints == NULL) + return -EINVAL; + intlen /= sizeof(u32); + + if (index >= intlen) + return -EINVAL; + + out_irq->controller = NULL; + out_irq->specifier[0] = ints[index]; + out_irq->size = 1; + + return 0; +} +#else /* defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) */ +static int of_irq_map_oldworld(struct device_node *device, int index, + struct of_irq *out_irq) +{ + return -EINVAL; +} +#endif /* !(defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)) */ + +int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) +{ + struct device_node *p; + u32 *intspec, *tmp, intsize, intlen, *addr; + int res; + + DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index); + + /* OldWorld mac stuff is "special", handle out of line */ + if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) + return of_irq_map_oldworld(device, index, out_irq); + + /* Get the interrupts property */ + intspec = (u32 *)get_property(device, "interrupts", &intlen); + if (intspec == NULL) + return -EINVAL; + intlen /= sizeof(u32); + + /* Get the reg property (if any) */ + addr = (u32 *)get_property(device, "reg", NULL); + + /* Look for the interrupt parent. */ + p = of_irq_find_parent(device); + if (p == NULL) + return -EINVAL; + + /* Get size of interrupt specifier */ + tmp = (u32 *)get_property(p, "#interrupt-cells", NULL); + if (tmp == NULL) { + of_node_put(p); + return -EINVAL; + } + intsize = *tmp; + + /* Check index */ + if (index * intsize >= intlen) + return -EINVAL; + + /* Get new specifier and map it */ + res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq); + of_node_put(p); + return res; +} +EXPORT_SYMBOL_GPL(of_irq_map_one); + +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) +{ + struct device_node *dn, *ppnode; + struct pci_dev *ppdev; + u32 lspec; + u32 laddr[3]; + u8 pin; + int rc; + + /* Check if we have a device node, if yes, fallback to standard OF + * parsing + */ + dn = pci_device_to_OF_node(pdev); + if (dn) + return of_irq_map_one(dn, 0, out_irq); + + /* Ok, we don't, time to have fun. Let's start by building up an + * interrupt spec. we assume #interrupt-cells is 1, which is standard + * for PCI. If you do different, then don't use that routine. + */ + rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (rc != 0) + return rc; + /* No pin, exit */ + if (pin == 0) + return -ENODEV; + + /* Now we walk up the PCI tree */ + lspec = pin; + for (;;) { + /* Get the pci_dev of our parent */ + ppdev = pdev->bus->self; + + /* Ouch, it's a host bridge... */ + if (ppdev == NULL) { +#ifdef CONFIG_PPC64 + ppnode = pci_bus_to_OF_node(pdev->bus); +#else + struct pci_controller *host; + host = pci_bus_to_host(pdev->bus); + ppnode = host ? host->arch_data : NULL; +#endif + /* No node for host bridge ? give up */ + if (ppnode == NULL) + return -EINVAL; + } else + /* We found a P2P bridge, check if it has a node */ + ppnode = pci_device_to_OF_node(ppdev); + + /* Ok, we have found a parent with a device-node, hand over to + * the OF parsing code. + * We build a unit address from the linux device to be used for + * resolution. Note that we use the linux bus number which may + * not match your firmware bus numbering. + * Fortunately, in most cases, interrupt-map-mask doesn't include + * the bus number as part of the matching. + * You should still be careful about that though if you intend + * to rely on this function (you ship a firmware that doesn't + * create device nodes for all PCI devices). + */ + if (ppnode) + break; + + /* We can only get here if we hit a P2P bridge with no node, + * let's do standard swizzling and try again + */ + lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); + pdev = ppdev; + } + + laddr[0] = (pdev->bus->number << 16) + | (pdev->devfn << 8); + laddr[1] = laddr[2] = 0; + return of_irq_map_raw(ppnode, &lspec, laddr, out_irq); +} +EXPORT_SYMBOL_GPL(of_irq_map_pci); + diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 6eb7e49b394..cda02265732 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -297,19 +297,9 @@ unsigned long __init find_and_init_phbs(void) struct device_node *node; struct pci_controller *phb; unsigned int index; - unsigned int root_size_cells = 0; - unsigned int *opprop = NULL; struct device_node *root = of_find_node_by_path("/"); - if (ppc64_interrupt_controller == IC_OPEN_PIC) { - opprop = (unsigned int *)get_property(root, - "platform-open-pic", NULL); - } - - root_size_cells = prom_n_size_cells(root); - index = 0; - for (node = of_get_next_child(root, NULL); node != NULL; node = of_get_next_child(root, node)) { @@ -324,13 +314,6 @@ unsigned long __init find_and_init_phbs(void) setup_phb(node, phb); pci_process_bridge_OF_ranges(phb, node, 0); pci_setup_phb_io(phb, index == 0); -#ifdef CONFIG_PPC_PSERIES - /* XXX This code need serious fixing ... --BenH */ - if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) { - int addr = root_size_cells * (index + 2) - 1; - mpic_assign_isu(pSeries_mpic, index, opprop[addr]); - } -#endif index++; } diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index ba7cd50d820..e0df2ba1ab9 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -51,7 +51,6 @@ extern void bootx_init(unsigned long r4, unsigned long phys); -boot_infos_t *boot_infos; struct ide_machdep_calls ppc_ide_md; int boot_cpuid; @@ -240,7 +239,6 @@ void __init setup_arch(char **cmdline_p) ppc_md.init_early(); find_legacy_serial_ports(); - finish_device_tree(); smp_setup_cpu_maps(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ac7276c4068..fd1785e4c9b 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -361,12 +361,15 @@ void __init setup_system(void) /* * Fill the ppc64_caches & systemcfg structures with informations - * retrieved from the device-tree. Need to be called before - * finish_device_tree() since the later requires some of the - * informations filled up here to properly parse the interrupt tree. + * retrieved from the device-tree. */ initialize_cache_info(); + /* + * Initialize irq remapping subsystem + */ + irq_early_init(); + #ifdef CONFIG_PPC_RTAS /* * Initialize RTAS if available @@ -394,12 +397,6 @@ void __init setup_system(void) find_legacy_serial_ports(); /* - * "Finish" the device-tree, that is do the actual parsing of - * some of the properties like the interrupt map - */ - finish_device_tree(); - - /* * Initialize xmon */ #ifdef CONFIG_XMON_DEFAULT @@ -427,8 +424,6 @@ void __init setup_system(void) printk("-----------------------------------------------------\n"); printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); - printk("ppc64_interrupt_controller = 0x%ld\n", - ppc64_interrupt_controller); printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size()); printk("ppc64_caches.dcache_line_size = 0x%x\n", ppc64_caches.dline_size); diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cdf5867838a..fad8580f908 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -218,7 +218,6 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) { struct vio_dev *viodev; unsigned int *unit_address; - unsigned int *irq_p; /* we need the 'device_type' property, in order to match with drivers */ if (of_node->type == NULL) { @@ -243,16 +242,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) viodev->dev.platform_data = of_node_get(of_node); - viodev->irq = NO_IRQ; - irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); - if (irq_p) { - int virq = virt_irq_create_mapping(*irq_p); - if (virq == NO_IRQ) { - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", of_node->full_name); - } else - viodev->irq = irq_offset_up(virq); - } + viodev->irq = irq_of_parse_and_map(of_node, 0); snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); viodev->name = of_node->name; diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 7675e675dce..5fe7b7faf45 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -16,12 +16,21 @@ config MPC834x_SYS 3 PCI slots. The PIBs PCI initialization is the bootloader's responsiblilty. +config MPC834x_ITX + bool "Freescale MPC834x ITX" + select DEFAULT_UIMAGE + help + This option enables support for the MPC 834x ITX evaluation board. + + Be aware that PCI initialization is the bootloader's + responsiblilty. + endchoice config MPC834x bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI - default y if MPC834x_SYS + default y if MPC834x_SYS || MPC834x_ITX endmenu diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 5c72367441a..9387a110d28 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile @@ -4,3 +4,4 @@ obj-y := misc.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o +obj-$(CONFIG_MPC834x_ITX) += mpc834x_itx.o diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c new file mode 100644 index 00000000000..b46305645d3 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -0,0 +1,156 @@ +/* + * arch/powerpc/platforms/83xx/mpc834x_itx.c + * + * MPC834x ITX board specific routines + * + * Maintainer: Kumar Gala <galak@kernel.crashing.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/config.h> +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/major.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> + +#include <asm/system.h> +#include <asm/atomic.h> +#include <asm/time.h> +#include <asm/io.h> +#include <asm/machdep.h> +#include <asm/ipic.h> +#include <asm/bootinfo.h> +#include <asm/irq.h> +#include <asm/prom.h> +#include <asm/udbg.h> +#include <sysdev/fsl_soc.h> + +#include "mpc83xx.h" + +#include <platforms/83xx/mpc834x_sys.h> + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +#ifdef CONFIG_PCI +static int +mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x0e */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x0f */ + {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x10 */ + }; + + const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} +#endif /* CONFIG_PCI */ + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init mpc834x_itx_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_itx_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp = + (int *)get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc83xx_map_irq; + ppc_md.pci_exclude_device = mpc83xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + +void __init mpc834x_itx_init_IRQ(void) +{ + u8 senses[8] = { + 0, /* EXT 0 */ + IRQ_SENSE_LEVEL, /* EXT 1 */ + IRQ_SENSE_LEVEL, /* EXT 2 */ + 0, /* EXT 3 */ +#ifdef CONFIG_PCI + IRQ_SENSE_LEVEL, /* EXT 4 */ + IRQ_SENSE_LEVEL, /* EXT 5 */ + IRQ_SENSE_LEVEL, /* EXT 6 */ + IRQ_SENSE_LEVEL, /* EXT 7 */ +#else + 0, /* EXT 4 */ + 0, /* EXT 5 */ + 0, /* EXT 6 */ + 0, /* EXT 7 */ +#endif + }; + + ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + ipic_set_default_priority(); +} + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init mpc834x_itx_probe(void) +{ + /* We always match for now, eventually we should look at the flat + dev tree to ensure this is the board we are suppose to run on + */ + return 1; +} + +define_machine(mpc834x_itx) { + .name = "MPC834x ITX", + .probe = mpc834x_itx_probe, + .setup_arch = mpc834x_itx_setup_arch, + .init_IRQ = mpc834x_itx_init_IRQ, + .get_irq = ipic_get_irq, + .restart = mpc83xx_restart, + .time_init = mpc83xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.h b/arch/powerpc/platforms/83xx/mpc834x_itx.h new file mode 100644 index 00000000000..174ca4ef55f --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.h @@ -0,0 +1,23 @@ +/* + * arch/powerpc/platforms/83xx/mpc834x_itx.h + * + * MPC834X ITX common board definitions + * + * Maintainer: Kumar Gala <galak@kernel.crashing.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC83XX_ITX_H__ +#define __MACH_MPC83XX_ITX_H__ + +#define PIRQA MPC83xx_IRQ_EXT4 +#define PIRQB MPC83xx_IRQ_EXT5 +#define PIRQC MPC83xx_IRQ_EXT6 +#define PIRQD MPC83xx_IRQ_EXT7 + +#endif /* __MACH_MPC83XX_ITX_H__ */ diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 880c8083d16..9d5da789689 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -1,6 +1,9 @@ /* * Cell Internal Interrupt Controller * + * Copyright (C) 2006 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * IBM, Corp. + * * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 * * Author: Arnd Bergmann <arndb@de.ibm.com> @@ -25,11 +28,13 @@ #include <linux/module.h> #include <linux/percpu.h> #include <linux/types.h> +#include <linux/ioport.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/prom.h> #include <asm/ptrace.h> +#include <asm/machdep.h> #include "interrupt.h" #include "cbe_regs.h" @@ -37,231 +42,65 @@ struct iic { struct cbe_iic_thread_regs __iomem *regs; u8 target_id; + u8 eoi_stack[16]; + int eoi_ptr; + struct irq_host *host; }; static DEFINE_PER_CPU(struct iic, iic); +#define IIC_NODE_COUNT 2 +static struct irq_host *iic_hosts[IIC_NODE_COUNT]; -void iic_local_enable(void) +/* Convert between "pending" bits and hw irq number */ +static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits) { - struct iic *iic = &__get_cpu_var(iic); - u64 tmp; - - /* - * There seems to be a bug that is present in DD2.x CPUs - * and still only partially fixed in DD3.1. - * This bug causes a value written to the priority register - * not to make it there, resulting in a system hang unless we - * write it again. - * Masking with 0xf0 is done because the Cell BE does not - * implement the lower four bits of the interrupt priority, - * they always read back as zeroes, although future CPUs - * might implement different bits. - */ - do { - out_be64(&iic->regs->prio, 0xff); - tmp = in_be64(&iic->regs->prio); - } while ((tmp & 0xf0) != 0xf0); -} - -void iic_local_disable(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0x0); -} + unsigned char unit = bits.source & 0xf; -static unsigned int iic_startup(unsigned int irq) -{ - return 0; + if (bits.flags & CBE_IIC_IRQ_IPI) + return IIC_IRQ_IPI0 | (bits.prio >> 4); + else if (bits.class <= 3) + return (bits.class << 4) | unit; + else + return IIC_IRQ_INVALID; } -static void iic_enable(unsigned int irq) +static void iic_mask(unsigned int irq) { - iic_local_enable(); } -static void iic_disable(unsigned int irq) +static void iic_unmask(unsigned int irq) { } -static void iic_end(unsigned int irq) +static void iic_eoi(unsigned int irq) { - iic_local_enable(); + struct iic *iic = &__get_cpu_var(iic); + out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]); + BUG_ON(iic->eoi_ptr < 0); } -static struct hw_interrupt_type iic_pic = { +static struct irq_chip iic_chip = { .typename = " CELL-IIC ", - .startup = iic_startup, - .enable = iic_enable, - .disable = iic_disable, - .end = iic_end, + .mask = iic_mask, + .unmask = iic_unmask, + .eoi = iic_eoi, }; -static int iic_external_get_irq(struct cbe_iic_pending_bits pending) -{ - int irq; - unsigned char node, unit; - - node = pending.source >> 4; - unit = pending.source & 0xf; - irq = -1; - - /* - * This mapping is specific to the Cell Broadband - * Engine. We might need to get the numbers - * from the device tree to support future CPUs. - */ - switch (unit) { - case 0x00: - case 0x0b: - /* - * One of these units can be connected - * to an external interrupt controller. - */ - if (pending.class != 2) - break; - irq = IIC_EXT_OFFSET - + spider_get_irq(node) - + node * IIC_NODE_STRIDE; - break; - case 0x01 ... 0x04: - case 0x07 ... 0x0a: - /* - * These units are connected to the SPEs - */ - if (pending.class > 2) - break; - irq = IIC_SPE_OFFSET - + pending.class * IIC_CLASS_STRIDE - + node * IIC_NODE_STRIDE - + unit; - break; - } - if (irq == -1) - printk(KERN_WARNING "Unexpected interrupt class %02x, " - "source %02x, prio %02x, cpu %02x\n", pending.class, - pending.source, pending.prio, smp_processor_id()); - return irq; -} - /* Get an IRQ number from the pending state register of the IIC */ -int iic_get_irq(struct pt_regs *regs) +static unsigned int iic_get_irq(struct pt_regs *regs) { - struct iic *iic; - int irq; - struct cbe_iic_pending_bits pending; - - iic = &__get_cpu_var(iic); - *(unsigned long *) &pending = - in_be64((unsigned long __iomem *) &iic->regs->pending_destr); - - irq = -1; - if (pending.flags & CBE_IIC_IRQ_VALID) { - if (pending.flags & CBE_IIC_IRQ_IPI) { - irq = IIC_IPI_OFFSET + (pending.prio >> 4); -/* - if (irq > 0x80) - printk(KERN_WARNING "Unexpected IPI prio %02x" - "on CPU %02x\n", pending.prio, - smp_processor_id()); -*/ - } else { - irq = iic_external_get_irq(pending); - } - } - return irq; -} - -/* hardcoded part to be compatible with older firmware */ - -static int setup_iic_hardcoded(void) -{ - struct device_node *np; - int nodeid, cpu; - unsigned long regs; - struct iic *iic; - - for_each_possible_cpu(cpu) { - iic = &per_cpu(iic, cpu); - nodeid = cpu/2; - - for (np = of_find_node_by_type(NULL, "cpu"); - np; - np = of_find_node_by_type(np, "cpu")) { - if (nodeid == *(int *)get_property(np, "node-id", NULL)) - break; - } - - if (!np) { - printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); - iic->regs = NULL; - iic->target_id = 0xff; - return -ENODEV; - } - - regs = *(long *)get_property(np, "iic", NULL); - - /* hack until we have decided on the devtree info */ - regs += 0x400; - if (cpu & 1) - regs += 0x20; - - printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); - iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs)); - iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); - } - - return 0; -} - -static int setup_iic(void) -{ - struct device_node *dn; - unsigned long *regs; - char *compatible; - unsigned *np, found = 0; - struct iic *iic = NULL; - - for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { - compatible = (char *)get_property(dn, "compatible", NULL); - - if (!compatible) { - printk(KERN_WARNING "no compatible property found !\n"); - continue; - } - - if (strstr(compatible, "IBM,CBEA-Internal-Interrupt-Controller")) - regs = (unsigned long *)get_property(dn,"reg", NULL); - else - continue; - - if (!regs) - printk(KERN_WARNING "IIC: no reg property\n"); - - np = (unsigned int *)get_property(dn, "ibm,interrupt-server-ranges", NULL); - - if (!np) { - printk(KERN_WARNING "IIC: CPU association not found\n"); - iic->regs = NULL; - iic->target_id = 0xff; - return -ENODEV; - } - - iic = &per_cpu(iic, np[0]); - iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs)); - iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); - printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); - - iic = &per_cpu(iic, np[1]); - iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs)); - iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); - printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); - - found++; - } - - if (found) - return 0; - else - return -ENODEV; + struct cbe_iic_pending_bits pending; + struct iic *iic; + + iic = &__get_cpu_var(iic); + *(unsigned long *) &pending = + in_be64((unsigned long __iomem *) &iic->regs->pending_destr); + iic->eoi_stack[++iic->eoi_ptr] = pending.prio; + BUG_ON(iic->eoi_ptr > 15); + if (pending.flags & CBE_IIC_IRQ_VALID) + return irq_linear_revmap(iic->host, + iic_pending_to_hwnum(pending)); + return NO_IRQ; } #ifdef CONFIG_SMP @@ -269,12 +108,12 @@ static int setup_iic(void) /* Use the highest interrupt priorities for IPI */ static inline int iic_ipi_to_irq(int ipi) { - return IIC_IPI_OFFSET + IIC_NUM_IPIS - 1 - ipi; + return IIC_IRQ_IPI0 + IIC_NUM_IPIS - 1 - ipi; } static inline int iic_irq_to_ipi(int irq) { - return IIC_NUM_IPIS - 1 - (irq - IIC_IPI_OFFSET); + return IIC_NUM_IPIS - 1 - (irq - IIC_IRQ_IPI0); } void iic_setup_cpu(void) @@ -293,22 +132,51 @@ u8 iic_get_target_id(int cpu) } EXPORT_SYMBOL_GPL(iic_get_target_id); +struct irq_host *iic_get_irq_host(int node) +{ + if (node < 0 || node >= IIC_NODE_COUNT) + return NULL; + return iic_hosts[node]; +} +EXPORT_SYMBOL_GPL(iic_get_irq_host); + + static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { - smp_message_recv(iic_irq_to_ipi(irq), regs); + int ipi = (int)(long)dev_id; + + smp_message_recv(ipi, regs); + return IRQ_HANDLED; } static void iic_request_ipi(int ipi, const char *name) { - int irq; - - irq = iic_ipi_to_irq(ipi); - /* IPIs are marked SA_INTERRUPT as they must run with irqs - * disabled */ - get_irq_desc(irq)->chip = &iic_pic; - get_irq_desc(irq)->status |= IRQ_PER_CPU; - request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL); + int node, virq; + + for (node = 0; node < IIC_NODE_COUNT; node++) { + char *rname; + if (iic_hosts[node] == NULL) + continue; + virq = irq_create_mapping(iic_hosts[node], + iic_ipi_to_irq(ipi), 0); + if (virq == NO_IRQ) { + printk(KERN_ERR + "iic: failed to map IPI %s on node %d\n", + name, node); + continue; + } + rname = kzalloc(strlen(name) + 16, GFP_KERNEL); + if (rname) + sprintf(rname, "%s node %d", name, node); + else + rname = (char *)name; + if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, + rname, (void *)(long)ipi)) + printk(KERN_ERR + "iic: failed to request IPI %s on node %d\n", + name, node); + } } void iic_request_IPIs(void) @@ -319,34 +187,119 @@ void iic_request_IPIs(void) iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); #endif /* CONFIG_DEBUGGER */ } + #endif /* CONFIG_SMP */ -static void iic_setup_spe_handlers(void) + +static int iic_host_match(struct irq_host *h, struct device_node *node) +{ + return h->host_data != NULL && node == h->host_data; +} + +static int iic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + if (hw < IIC_IRQ_IPI0) + set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq); + else + set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq); + return 0; +} + +static int iic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags) + +{ + /* Currently, we don't translate anything. That needs to be fixed as + * we get better defined device-trees. iic interrupts have to be + * explicitely mapped by whoever needs them + */ + return -ENODEV; +} + +static struct irq_host_ops iic_host_ops = { + .match = iic_host_match, + .map = iic_host_map, + .xlate = iic_host_xlate, +}; + +static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr, + struct irq_host *host) { - int be, isrc; + /* XXX FIXME: should locate the linux CPU number from the HW cpu + * number properly. We are lucky for now + */ + struct iic *iic = &per_cpu(iic, hw_cpu); + + iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs)); + BUG_ON(iic->regs == NULL); - /* Assume two threads per BE are present */ - for (be=0; be < num_present_cpus() / 2; be++) { - for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) { - int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc; - get_irq_desc(irq)->chip = &iic_pic; + iic->target_id = ((hw_cpu & 2) << 3) | ((hw_cpu & 1) ? 0xf : 0xe); + iic->eoi_stack[0] = 0xff; + iic->host = host; + out_be64(&iic->regs->prio, 0); + + printk(KERN_INFO "IIC for CPU %d at %lx mapped to %p, target id 0x%x\n", + hw_cpu, addr, iic->regs, iic->target_id); +} + +static int __init setup_iic(void) +{ + struct device_node *dn; + struct resource r0, r1; + struct irq_host *host; + int found = 0; + u32 *np; + + for (dn = NULL; + (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) { + if (!device_is_compatible(dn, + "IBM,CBEA-Internal-Interrupt-Controller")) + continue; + np = (u32 *)get_property(dn, "ibm,interrupt-server-ranges", + NULL); + if (np == NULL) { + printk(KERN_WARNING "IIC: CPU association not found\n"); + of_node_put(dn); + return -ENODEV; + } + if (of_address_to_resource(dn, 0, &r0) || + of_address_to_resource(dn, 1, &r1)) { + printk(KERN_WARNING "IIC: Can't resolve addresses\n"); + of_node_put(dn); + return -ENODEV; } + host = NULL; + if (found < IIC_NODE_COUNT) { + host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, + IIC_SOURCE_COUNT, + &iic_host_ops, + IIC_IRQ_INVALID); + iic_hosts[found] = host; + BUG_ON(iic_hosts[found] == NULL); + iic_hosts[found]->host_data = of_node_get(dn); + found++; + } + init_one_iic(np[0], r0.start, host); + init_one_iic(np[1], r1.start, host); } + + if (found) + return 0; + else + return -ENODEV; } -void iic_init_IRQ(void) +void __init iic_init_IRQ(void) { - int cpu, irq_offset; - struct iic *iic; - + /* Discover and initialize iics */ if (setup_iic() < 0) - setup_iic_hardcoded(); + panic("IIC: Failed to initialize !\n"); - irq_offset = 0; - for_each_possible_cpu(cpu) { - iic = &per_cpu(iic, cpu); - if (iic->regs) - out_be64(&iic->regs->prio, 0xff); - } - iic_setup_spe_handlers(); + /* Set master interrupt handling function */ + ppc_md.get_irq = iic_get_irq; + + /* Enable on current CPU */ + iic_setup_cpu(); } diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h index 799f77d98f9..5560a92ec3a 100644 --- a/arch/powerpc/platforms/cell/interrupt.h +++ b/arch/powerpc/platforms/cell/interrupt.h @@ -37,27 +37,24 @@ */ enum { - IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */ - IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */ - IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */ - IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */ - IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */ - IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */ - IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */ + IIC_IRQ_INVALID = 0xff, + IIC_IRQ_MAX = 0x3f, + IIC_IRQ_EXT_IOIF0 = 0x20, + IIC_IRQ_EXT_IOIF1 = 0x2b, + IIC_IRQ_IPI0 = 0x40, + IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */ + IIC_SOURCE_COUNT = 0x50, }; extern void iic_init_IRQ(void); -extern int iic_get_irq(struct pt_regs *regs); extern void iic_cause_IPI(int cpu, int mesg); extern void iic_request_IPIs(void); extern void iic_setup_cpu(void); -extern void iic_local_enable(void); -extern void iic_local_disable(void); extern u8 iic_get_target_id(int cpu); +extern struct irq_host *iic_get_irq_host(int node); extern void spider_init_IRQ(void); -extern int spider_get_irq(int node); #endif #endif /* ASM_CELL_PIC_H */ diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index d8c2a29b3c1..282987d6d4a 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -49,6 +49,7 @@ #include <asm/irq.h> #include <asm/spu.h> #include <asm/spu_priv1.h> +#include <asm/udbg.h> #include "interrupt.h" #include "iommu.h" @@ -79,10 +80,22 @@ static void cell_progress(char *s, unsigned short hex) printk("*** %04x : %s\n", hex, s ? s : ""); } +static void __init cell_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + for_each_pci_dev(dev) + pci_read_irq_line(dev); +} + +static void __init cell_init_irq(void) +{ + iic_init_IRQ(); + spider_init_IRQ(); +} + static void __init cell_setup_arch(void) { - ppc_md.init_IRQ = iic_init_IRQ; - ppc_md.get_irq = iic_get_irq; #ifdef CONFIG_SPU_BASE spu_priv1_ops = &spu_priv1_mmio_ops; #endif @@ -108,7 +121,6 @@ static void __init cell_setup_arch(void) /* Find and initialize PCI host bridges */ init_pci_config_tokens(); find_and_init_phbs(); - spider_init_IRQ(); cbe_pervasive_init(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; @@ -126,8 +138,6 @@ static void __init cell_init_early(void) cell_init_iommu(); - ppc64_interrupt_controller = IC_CELL_PIC; - DBG(" <- cell_init_early()\n"); } @@ -173,6 +183,8 @@ define_machine(cell) { .calibrate_decr = generic_calibrate_decr, .check_legacy_ioport = cell_check_legacy_ioport, .progress = cell_progress, + .init_IRQ = cell_init_irq, + .pcibios_fixup = cell_pcibios_fixup, #ifdef CONFIG_KEXEC .machine_kexec = default_machine_kexec, .machine_kexec_prepare = default_machine_kexec_prepare, diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 7c3a0b6d34f..ae7ef88f1a3 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/ioport.h> #include <asm/pgtable.h> #include <asm/prom.h> @@ -56,184 +57,313 @@ enum { REISWAITEN = 0x508, /* Reissue Wait Control*/ }; -static void __iomem *spider_pics[4]; +#define SPIDER_CHIP_COUNT 4 +#define SPIDER_SRC_COUNT 64 +#define SPIDER_IRQ_INVALID 63 -static void __iomem *spider_get_pic(int irq) -{ - int node = irq / IIC_NODE_STRIDE; - irq %= IIC_NODE_STRIDE; - - if (irq >= IIC_EXT_OFFSET && - irq < IIC_EXT_OFFSET + IIC_NUM_EXT && - spider_pics) - return spider_pics[node]; - return NULL; -} +struct spider_pic { + struct irq_host *host; + struct device_node *of_node; + void __iomem *regs; + unsigned int node_id; +}; +static struct spider_pic spider_pics[SPIDER_CHIP_COUNT]; -static int spider_get_nr(unsigned int irq) +static struct spider_pic *spider_virq_to_pic(unsigned int virq) { - return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET; + return irq_map[virq].host->host_data; } -static void __iomem *spider_get_irq_config(int irq) +static void __iomem *spider_get_irq_config(struct spider_pic *pic, + unsigned int src) { - void __iomem *pic; - pic = spider_get_pic(irq); - return pic + TIR_CFGA + 8 * spider_get_nr(irq); + return pic->regs + TIR_CFGA + 8 * src; } -static void spider_enable_irq(unsigned int irq) +static void spider_unmask_irq(unsigned int virq) { - int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; - void __iomem *cfg = spider_get_irq_config(irq); - irq = spider_get_nr(irq); + struct spider_pic *pic = spider_virq_to_pic(virq); + void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq); - out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); - out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); + /* We use no locking as we should be covered by the descriptor lock + * for access to invidual source configuration registers + */ + out_be32(cfg, in_be32(cfg) | 0x30000000u); } -static void spider_disable_irq(unsigned int irq) +static void spider_mask_irq(unsigned int virq) { - void __iomem *cfg = spider_get_irq_config(irq); - irq = spider_get_nr(irq); + struct spider_pic *pic = spider_virq_to_pic(virq); + void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq); + /* We use no locking as we should be covered by the descriptor lock + * for access to invidual source configuration registers + */ out_be32(cfg, in_be32(cfg) & ~0x30000000u); } -static unsigned int spider_startup_irq(unsigned int irq) +static void spider_ack_irq(unsigned int virq) { - spider_enable_irq(irq); - return 0; -} + struct spider_pic *pic = spider_virq_to_pic(virq); + unsigned int src = irq_map[virq].hwirq; -static void spider_shutdown_irq(unsigned int irq) -{ - spider_disable_irq(irq); -} + /* Reset edge detection logic if necessary + */ + if (get_irq_desc(virq)->status & IRQ_LEVEL) + return; -static void spider_end_irq(unsigned int irq) -{ - spider_enable_irq(irq); -} + /* Only interrupts 47 to 50 can be set to edge */ + if (src < 47 || src > 50) + return; -static void spider_ack_irq(unsigned int irq) -{ - spider_disable_irq(irq); - iic_local_enable(); + /* Perform the clear of the edge logic */ + out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf)); } -static struct hw_interrupt_type spider_pic = { +static struct irq_chip spider_pic = { .typename = " SPIDER ", - .startup = spider_startup_irq, - .shutdown = spider_shutdown_irq, - .enable = spider_enable_irq, - .disable = spider_disable_irq, + .unmask = spider_unmask_irq, + .mask = spider_mask_irq, .ack = spider_ack_irq, - .end = spider_end_irq, }; -int spider_get_irq(int node) +static int spider_host_match(struct irq_host *h, struct device_node *node) { - unsigned long cs; - void __iomem *regs = spider_pics[node]; - - cs = in_be32(regs + TIR_CS) >> 24; - - if (cs == 63) - return -1; - else - return cs; + struct spider_pic *pic = h->host_data; + return node == pic->of_node; } -/* hardcoded part to be compatible with older firmware */ - -void spider_init_IRQ_hardcoded(void) +static int spider_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) { - int node; - long spiderpic; - long pics[] = { 0x24000008000, 0x34000008000 }; - int n; - - pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); - - for (node = 0; node < num_present_cpus()/2; node++) { - spiderpic = pics[node]; - printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); - spider_pics[node] = ioremap(spiderpic, 0x800); - for (n = 0; n < IIC_NUM_EXT; n++) { - int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; - get_irq_desc(irq)->chip = &spider_pic; - } - - /* do not mask any interrupts because of level */ - out_be32(spider_pics[node] + TIR_MSK, 0x0); - - /* disable edge detection clear */ - /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ - - /* enable interrupt packets to be output */ - out_be32(spider_pics[node] + TIR_PIEN, - in_be32(spider_pics[node] + TIR_PIEN) | 0x1); - - /* Enable the interrupt detection enable bit. Do this last! */ - out_be32(spider_pics[node] + TIR_DEN, - in_be32(spider_pics[node] + TIR_DEN) | 0x1); + unsigned int sense = flags & IRQ_TYPE_SENSE_MASK; + struct spider_pic *pic = h->host_data; + void __iomem *cfg = spider_get_irq_config(pic, hw); + int level = 0; + u32 ic; + + /* Note that only level high is supported for most interrupts */ + if (sense != IRQ_TYPE_NONE && sense != IRQ_TYPE_LEVEL_HIGH && + (hw < 47 || hw > 50)) + return -EINVAL; + + /* Decode sense type */ + switch(sense) { + case IRQ_TYPE_EDGE_RISING: + ic = 0x3; + break; + case IRQ_TYPE_EDGE_FALLING: + ic = 0x2; + break; + case IRQ_TYPE_LEVEL_LOW: + ic = 0x0; + level = 1; + break; + case IRQ_TYPE_LEVEL_HIGH: + case IRQ_TYPE_NONE: + ic = 0x1; + level = 1; + break; + default: + return -EINVAL; } -} -void spider_init_IRQ(void) -{ - long spider_reg; - struct device_node *dn; - char *compatible; - int n, node = 0; + /* Configure the source. One gross hack that was there before and + * that I've kept around is the priority to the BE which I set to + * be the same as the interrupt source number. I don't know wether + * that's supposed to make any kind of sense however, we'll have to + * decide that, but for now, I'm not changing the behaviour. + */ + out_be32(cfg, (ic << 24) | (0x7 << 16) | (pic->node_id << 4) | 0xe); + out_be32(cfg + 4, (0x2 << 16) | (hw & 0xff)); + + if (level) + get_irq_desc(virq)->status |= IRQ_LEVEL; + set_irq_chip_and_handler(virq, &spider_pic, handle_level_irq); + return 0; +} - for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { - compatible = (char *)get_property(dn, "compatible", NULL); +static int spider_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags) - if (!compatible) - continue; +{ + /* Spider interrupts have 2 cells, first is the interrupt source, + * second, well, I don't know for sure yet ... We mask the top bits + * because old device-trees encode a node number in there + */ + *out_hwirq = intspec[0] & 0x3f; + *out_flags = IRQ_TYPE_LEVEL_HIGH; + return 0; +} - if (strstr(compatible, "CBEA,platform-spider-pic")) - spider_reg = *(long *)get_property(dn,"reg", NULL); - else if (strstr(compatible, "sti,platform-spider-pic")) { - spider_init_IRQ_hardcoded(); - return; - } else - continue; +static struct irq_host_ops spider_host_ops = { + .match = spider_host_match, + .map = spider_host_map, + .xlate = spider_host_xlate, +}; - if (!spider_reg) - printk("interrupt controller does not have reg property !\n"); +static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs) +{ + struct spider_pic *pic = desc->handler_data; + unsigned int cs, virq; - n = prom_n_addr_cells(dn); + cs = in_be32(pic->regs + TIR_CS) >> 24; + if (cs == SPIDER_IRQ_INVALID) + virq = NO_IRQ; + else + virq = irq_linear_revmap(pic->host, cs); + if (virq != NO_IRQ) + generic_handle_irq(virq, regs); + desc->chip->eoi(irq); +} - if ( n != 2) - printk("reg property with invalid number of elements \n"); +/* For hooking up the cascace we have a problem. Our device-tree is + * crap and we don't know on which BE iic interrupt we are hooked on at + * least not the "standard" way. We can reconstitute it based on two + * informations though: which BE node we are connected to and wether + * we are connected to IOIF0 or IOIF1. Right now, we really only care + * about the IBM cell blade and we know that its firmware gives us an + * interrupt-map property which is pretty strange. + */ +static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) +{ + unsigned int virq; + u32 *imap, *tmp; + int imaplen, intsize, unit; + struct device_node *iic; + struct irq_host *iic_host; + +#if 0 /* Enable that when we have a way to retreive the node as well */ + /* First, we check wether we have a real "interrupts" in the device + * tree in case the device-tree is ever fixed + */ + struct of_irq oirq; + if (of_irq_map_one(pic->of_node, 0, &oirq) == 0) { + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, + oirq.size); + goto bail; + } +#endif + + /* Now do the horrible hacks */ + tmp = (u32 *)get_property(pic->of_node, "#interrupt-cells", NULL); + if (tmp == NULL) + return NO_IRQ; + intsize = *tmp; + imap = (u32 *)get_property(pic->of_node, "interrupt-map", &imaplen); + if (imap == NULL || imaplen < (intsize + 1)) + return NO_IRQ; + iic = of_find_node_by_phandle(imap[intsize]); + if (iic == NULL) + return NO_IRQ; + imap += intsize + 1; + tmp = (u32 *)get_property(iic, "#interrupt-cells", NULL); + if (tmp == NULL) + return NO_IRQ; + intsize = *tmp; + /* Assume unit is last entry of interrupt specifier */ + unit = imap[intsize - 1]; + /* Ok, we have a unit, now let's try to get the node */ + tmp = (u32 *)get_property(iic, "ibm,interrupt-server-ranges", NULL); + if (tmp == NULL) { + of_node_put(iic); + return NO_IRQ; + } + /* ugly as hell but works for now */ + pic->node_id = (*tmp) >> 1; + of_node_put(iic); + + /* Ok, now let's get cracking. You may ask me why I just didn't match + * the iic host from the iic OF node, but that way I'm still compatible + * with really really old old firmwares for which we don't have a node + */ + iic_host = iic_get_irq_host(pic->node_id); + if (iic_host == NULL) + return NO_IRQ; + /* Manufacture an IIC interrupt number of class 2 */ + virq = irq_create_mapping(iic_host, 0x20 | unit, 0); + if (virq == NO_IRQ) + printk(KERN_ERR "spider_pic: failed to map cascade !"); + return virq; +} - spider_pics[node] = ioremap(spider_reg, 0x800); - printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n", - spider_reg, n, spider_pics[node]); +static void __init spider_init_one(struct device_node *of_node, int chip, + unsigned long addr) +{ + struct spider_pic *pic = &spider_pics[chip]; + int i, virq; + + /* Map registers */ + pic->regs = ioremap(addr, 0x1000); + if (pic->regs == NULL) + panic("spider_pic: can't map registers !"); + + /* Allocate a host */ + pic->host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, SPIDER_SRC_COUNT, + &spider_host_ops, SPIDER_IRQ_INVALID); + if (pic->host == NULL) + panic("spider_pic: can't allocate irq host !"); + pic->host->host_data = pic; + + /* Fill out other bits */ + pic->of_node = of_node_get(of_node); + + /* Go through all sources and disable them */ + for (i = 0; i < SPIDER_SRC_COUNT; i++) { + void __iomem *cfg = pic->regs + TIR_CFGA + 8 * i; + out_be32(cfg, in_be32(cfg) & ~0x30000000u); + } - for (n = 0; n < IIC_NUM_EXT; n++) { - int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; - get_irq_desc(irq)->chip = &spider_pic; - } + /* do not mask any interrupts because of level */ + out_be32(pic->regs + TIR_MSK, 0x0); - /* do not mask any interrupts because of level */ - out_be32(spider_pics[node] + TIR_MSK, 0x0); + /* enable interrupt packets to be output */ + out_be32(pic->regs + TIR_PIEN, in_be32(pic->regs + TIR_PIEN) | 0x1); - /* disable edge detection clear */ - /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ + /* Hook up the cascade interrupt to the iic and nodeid */ + virq = spider_find_cascade_and_node(pic); + if (virq == NO_IRQ) + return; + set_irq_data(virq, pic); + set_irq_chained_handler(virq, spider_irq_cascade); - /* enable interrupt packets to be output */ - out_be32(spider_pics[node] + TIR_PIEN, - in_be32(spider_pics[node] + TIR_PIEN) | 0x1); + printk(KERN_INFO "spider_pic: node %d, addr: 0x%lx %s\n", + pic->node_id, addr, of_node->full_name); - /* Enable the interrupt detection enable bit. Do this last! */ - out_be32(spider_pics[node] + TIR_DEN, - in_be32(spider_pics[node] + TIR_DEN) | 0x1); + /* Enable the interrupt detection enable bit. Do this last! */ + out_be32(pic->regs + TIR_DEN, in_be32(pic->regs + TIR_DEN) | 0x1); +} - node++; +void __init spider_init_IRQ(void) +{ + struct resource r; + struct device_node *dn; + int chip = 0; + + /* XXX node numbers are totally bogus. We _hope_ we get the device + * nodes in the right order here but that's definitely not guaranteed, + * we need to get the node from the device tree instead. + * There is currently no proper property for it (but our whole + * device-tree is bogus anyway) so all we can do is pray or maybe test + * the address and deduce the node-id + */ + for (dn = NULL; + (dn = of_find_node_by_name(dn, "interrupt-controller"));) { + if (device_is_compatible(dn, "CBEA,platform-spider-pic")) { + if (of_address_to_resource(dn, 0, &r)) { + printk(KERN_WARNING "spider-pic: Failed\n"); + continue; + } + } else if (device_is_compatible(dn, "sti,platform-spider-pic") + && (chip < 2)) { + static long hard_coded_pics[] = + { 0x24000008000, 0x34000008000 }; + r.start = hard_coded_pics[chip]; + } else + continue; + spider_init_one(dn, chip++, r.start); } } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index b306723abb8..5d2313a6c82 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -264,51 +264,57 @@ spu_irq_class_2(int irq, void *data, struct pt_regs *regs) return stat ? IRQ_HANDLED : IRQ_NONE; } -static int -spu_request_irqs(struct spu *spu) +static int spu_request_irqs(struct spu *spu) { - int ret; - int irq_base; - - irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET; - - snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number); - ret = request_irq(irq_base + spu->isrc, - spu_irq_class_0, SA_INTERRUPT, spu->irq_c0, spu); - if (ret) - goto out; - - snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number); - ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, - spu_irq_class_1, SA_INTERRUPT, spu->irq_c1, spu); - if (ret) - goto out1; + int ret = 0; - snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number); - ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc, - spu_irq_class_2, SA_INTERRUPT, spu->irq_c2, spu); - if (ret) - goto out2; - goto out; + if (spu->irqs[0] != NO_IRQ) { + snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", + spu->number); + ret = request_irq(spu->irqs[0], spu_irq_class_0, + IRQF_DISABLED, + spu->irq_c0, spu); + if (ret) + goto bail0; + } + if (spu->irqs[1] != NO_IRQ) { + snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", + spu->number); + ret = request_irq(spu->irqs[1], spu_irq_class_1, + IRQF_DISABLED, + spu->irq_c1, spu); + if (ret) + goto bail1; + } + if (spu->irqs[2] != NO_IRQ) { + snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", + spu->number); + ret = request_irq(spu->irqs[2], spu_irq_class_2, + IRQF_DISABLED, + spu->irq_c2, spu); + if (ret) + goto bail2; + } + return 0; -out2: - free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu); -out1: - free_irq(irq_base + spu->isrc, spu); -out: +bail2: + if (spu->irqs[1] != NO_IRQ) + free_irq(spu->irqs[1], spu); +bail1: + if (spu->irqs[0] != NO_IRQ) + free_irq(spu->irqs[0], spu); +bail0: return ret; } -static void -spu_free_irqs(struct spu *spu) +static void spu_free_irqs(struct spu *spu) { - int irq_base; - - irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET; - - free_irq(irq_base + spu->isrc, spu); - free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu); - free_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc, spu); + if (spu->irqs[0] != NO_IRQ) + free_irq(spu->irqs[0], spu); + if (spu->irqs[1] != NO_IRQ) + free_irq(spu->irqs[1], spu); + if (spu->irqs[2] != NO_IRQ) + free_irq(spu->irqs[2], spu); } static LIST_HEAD(spu_list); @@ -559,17 +565,38 @@ static void spu_unmap(struct spu *spu) iounmap((u8 __iomem *)spu->local_store); } +/* This function shall be abstracted for HV platforms */ +static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) +{ + struct irq_host *host; + unsigned int isrc; + u32 *tmp; + + host = iic_get_irq_host(spu->node); + if (host == NULL) + return -ENODEV; + + /* Get the interrupt source from the device-tree */ + tmp = (u32 *)get_property(np, "isrc", NULL); + if (!tmp) + return -ENODEV; + spu->isrc = isrc = tmp[0]; + + /* Now map interrupts of all 3 classes */ + spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc, 0); + spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc, 0); + spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc, 0); + + /* Right now, we only fail if class 2 failed */ + return spu->irqs[2] == NO_IRQ ? -EINVAL : 0; +} + static int __init spu_map_device(struct spu *spu, struct device_node *node) { char *prop; int ret; ret = -ENODEV; - prop = get_property(node, "isrc", NULL); - if (!prop) - goto out; - spu->isrc = *(unsigned int *)prop; - spu->name = get_property(node, "name", NULL); if (!spu->name) goto out; @@ -636,7 +663,8 @@ static int spu_create_sysdev(struct spu *spu) return ret; } - sysdev_create_file(&spu->sysdev, &attr_isrc); + if (spu->isrc != 0) + sysdev_create_file(&spu->sysdev, &attr_isrc); sysfs_add_device_to_node(&spu->sysdev, spu->nid); return 0; @@ -668,6 +696,9 @@ static int __init create_spu(struct device_node *spe) spu->nid = of_node_to_nid(spe); if (spu->nid == -1) spu->nid = 0; + ret = spu_map_interrupts(spu, spe); + if (ret) + goto out_unmap; spin_lock_init(&spu->register_lock); spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); spu_mfc_sr1_set(spu, 0x33); diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 66c25349880..6802cdc3168 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -18,7 +18,6 @@ #include <asm/machdep.h> #include <asm/sections.h> #include <asm/pci-bridge.h> -#include <asm/open_pic.h> #include <asm/grackle.h> #include <asm/rtas.h> @@ -161,15 +160,9 @@ void __init chrp_pcibios_fixup(void) { struct pci_dev *dev = NULL; - struct device_node *np; - /* PCI interrupts are controlled by the OpenPIC */ - for_each_pci_dev(dev) { - np = pci_device_to_OF_node(dev); - if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0)) - dev->irq = np->intrs[0].line; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } + for_each_pci_dev(dev) + pci_read_irq_line(dev); } #define PRG_CL_RESET_VALID 0x00010000 diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 1f1771b212b..538e337d63e 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -24,7 +24,7 @@ #include <linux/reboot.h> #include <linux/init.h> #include <linux/pci.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/adb.h> #include <linux/module.h> #include <linux/delay.h> @@ -59,7 +59,7 @@ void rtas_indicator_progress(char *, unsigned short); int _chrp_type; EXPORT_SYMBOL(_chrp_type); -struct mpic *chrp_mpic; +static struct mpic *chrp_mpic; /* Used for doing CHRP event-scans */ DEFINE_PER_CPU(struct timer_list, heartbeat_timer); @@ -315,24 +315,32 @@ chrp_event_scan(unsigned long unused) jiffies + event_scan_interval); } +static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs) +{ + unsigned int cascade_irq = i8259_irq(regs); + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq, regs); + desc->chip->eoi(irq); +} + /* * Finds the open-pic node and sets up the mpic driver. */ static void __init chrp_find_openpic(void) { struct device_node *np, *root; - int len, i, j, irq_count; + int len, i, j; int isu_size, idu_size; unsigned int *iranges, *opprop = NULL; int oplen = 0; unsigned long opaddr; int na = 1; - unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS]; - np = find_type_devices("open-pic"); + np = of_find_node_by_type(NULL, "open-pic"); if (np == NULL) return; - root = find_path_device("/"); + root = of_find_node_by_path("/"); if (root) { opprop = (unsigned int *) get_property (root, "platform-open-pic", &oplen); @@ -343,19 +351,15 @@ static void __init chrp_find_openpic(void) oplen /= na * sizeof(unsigned int); } else { struct resource r; - if (of_address_to_resource(np, 0, &r)) - return; + if (of_address_to_resource(np, 0, &r)) { + goto bail; + } opaddr = r.start; oplen = 0; } printk(KERN_INFO "OpenPIC at %lx\n", opaddr); - irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ - prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4); - /* i8259 cascade is always positive level */ - init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE; - iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); if (iranges == NULL) len = 0; /* non-distributed mpic */ @@ -382,15 +386,12 @@ static void __init chrp_find_openpic(void) if (len > 1) isu_size = iranges[3]; - chrp_mpic = mpic_alloc(opaddr, MPIC_PRIMARY, - isu_size, NUM_ISA_INTERRUPTS, irq_count, - NR_IRQS - 4, init_senses, irq_count, - " MPIC "); + chrp_mpic = mpic_alloc(np, opaddr, MPIC_PRIMARY, + isu_size, 0, " MPIC "); if (chrp_mpic == NULL) { printk(KERN_ERR "Failed to allocate MPIC structure\n"); - return; + goto bail; } - j = na - 1; for (i = 1; i < len; ++i) { iranges += 2; @@ -402,7 +403,10 @@ static void __init chrp_find_openpic(void) } mpic_init(chrp_mpic); - mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL); + ppc_md.get_irq = mpic_get_irq; + bail: + of_node_put(root); + of_node_put(np); } #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) @@ -413,14 +417,34 @@ static struct irqaction xmon_irqaction = { }; #endif -void __init chrp_init_IRQ(void) +static void __init chrp_find_8259(void) { - struct device_node *np; + struct device_node *np, *pic = NULL; unsigned long chrp_int_ack = 0; -#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) - struct device_node *kbd; -#endif + unsigned int cascade_irq; + + /* Look for cascade */ + for_each_node_by_type(np, "interrupt-controller") + if (device_is_compatible(np, "chrp,iic")) { + pic = np; + break; + } + /* Ok, 8259 wasn't found. We need to handle the case where + * we have a pegasos that claims to be chrp but doesn't have + * a proper interrupt tree + */ + if (pic == NULL && chrp_mpic != NULL) { + printk(KERN_ERR "i8259: Not found in device-tree" + " assuming no legacy interrupts\n"); + return; + } + /* Look for intack. In a perfect world, we would look for it on + * the ISA bus that holds the 8259 but heh... Works that way. If + * we ever see a problem, we can try to re-use the pSeries code here. + * Also, Pegasos-type platforms don't have a proper node to start + * from anyway + */ for (np = find_devices("pci"); np != NULL; np = np->next) { unsigned int *addrp = (unsigned int *) get_property(np, "8259-interrupt-acknowledge", NULL); @@ -431,11 +455,29 @@ void __init chrp_init_IRQ(void) break; } if (np == NULL) - printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n"); + printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" + " address, polling\n"); + + i8259_init(pic, chrp_int_ack); + if (ppc_md.get_irq == NULL) + ppc_md.get_irq = i8259_irq; + if (chrp_mpic != NULL) { + cascade_irq = irq_of_parse_and_map(pic, 0); + if (cascade_irq == NO_IRQ) + printk(KERN_ERR "i8259: failed to map cascade irq\n"); + else + set_irq_chained_handler(cascade_irq, + chrp_8259_cascade); + } +} +void __init chrp_init_IRQ(void) +{ +#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) + struct device_node *kbd; +#endif chrp_find_openpic(); - - i8259_init(chrp_int_ack, 0); + chrp_find_8259(); if (_chrp_type == _CHRP_Pegasos) ppc_md.get_irq = i8259_irq; @@ -520,10 +562,6 @@ static int __init chrp_probe(void) DMA_MODE_READ = 0x44; DMA_MODE_WRITE = 0x48; isa_io_base = CHRP_ISA_IO_BASE; /* default value */ - ppc_do_canonicalize_irqs = 1; - - /* Assume we have an 8259... */ - __irq_offset_value = NUM_ISA_INTERRUPTS; return 1; } @@ -535,7 +573,6 @@ define_machine(chrp) { .init = chrp_init2, .show_cpuinfo = chrp_show_cpuinfo, .init_IRQ = chrp_init_IRQ, - .get_irq = mpic_get_irq, .pcibios_fixup = chrp_pcibios_fixup, .restart = rtas_restart, .power_off = rtas_power_off, diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c index c298ca1ea68..1d2307e87c3 100644 --- a/arch/powerpc/platforms/chrp/smp.c +++ b/arch/powerpc/platforms/chrp/smp.c @@ -29,7 +29,6 @@ #include <asm/smp.h> #include <asm/residual.h> #include <asm/time.h> -#include <asm/open_pic.h> #include <asm/machdep.h> #include <asm/smp.h> #include <asm/mpic.h> diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index f70e820e730..2275e64f315 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -162,27 +162,6 @@ static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs) printk(KERN_ERR "pci_event_handler: NULL event received\n"); } -/* - * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c - * It must be called before the bus walk. - */ -void __init iSeries_init_IRQ(void) -{ - /* Register PCI event handler and open an event path */ - int ret; - - ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, - &pci_event_handler); - if (ret == 0) { - ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); - if (ret != 0) - printk(KERN_ERR "iseries_init_IRQ: open event path " - "failed with rc 0x%x\n", ret); - } else - printk(KERN_ERR "iseries_init_IRQ: register handler " - "failed with rc 0x%x\n", ret); -} - #define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff) #define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) #define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) @@ -196,7 +175,7 @@ static void iseries_enable_IRQ(unsigned int irq) { u32 bus, dev_id, function, mask; const u32 sub_bus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; + unsigned int rirq = (unsigned int)irq_map[irq].hwirq; /* The IRQ has already been locked by the caller */ bus = REAL_IRQ_TO_BUS(rirq); @@ -213,7 +192,7 @@ static unsigned int iseries_startup_IRQ(unsigned int irq) { u32 bus, dev_id, function, mask; const u32 sub_bus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; + unsigned int rirq = (unsigned int)irq_map[irq].hwirq; bus = REAL_IRQ_TO_BUS(rirq); function = REAL_IRQ_TO_FUNC(rirq); @@ -254,7 +233,7 @@ static void iseries_shutdown_IRQ(unsigned int irq) { u32 bus, dev_id, function, mask; const u32 sub_bus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; + unsigned int rirq = (unsigned int)irq_map[irq].hwirq; /* irq should be locked by the caller */ bus = REAL_IRQ_TO_BUS(rirq); @@ -277,7 +256,7 @@ static void iseries_disable_IRQ(unsigned int irq) { u32 bus, dev_id, function, mask; const u32 sub_bus = 0; - unsigned int rirq = virt_irq_to_real_map[irq]; + unsigned int rirq = (unsigned int)irq_map[irq].hwirq; /* The IRQ has already been locked by the caller */ bus = REAL_IRQ_TO_BUS(rirq); @@ -291,19 +270,19 @@ static void iseries_disable_IRQ(unsigned int irq) static void iseries_end_IRQ(unsigned int irq) { - unsigned int rirq = virt_irq_to_real_map[irq]; + unsigned int rirq = (unsigned int)irq_map[irq].hwirq; HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq), (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); } -static hw_irq_controller iSeries_IRQ_handler = { - .typename = "iSeries irq controller", - .startup = iseries_startup_IRQ, - .shutdown = iseries_shutdown_IRQ, - .enable = iseries_enable_IRQ, - .disable = iseries_disable_IRQ, - .end = iseries_end_IRQ +static struct irq_chip iseries_pic = { + .typename = "iSeries irq controller", + .startup = iseries_startup_IRQ, + .shutdown = iseries_shutdown_IRQ, + .unmask = iseries_enable_IRQ, + .mask = iseries_disable_IRQ, + .eoi = iseries_end_IRQ }; /* @@ -314,17 +293,14 @@ static hw_irq_controller iSeries_IRQ_handler = { int __init iSeries_allocate_IRQ(HvBusNumber bus, HvSubBusNumber sub_bus, u32 bsubbus) { - int virtirq; unsigned int realirq; u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) + function; - virtirq = virt_irq_create_mapping(realirq); - irq_desc[virtirq].chip = &iSeries_IRQ_handler; - return virtirq; + return irq_create_mapping(NULL, realirq, IRQ_TYPE_NONE); } #endif /* CONFIG_PCI */ @@ -332,10 +308,9 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, /* * Get the next pending IRQ. */ -int iSeries_get_irq(struct pt_regs *regs) +unsigned int iSeries_get_irq(struct pt_regs *regs) { - /* -2 means ignore this interrupt */ - int irq = -2; + int irq = NO_IRQ_IGNORE; #ifdef CONFIG_SMP if (get_lppaca()->int_dword.fields.ipi_cnt) { @@ -358,9 +333,57 @@ int iSeries_get_irq(struct pt_regs *regs) } spin_unlock(&pending_irqs_lock); if (irq >= NR_IRQS) - irq = -2; + irq = NO_IRQ_IGNORE; } #endif return irq; } + +static int iseries_irq_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq); + + return 0; +} + +static struct irq_host_ops iseries_irq_host_ops = { + .map = iseries_irq_host_map, +}; + +/* + * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c + * It must be called before the bus walk. + */ +void __init iSeries_init_IRQ(void) +{ + /* Register PCI event handler and open an event path */ + struct irq_host *host; + int ret; + + /* + * The Hypervisor only allows us up to 256 interrupt + * sources (the irq number is passed in a u8). + */ + irq_set_virq_count(256); + + /* Create irq host. No need for a revmap since HV will give us + * back our virtual irq number + */ + host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &iseries_irq_host_ops, 0); + BUG_ON(host == NULL); + irq_set_default_host(host); + + ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, + &pci_event_handler); + if (ret == 0) { + ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); + if (ret != 0) + printk(KERN_ERR "iseries_init_IRQ: open event path " + "failed with rc 0x%x\n", ret); + } else + printk(KERN_ERR "iseries_init_IRQ: register handler " + "failed with rc 0x%x\n", ret); +} + diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h index 188aa808abd..1ee8985140e 100644 --- a/arch/powerpc/platforms/iseries/irq.h +++ b/arch/powerpc/platforms/iseries/irq.h @@ -4,6 +4,6 @@ extern void iSeries_init_IRQ(void); extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32); extern void iSeries_activate_IRQs(void); -extern int iSeries_get_irq(struct pt_regs *); +extern unsigned int iSeries_get_irq(struct pt_regs *); #endif /* _ISERIES_IRQ_H */ diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index c877074745b..c9605d773a7 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -294,8 +294,6 @@ static void __init iSeries_init_early(void) { DBG(" -> iSeries_init_early()\n"); - ppc64_interrupt_controller = IC_ISERIES; - #if defined(CONFIG_BLK_DEV_INITRD) /* * If the init RAM disk has been configured and there is @@ -659,12 +657,6 @@ static int __init iseries_probe(void) powerpc_firmware_features |= FW_FEATURE_ISERIES; powerpc_firmware_features |= FW_FEATURE_LPAR; - /* - * The Hypervisor only allows us up to 256 interrupt - * sources (the irq number is passed in a u8). - */ - virt_irq_max = 255; - hpte_init_iSeries(); return 1; diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index f7170ff86da..63a1670d3bf 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -443,18 +443,23 @@ void __init maple_pci_init(void) int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel) { struct device_node *np; - int irq = channel ? 15 : 14; + unsigned int defirq = channel ? 15 : 14; + unsigned int irq; if (pdev->vendor != PCI_VENDOR_ID_AMD || pdev->device != PCI_DEVICE_ID_AMD_8111_IDE) - return irq; + return defirq; np = pci_device_to_OF_node(pdev); if (np == NULL) - return irq; - if (np->n_intrs < 2) - return irq; - return np->intrs[channel & 0x1].line; + return defirq; + irq = irq_of_parse_and_map(np, channel & 0x1); + if (irq == NO_IRQ) { + printk("Failed to map onboard IDE interrupt for channel %d\n", + channel); + return defirq; + } + return irq; } /* XXX: To remove once all firmwares are ok */ diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 5cf90c28b14..cb528c9de4c 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -11,7 +11,7 @@ * */ -#define DEBUG +#undef DEBUG #include <linux/init.h> #include <linux/errno.h> @@ -198,50 +198,81 @@ static void __init maple_init_early(void) { DBG(" -> maple_init_early\n"); - /* Setup interrupt mapping options */ - ppc64_interrupt_controller = IC_OPEN_PIC; - iommu_init_early_dart(); DBG(" <- maple_init_early\n"); } - -static __init void maple_init_IRQ(void) +/* + * This is almost identical to pSeries and CHRP. We need to make that + * code generic at one point, with appropriate bits in the device-tree to + * identify the presence of an HT APIC + */ +static void __init maple_init_IRQ(void) { - struct device_node *root; + struct device_node *root, *np, *mpic_node = NULL; unsigned int *opprop; - unsigned long opic_addr; + unsigned long openpic_addr = 0; + int naddr, n, i, opplen, has_isus = 0; struct mpic *mpic; - unsigned char senses[128]; - int n; + unsigned int flags = MPIC_PRIMARY; - DBG(" -> maple_init_IRQ\n"); + /* Locate MPIC in the device-tree. Note that there is a bug + * in Maple device-tree where the type of the controller is + * open-pic and not interrupt-controller + */ + for_each_node_by_type(np, "open-pic") { + mpic_node = np; + break; + } + if (mpic_node == NULL) { + printk(KERN_ERR + "Failed to locate the MPIC interrupt controller\n"); + return; + } - /* XXX: Non standard, replace that with a proper openpic/mpic node - * in the device-tree. Find the Open PIC if present */ + /* Find address list in /platform-open-pic */ root = of_find_node_by_path("/"); - opprop = (unsigned int *) get_property(root, - "platform-open-pic", NULL); - if (opprop == 0) - panic("OpenPIC not found !\n"); - - n = prom_n_addr_cells(root); - for (opic_addr = 0; n > 0; --n) - opic_addr = (opic_addr << 32) + *opprop++; + naddr = prom_n_addr_cells(root); + opprop = (unsigned int *) get_property(root, "platform-open-pic", + &opplen); + if (opprop != 0) { + openpic_addr = of_read_number(opprop, naddr); + has_isus = (opplen > naddr); + printk(KERN_DEBUG "OpenPIC addr: %lx, has ISUs: %d\n", + openpic_addr, has_isus); + } of_node_put(root); - /* Obtain sense values from device-tree */ - prom_get_irq_senses(senses, 0, 128); + BUG_ON(openpic_addr == 0); + + /* Check for a big endian MPIC */ + if (get_property(np, "big-endian", NULL) != NULL) + flags |= MPIC_BIG_ENDIAN; - mpic = mpic_alloc(opic_addr, - MPIC_PRIMARY | MPIC_BIG_ENDIAN | - MPIC_BROKEN_U3 | MPIC_WANTS_RESET, - 0, 0, 128, 128, senses, 128, "U3-MPIC"); + /* XXX Maple specific bits */ + flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET; + + /* Setup the openpic driver. More device-tree junks, we hard code no + * ISUs for now. I'll have to revisit some stuffs with the folks doing + * the firmware for those + */ + mpic = mpic_alloc(mpic_node, openpic_addr, flags, + /*has_isus ? 16 :*/ 0, 0, " MPIC "); BUG_ON(mpic == NULL); - mpic_init(mpic); - DBG(" <- maple_init_IRQ\n"); + /* Add ISUs */ + opplen /= sizeof(u32); + for (n = 0, i = naddr; i < opplen; i += naddr, n++) { + unsigned long isuaddr = of_read_number(opprop + i, naddr); + mpic_assign_isu(mpic, n, isuaddr); + } + + /* All ISUs are setup, complete initialization */ + mpic_init(mpic); + ppc_md.get_irq = mpic_get_irq; + of_node_put(mpic_node); + of_node_put(root); } static void __init maple_progress(char *s, unsigned short hex) @@ -256,7 +287,9 @@ static void __init maple_progress(char *s, unsigned short hex) static int __init maple_probe(void) { unsigned long root = of_get_flat_dt_root(); - if (!of_flat_dt_is_compatible(root, "Momentum,Maple")) + + if (!of_flat_dt_is_compatible(root, "Momentum,Maple") && + !of_flat_dt_is_compatible(root, "Momentum,Apache")) return 0; /* * On U3, the DART (iommu) must be allocated now since it @@ -277,7 +310,6 @@ define_machine(maple_md) { .setup_arch = maple_setup_arch, .init_early = maple_init_early, .init_IRQ = maple_init_IRQ, - .get_irq = mpic_get_irq, .pcibios_fixup = maple_pcibios_fixup, .pci_get_legacy_ide_irq = maple_pci_get_legacy_ide_irq, .restart = maple_restart, diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index cb257aeb91f..871b002c9f9 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c @@ -12,7 +12,7 @@ #include <linux/kernel.h> #include <linux/string.h> #include <linux/init.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <asm/sections.h> #include <asm/prom.h> #include <asm/page.h> @@ -162,6 +162,8 @@ static void __init bootx_add_chosen_props(unsigned long base, { u32 val; + bootx_dt_add_prop("linux,bootx", NULL, 0, mem_end); + if (bootx_info->kernelParamsOffset) { char *args = (char *)((unsigned long)bootx_info) + bootx_info->kernelParamsOffset; @@ -181,8 +183,25 @@ static void __init bootx_add_chosen_props(unsigned long base, static void __init bootx_add_display_props(unsigned long base, unsigned long *mem_end) { + boot_infos_t *bi = bootx_info; + u32 tmp; + bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end); bootx_dt_add_prop("linux,opened", NULL, 0, mem_end); + tmp = bi->dispDeviceDepth; + bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end); + tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0]; + bootx_dt_add_prop("linux,bootx-width", &tmp, 4, mem_end); + tmp = bi->dispDeviceRect[3] - bi->dispDeviceRect[1]; + bootx_dt_add_prop("linux,bootx-height", &tmp, 4, mem_end); + tmp = bi->dispDeviceRowBytes; + bootx_dt_add_prop("linux,bootx-linebytes", &tmp, 4, mem_end); + tmp = (u32)bi->dispDeviceBase; + if (tmp == 0) + tmp = (u32)bi->logicalDisplayBase; + tmp += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes; + tmp += bi->dispDeviceRect[0] * ((bi->dispDeviceDepth + 7) / 8); + bootx_dt_add_prop("linux,bootx-addr", &tmp, 4, mem_end); } static void __init bootx_dt_add_string(char *s, unsigned long *mem_end) @@ -211,7 +230,7 @@ static void __init bootx_scan_dt_build_strings(unsigned long base, if (!strcmp(namep, "/chosen")) { DBG(" detected /chosen ! adding properties names !\n"); - bootx_dt_add_string("linux,platform", mem_end); + bootx_dt_add_string("linux,bootx", mem_end); bootx_dt_add_string("linux,stdout-path", mem_end); bootx_dt_add_string("linux,initrd-start", mem_end); bootx_dt_add_string("linux,initrd-end", mem_end); @@ -222,6 +241,11 @@ static void __init bootx_scan_dt_build_strings(unsigned long base, DBG(" detected display ! adding properties names !\n"); bootx_dt_add_string("linux,boot-display", mem_end); bootx_dt_add_string("linux,opened", mem_end); + bootx_dt_add_string("linux,bootx-depth", mem_end); + bootx_dt_add_string("linux,bootx-width", mem_end); + bootx_dt_add_string("linux,bootx-height", mem_end); + bootx_dt_add_string("linux,bootx-linebytes", mem_end); + bootx_dt_add_string("linux,bootx-addr", mem_end); strncpy(bootx_disp_path, namep, 255); } @@ -443,7 +467,14 @@ void __init bootx_init(unsigned long r3, unsigned long r4) if (!BOOT_INFO_IS_V2_COMPATIBLE(bi)) bi->logicalDisplayBase = bi->dispDeviceBase; + /* Fixup depth 16 -> 15 as that's what MacOS calls 16bpp */ + if (bi->dispDeviceDepth == 16) + bi->dispDeviceDepth = 15; + #ifdef CONFIG_BOOTX_TEXT + ptr = (unsigned long)bi->logicalDisplayBase; + ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes; + ptr += bi->dispDeviceRect[0] * ((bi->dispDeviceDepth + 7) / 8); btext_setup_display(bi->dispDeviceRect[2] - bi->dispDeviceRect[0], bi->dispDeviceRect[3] - bi->dispDeviceRect[1], bi->dispDeviceDepth, bi->dispDeviceRowBytes, diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index ceafaf52a66..8677f50c258 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -522,10 +522,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) host->speed = KW_I2C_MODE_25KHZ; break; } - if (np->n_intrs > 0) - host->irq = np->intrs[0].line; - else - host->irq = NO_IRQ; + host->irq = irq_of_parse_and_map(np, 0); + if (host->irq == NO_IRQ) + printk(KERN_WARNING + "low_i2c: Failed to map interrupt for %s\n", + np->full_name); host->base = ioremap((*addrp), 0x1000); if (host->base == NULL) { diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 41fa2409482..6a36ea9bf67 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c @@ -29,6 +29,8 @@ #include <asm/machdep.h> #include <asm/nvram.h> +#include "pmac.h" + #define DEBUG #ifdef DEBUG @@ -80,9 +82,6 @@ static int nvram_partitions[3]; // XXX Turn that into a sem static DEFINE_SPINLOCK(nv_lock); -extern int pmac_newworld; -extern int system_running; - static int (*core99_write_bank)(int bank, u8* datas); static int (*core99_erase_bank)(int bank); diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index d524a915aa8..556b349797e 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -46,6 +46,9 @@ static int has_uninorth; static struct pci_controller *u3_agp; static struct pci_controller *u4_pcie; static struct pci_controller *u3_ht; +#define has_second_ohare 0 +#else +static int has_second_ohare; #endif /* CONFIG_PPC64 */ extern u8 pci_cache_line_size; @@ -647,6 +650,33 @@ static void __init init_p2pbridge(void) early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); } +static void __init init_second_ohare(void) +{ + struct device_node *np = of_find_node_by_name(NULL, "pci106b,7"); + unsigned char bus, devfn; + unsigned short cmd; + + if (np == NULL) + return; + + /* This must run before we initialize the PICs since the second + * ohare hosts a PIC that will be accessed there. + */ + if (pci_device_from_OF_node(np, &bus, &devfn) == 0) { + struct pci_controller* hose = + pci_find_hose_for_OF_device(np); + if (!hose) { + printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); + return; + } + early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + cmd &= ~PCI_COMMAND_IO; + early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); + } + has_second_ohare = 1; +} + /* * Some Apple desktop machines have a NEC PD720100A USB2 controller * on the motherboard. Open Firmware, on these, will disable the @@ -688,9 +718,6 @@ static void __init fixup_nec_usb2(void) " EHCI, fixing up...\n"); data &= ~1UL; early_write_config_dword(hose, bus, devfn, 0xe4, data); - early_write_config_byte(hose, bus, - devfn | 2, PCI_INTERRUPT_LINE, - nec->intrs[0].line); } } } @@ -958,32 +985,28 @@ static int __init add_bridge(struct device_node *dev) return 0; } -static void __init pcibios_fixup_OF_interrupts(void) +void __init pmac_pcibios_fixup(void) { struct pci_dev* dev = NULL; - /* - * Open Firmware often doesn't initialize the - * PCI_INTERRUPT_LINE config register properly, so we - * should find the device node and apply the interrupt - * obtained from the OF device-tree - */ for_each_pci_dev(dev) { - struct device_node *node; - node = pci_device_to_OF_node(dev); - /* this is the node, see if it has interrupts */ - if (node && node->n_intrs > 0) - dev->irq = node->intrs[0].line; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + /* Read interrupt from the device-tree */ + pci_read_irq_line(dev); + + /* Fixup interrupt for the modem/ethernet combo controller. + * on machines with a second ohare chip. + * The number in the device tree (27) is bogus (correct for + * the ethernet-only board but not the combo ethernet/modem + * board). The real interrupt is 28 on the second controller + * -> 28+32 = 60. + */ + if (has_second_ohare && + dev->vendor == PCI_VENDOR_ID_DEC && + dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) + dev->irq = irq_create_mapping(NULL, 60, 0); } } -void __init pmac_pcibios_fixup(void) -{ - /* Fixup interrupts according to OF tree */ - pcibios_fixup_OF_interrupts(); -} - #ifdef CONFIG_PPC64 static void __init pmac_fixup_phb_resources(void) { @@ -1071,6 +1094,7 @@ void __init pmac_pci_init(void) #else /* CONFIG_PPC64 */ init_p2pbridge(); + init_second_ohare(); fixup_nec_usb2(); /* We are still having some issues with the Xserve G4, enabling diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index d6eab8b3f7d..6d66359ec8c 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c @@ -24,19 +24,18 @@ static irqreturn_t macio_gpio_irq(int irq, void *data, struct pt_regs *regs) static int macio_do_gpio_irq_enable(struct pmf_function *func) { - if (func->node->n_intrs < 1) + unsigned int irq = irq_of_parse_and_map(func->node, 0); + if (irq == NO_IRQ) return -EINVAL; - - return request_irq(func->node->intrs[0].line, macio_gpio_irq, 0, - func->node->name, func); + return request_irq(irq, macio_gpio_irq, 0, func->node->name, func); } static int macio_do_gpio_irq_disable(struct pmf_function *func) { - if (func->node->n_intrs < 1) + unsigned int irq = irq_of_parse_and_map(func->node, 0); + if (irq == NO_IRQ) return -EINVAL; - - free_irq(func->node->intrs[0].line, func); + free_irq(irq, func); return 0; } diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 532bce57c0d..3d328bc1f7e 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -65,39 +65,36 @@ static u32 level_mask[4]; static DEFINE_SPINLOCK(pmac_pic_lock); -#define GATWICK_IRQ_POOL_SIZE 10 -static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; - #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; +static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; +static int pmac_irq_cascade = -1; +static struct irq_host *pmac_pic_host; -/* - * Mark an irq as "lost". This is only used on the pmac - * since it can lose interrupts (see pmac_set_irq_mask). - * -- Cort - */ -void __set_lost(unsigned long irq_nr, int nokick) +static void __pmac_retrigger(unsigned int irq_nr) { - if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { + if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) { + __set_bit(irq_nr, ppc_lost_interrupts); + irq_nr = pmac_irq_cascade; + mb(); + } + if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) { atomic_inc(&ppc_n_lost_interrupts); - if (!nokick) - set_dec(1); + set_dec(1); } } -static void pmac_mask_and_ack_irq(unsigned int irq_nr) +static void pmac_mask_and_ack_irq(unsigned int virq) { - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; + unsigned int src = irq_map[virq].hwirq; + unsigned long bit = 1UL << (virq & 0x1f); + int i = virq >> 5; unsigned long flags; - if ((unsigned)irq_nr >= max_irqs) - return; - - clear_bit(irq_nr, ppc_cached_irq_mask); - if (test_and_clear_bit(irq_nr, ppc_lost_interrupts)) - atomic_dec(&ppc_n_lost_interrupts); spin_lock_irqsave(&pmac_pic_lock, flags); + __clear_bit(src, ppc_cached_irq_mask); + if (__test_and_clear_bit(src, ppc_lost_interrupts)) + atomic_dec(&ppc_n_lost_interrupts); out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); out_le32(&pmac_irq_hw[i]->ack, bit); do { @@ -109,16 +106,29 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr) spin_unlock_irqrestore(&pmac_pic_lock, flags); } -static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) +static void pmac_ack_irq(unsigned int virq) +{ + unsigned int src = irq_map[virq].hwirq; + unsigned long bit = 1UL << (src & 0x1f); + int i = src >> 5; + unsigned long flags; + + spin_lock_irqsave(&pmac_pic_lock, flags); + if (__test_and_clear_bit(src, ppc_lost_interrupts)) + atomic_dec(&ppc_n_lost_interrupts); + out_le32(&pmac_irq_hw[i]->ack, bit); + (void)in_le32(&pmac_irq_hw[i]->ack); + spin_unlock_irqrestore(&pmac_pic_lock, flags); +} + +static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) { unsigned long bit = 1UL << (irq_nr & 0x1f); int i = irq_nr >> 5; - unsigned long flags; if ((unsigned)irq_nr >= max_irqs) return; - spin_lock_irqsave(&pmac_pic_lock, flags); /* enable unmasked interrupts */ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); @@ -135,71 +145,78 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) * the bit in the flag register or request another interrupt. */ if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) - __set_lost((ulong)irq_nr, nokicklost); - spin_unlock_irqrestore(&pmac_pic_lock, flags); + __pmac_retrigger(irq_nr); } /* When an irq gets requested for the first client, if it's an * edge interrupt, we clear any previous one on the controller */ -static unsigned int pmac_startup_irq(unsigned int irq_nr) +static unsigned int pmac_startup_irq(unsigned int virq) { - unsigned long bit = 1UL << (irq_nr & 0x1f); - int i = irq_nr >> 5; + unsigned long flags; + unsigned int src = irq_map[virq].hwirq; + unsigned long bit = 1UL << (src & 0x1f); + int i = src >> 5; - if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) + spin_lock_irqsave(&pmac_pic_lock, flags); + if ((irq_desc[virq].status & IRQ_LEVEL) == 0) out_le32(&pmac_irq_hw[i]->ack, bit); - set_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 0); + __set_bit(src, ppc_cached_irq_mask); + __pmac_set_irq_mask(src, 0); + spin_unlock_irqrestore(&pmac_pic_lock, flags); return 0; } -static void pmac_mask_irq(unsigned int irq_nr) +static void pmac_mask_irq(unsigned int virq) { - clear_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 0); - mb(); + unsigned long flags; + unsigned int src = irq_map[virq].hwirq; + + spin_lock_irqsave(&pmac_pic_lock, flags); + __clear_bit(src, ppc_cached_irq_mask); + __pmac_set_irq_mask(src, 0); + spin_unlock_irqrestore(&pmac_pic_lock, flags); } -static void pmac_unmask_irq(unsigned int irq_nr) +static void pmac_unmask_irq(unsigned int virq) { - set_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 0); + unsigned long flags; + unsigned int src = irq_map[virq].hwirq; + + spin_lock_irqsave(&pmac_pic_lock, flags); + __set_bit(src, ppc_cached_irq_mask); + __pmac_set_irq_mask(src, 0); + spin_unlock_irqrestore(&pmac_pic_lock, flags); } -static void pmac_end_irq(unsigned int irq_nr) +static int pmac_retrigger(unsigned int virq) { - if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) - && irq_desc[irq_nr].action) { - set_bit(irq_nr, ppc_cached_irq_mask); - pmac_set_irq_mask(irq_nr, 1); - } -} + unsigned long flags; + spin_lock_irqsave(&pmac_pic_lock, flags); + __pmac_retrigger(irq_map[virq].hwirq); + spin_unlock_irqrestore(&pmac_pic_lock, flags); + return 1; +} -struct hw_interrupt_type pmac_pic = { +static struct irq_chip pmac_pic = { .typename = " PMAC-PIC ", .startup = pmac_startup_irq, - .enable = pmac_unmask_irq, - .disable = pmac_mask_irq, - .ack = pmac_mask_and_ack_irq, - .end = pmac_end_irq, -}; - -struct hw_interrupt_type gatwick_pic = { - .typename = " GATWICK ", - .startup = pmac_startup_irq, - .enable = pmac_unmask_irq, - .disable = pmac_mask_irq, - .ack = pmac_mask_and_ack_irq, - .end = pmac_end_irq, + .mask = pmac_mask_irq, + .ack = pmac_ack_irq, + .mask_ack = pmac_mask_and_ack_irq, + .unmask = pmac_unmask_irq, + .retrigger = pmac_retrigger, }; static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) { + unsigned long flags; int irq, bits; + int rc = IRQ_NONE; + spin_lock_irqsave(&pmac_pic_lock, flags); for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { int i = irq >> 5; bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; @@ -209,17 +226,20 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) if (bits == 0) continue; irq += __ilog2(bits); + spin_unlock_irqrestore(&pmac_pic_lock, flags); __do_IRQ(irq, regs); - return IRQ_HANDLED; + spin_lock_irqsave(&pmac_pic_lock, flags); + rc = IRQ_HANDLED; } - printk("gatwick irq not from gatwick pic\n"); - return IRQ_NONE; + spin_unlock_irqrestore(&pmac_pic_lock, flags); + return rc; } -static int pmac_get_irq(struct pt_regs *regs) +static unsigned int pmac_pic_get_irq(struct pt_regs *regs) { int irq; unsigned long bits = 0; + unsigned long flags; #ifdef CONFIG_SMP void psurge_smp_message_recv(struct pt_regs *); @@ -227,9 +247,10 @@ static int pmac_get_irq(struct pt_regs *regs) /* IPI's are a hack on the powersurge -- Cort */ if ( smp_processor_id() != 0 ) { psurge_smp_message_recv(regs); - return -2; /* ignore, already handled */ + return NO_IRQ_IGNORE; /* ignore, already handled */ } #endif /* CONFIG_SMP */ + spin_lock_irqsave(&pmac_pic_lock, flags); for (irq = max_real_irqs; (irq -= 32) >= 0; ) { int i = irq >> 5; bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; @@ -241,133 +262,10 @@ static int pmac_get_irq(struct pt_regs *regs) irq += __ilog2(bits); break; } - - return irq; -} - -/* This routine will fix some missing interrupt values in the device tree - * on the gatwick mac-io controller used by some PowerBooks - * - * Walking of OF nodes could use a bit more fixing up here, but it's not - * very important as this is all boot time code on static portions of the - * device-tree. - * - * However, the modifications done to "intrs" will have to be removed and - * replaced with proper updates of the "interrupts" properties or - * AAPL,interrupts, yet to be decided, once the dynamic parsing is there. - */ -static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, - int irq_base) -{ - struct device_node *node; - int count; - - memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); - count = 0; - for (node = NULL; (node = of_get_next_child(gw, node)) != NULL;) { - /* Fix SCC */ - if ((strcasecmp(node->name, "escc") == 0) && node->child) { - if (node->child->n_intrs < 3) { - node->child->intrs = &gatwick_int_pool[count]; - count += 3; - } - node->child->n_intrs = 3; - node->child->intrs[0].line = 15+irq_base; - node->child->intrs[1].line = 4+irq_base; - node->child->intrs[2].line = 5+irq_base; - printk(KERN_INFO "irq: fixed SCC on gatwick" - " (%d,%d,%d)\n", - node->child->intrs[0].line, - node->child->intrs[1].line, - node->child->intrs[2].line); - } - /* Fix media-bay & left SWIM */ - if (strcasecmp(node->name, "media-bay") == 0) { - struct device_node* ya_node; - - if (node->n_intrs == 0) - node->intrs = &gatwick_int_pool[count++]; - node->n_intrs = 1; - node->intrs[0].line = 29+irq_base; - printk(KERN_INFO "irq: fixed media-bay on gatwick" - " (%d)\n", node->intrs[0].line); - - ya_node = node->child; - while(ya_node) { - if (strcasecmp(ya_node->name, "floppy") == 0) { - if (ya_node->n_intrs < 2) { - ya_node->intrs = &gatwick_int_pool[count]; - count += 2; - } - ya_node->n_intrs = 2; - ya_node->intrs[0].line = 19+irq_base; - ya_node->intrs[1].line = 1+irq_base; - printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", - ya_node->intrs[0].line, ya_node->intrs[1].line); - } - if (strcasecmp(ya_node->name, "ata4") == 0) { - if (ya_node->n_intrs < 2) { - ya_node->intrs = &gatwick_int_pool[count]; - count += 2; - } - ya_node->n_intrs = 2; - ya_node->intrs[0].line = 14+irq_base; - ya_node->intrs[1].line = 3+irq_base; - printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", - ya_node->intrs[0].line, ya_node->intrs[1].line); - } - ya_node = ya_node->sibling; - } - } - } - if (count > 10) { - printk("WARNING !! Gatwick interrupt pool overflow\n"); - printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); - printk(" requested = %d\n", count); - } -} - -/* - * The PowerBook 3400/2400/3500 can have a combo ethernet/modem - * card which includes an ohare chip that acts as a second interrupt - * controller. If we find this second ohare, set it up and fix the - * interrupt value in the device tree for the ethernet chip. - */ -static void __init enable_second_ohare(struct device_node *np) -{ - unsigned char bus, devfn; - unsigned short cmd; - struct device_node *ether; - - /* This code doesn't strictly belong here, it could be part of - * either the PCI initialisation or the feature code. It's kept - * here for historical reasons. - */ - if (pci_device_from_OF_node(np, &bus, &devfn) == 0) { - struct pci_controller* hose = - pci_find_hose_for_OF_device(np); - if (!hose) { - printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); - return; - } - early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - cmd &= ~PCI_COMMAND_IO; - early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); - } - - /* Fix interrupt for the modem/ethernet combo controller. The number - * in the device tree (27) is bogus (correct for the ethernet-only - * board but not the combo ethernet/modem board). - * The real interrupt is 28 on the second controller -> 28+32 = 60. - */ - ether = of_find_node_by_name(NULL, "pci1011,14"); - if (ether && ether->n_intrs > 0) { - ether->intrs[0].line = 60; - printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", - ether->intrs[0].line); - } - of_node_put(ether); + spin_unlock_irqrestore(&pmac_pic_lock, flags); + if (unlikely(irq < 0)) + return NO_IRQ; + return irq_linear_revmap(pmac_pic_host, irq); } #ifdef CONFIG_XMON @@ -381,22 +279,65 @@ static struct irqaction xmon_action = { static struct irqaction gatwick_cascade_action = { .handler = gatwick_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "cascade", }; +static int pmac_pic_host_match(struct irq_host *h, struct device_node *node) +{ + /* We match all, we don't always have a node anyway */ + return 1; +} + +static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + struct irq_desc *desc = get_irq_desc(virq); + int level; + + if (hw >= max_irqs) + return -EINVAL; + + /* Mark level interrupts, set delayed disable for edge ones and set + * handlers + */ + level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f))); + if (level) + desc->status |= IRQ_LEVEL; + else + desc->status |= IRQ_DELAYED_DISABLE; + set_irq_chip_and_handler(virq, &pmac_pic, level ? + handle_level_irq : handle_edge_irq); + return 0; +} + +static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, + unsigned int *out_flags) + +{ + *out_hwirq = *intspec; + return 0; +} + +static struct irq_host_ops pmac_pic_host_ops = { + .match = pmac_pic_host_match, + .map = pmac_pic_host_map, + .xlate = pmac_pic_host_xlate, +}; + static void __init pmac_pic_probe_oldstyle(void) { int i; - int irq_cascade = -1; struct device_node *master = NULL; struct device_node *slave = NULL; u8 __iomem *addr; struct resource r; /* Set our get_irq function */ - ppc_md.get_irq = pmac_get_irq; + ppc_md.get_irq = pmac_pic_get_irq; /* * Find the interrupt controller type & node @@ -414,7 +355,6 @@ static void __init pmac_pic_probe_oldstyle(void) if (slave) { max_irqs = 64; level_mask[1] = OHARE_LEVEL_MASK; - enable_second_ohare(slave); } } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) { max_irqs = max_real_irqs = 64; @@ -438,14 +378,18 @@ static void __init pmac_pic_probe_oldstyle(void) max_irqs = 128; level_mask[2] = HEATHROW_LEVEL_MASK; level_mask[3] = 0; - pmac_fix_gatwick_interrupts(slave, max_real_irqs); } } BUG_ON(master == NULL); - /* Set the handler for the main PIC */ - for ( i = 0; i < max_real_irqs ; i++ ) - irq_desc[i].chip = &pmac_pic; + /* + * Allocate an irq host + */ + pmac_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, max_irqs, + &pmac_pic_host_ops, + max_irqs); + BUG_ON(pmac_pic_host == NULL); + irq_set_default_host(pmac_pic_host); /* Get addresses of first controller if we have a node for it */ BUG_ON(of_address_to_resource(master, 0, &r)); @@ -472,39 +416,38 @@ static void __init pmac_pic_probe_oldstyle(void) pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *) (addr + 0x10); - irq_cascade = slave->intrs[0].line; + pmac_irq_cascade = irq_of_parse_and_map(slave, 0); printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" " cascade: %d\n", slave->full_name, - max_irqs - max_real_irqs, irq_cascade); + max_irqs - max_real_irqs, pmac_irq_cascade); } of_node_put(slave); - /* disable all interrupts in all controllers */ + /* Disable all interrupts in all controllers */ for (i = 0; i * 32 < max_irqs; ++i) out_le32(&pmac_irq_hw[i]->enable, 0); - /* mark level interrupts */ - for (i = 0; i < max_irqs; i++) - if (level_mask[i >> 5] & (1UL << (i & 0x1f))) - irq_desc[i].status = IRQ_LEVEL; + /* Hookup cascade irq */ + if (slave && pmac_irq_cascade != NO_IRQ) + setup_irq(pmac_irq_cascade, &gatwick_cascade_action); - /* Setup handlers for secondary controller and hook cascade irq*/ - if (slave) { - for ( i = max_real_irqs ; i < max_irqs ; i++ ) - irq_desc[i].chip = &gatwick_pic; - setup_irq(irq_cascade, &gatwick_cascade_action); - } printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); #ifdef CONFIG_XMON - setup_irq(20, &xmon_action); + setup_irq(irq_create_mapping(NULL, 20, 0), &xmon_action); #endif } #endif /* CONFIG_PPC32 */ -static int pmac_u3_cascade(struct pt_regs *regs, void *data) +static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs) { - return mpic_get_one_irq((struct mpic *)data, regs); + struct mpic *mpic = desc->handler_data; + + unsigned int cascade_irq = mpic_get_one_irq(mpic, regs); + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq, regs); + desc->chip->eoi(irq); } static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) @@ -514,21 +457,20 @@ static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) int nmi_irq; pswitch = of_find_node_by_name(NULL, "programmer-switch"); - if (pswitch && pswitch->n_intrs) { - nmi_irq = pswitch->intrs[0].line; - mpic_irq_set_priority(nmi_irq, 9); - setup_irq(nmi_irq, &xmon_action); + if (pswitch) { + nmi_irq = irq_of_parse_and_map(pswitch, 0); + if (nmi_irq != NO_IRQ) { + mpic_irq_set_priority(nmi_irq, 9); + setup_irq(nmi_irq, &xmon_action); + } + of_node_put(pswitch); } - of_node_put(pswitch); #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ } static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, int master) { - unsigned char senses[128]; - int offset = master ? 0 : 128; - int count = master ? 128 : 124; const char *name = master ? " MPIC 1 " : " MPIC 2 "; struct resource r; struct mpic *mpic; @@ -541,8 +483,6 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); - prom_get_irq_senses(senses, offset, offset + count); - flags |= MPIC_WANTS_RESET; if (get_property(np, "big-endian", NULL)) flags |= MPIC_BIG_ENDIAN; @@ -553,8 +493,7 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, if (master && (flags & MPIC_BIG_ENDIAN)) flags |= MPIC_BROKEN_U3; - mpic = mpic_alloc(r.start, flags, 0, offset, count, master ? 252 : 0, - senses, count, name); + mpic = mpic_alloc(np, r.start, flags, 0, 0, name); if (mpic == NULL) return NULL; @@ -567,6 +506,7 @@ static int __init pmac_pic_probe_mpic(void) { struct mpic *mpic1, *mpic2; struct device_node *np, *master = NULL, *slave = NULL; + unsigned int cascade; /* We can have up to 2 MPICs cascaded */ for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) @@ -603,8 +543,15 @@ static int __init pmac_pic_probe_mpic(void) of_node_put(master); /* No slave, let's go out */ - if (slave == NULL || slave->n_intrs < 1) + if (slave == NULL) + return 0; + + /* Get/Map slave interrupt */ + cascade = irq_of_parse_and_map(slave, 0); + if (cascade == NO_IRQ) { + printk(KERN_ERR "Failed to map cascade IRQ\n"); return 0; + } mpic2 = pmac_setup_one_mpic(slave, 0); if (mpic2 == NULL) { @@ -612,7 +559,8 @@ static int __init pmac_pic_probe_mpic(void) of_node_put(slave); return 0; } - mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); + set_irq_data(cascade, mpic2); + set_irq_chained_handler(cascade, pmac_u3_cascade); of_node_put(slave); return 0; @@ -621,6 +569,19 @@ static int __init pmac_pic_probe_mpic(void) void __init pmac_pic_init(void) { + unsigned int flags = 0; + + /* We configure the OF parsing based on our oldworld vs. newworld + * platform type and wether we were booted by BootX. + */ +#ifdef CONFIG_PPC32 + if (!pmac_newworld) + flags |= OF_IMAP_OLDWORLD_MAC; + if (get_property(of_chosen, "linux,bootx", NULL) != NULL) + flags |= OF_IMAP_NO_PHANDLE; + of_irq_map_init(flags); +#endif /* CONFIG_PPC_32 */ + /* We first try to detect Apple's new Core99 chipset, since mac-io * is quite different on those machines and contains an IBM MPIC2. */ @@ -643,6 +604,7 @@ unsigned long sleep_save_mask[2]; /* This used to be passed by the PMU driver but that link got * broken with the new driver model. We use this tweak for now... + * We really want to do things differently though... */ static int pmacpic_find_viaint(void) { @@ -656,7 +618,7 @@ static int pmacpic_find_viaint(void) np = of_find_node_by_name(NULL, "via-pmu"); if (np == NULL) goto not_found; - viaint = np->intrs[0].line; + viaint = irq_of_parse_and_map(np, 0);; #endif /* CONFIG_ADB_PMU */ not_found: diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 21c7b0f8f32..94e7b24b840 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h @@ -12,6 +12,8 @@ struct rtc_time; +extern int pmac_newworld; + extern long pmac_time_init(void); extern unsigned long pmac_get_boot_time(void); extern void pmac_get_rtc_time(struct rtc_time *); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 8654b5f0783..31a9da769fa 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -613,9 +613,6 @@ static void __init pmac_init_early(void) udbg_adb_init(!!strstr(cmd_line, "btextdbg")); #ifdef CONFIG_PPC64 - /* Setup interrupt mapping options */ - ppc64_interrupt_controller = IC_OPEN_PIC; - iommu_init_early_dart(); #endif } diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 63affcb2421..827b7121ffb 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -377,7 +377,7 @@ static void __init psurge_dual_sync_tb(int cpu_nr) static struct irqaction psurge_irqaction = { .handler = psurge_primary_intr, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "primary IPI", }; diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 9639c66b453..9df783088b6 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -72,32 +72,62 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id, /* #define DEBUG */ -static void request_ras_irqs(struct device_node *np, char *propname, + +static void request_ras_irqs(struct device_node *np, irqreturn_t (*handler)(int, void *, struct pt_regs *), const char *name) { - unsigned int *ireg, len, i; - int virq, n_intr; - - ireg = (unsigned int *)get_property(np, propname, &len); - if (ireg == NULL) - return; - n_intr = prom_n_intr_cells(np); - len /= n_intr * sizeof(*ireg); - - for (i = 0; i < len; i++) { - virq = virt_irq_create_mapping(*ireg); - if (virq == NO_IRQ) { - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", np->full_name); - return; + int i, index, count = 0; + struct of_irq oirq; + u32 *opicprop; + unsigned int opicplen; + unsigned int virqs[16]; + + /* Check for obsolete "open-pic-interrupt" property. If present, then + * map those interrupts using the default interrupt host and default + * trigger + */ + opicprop = (u32 *)get_property(np, "open-pic-interrupt", &opicplen); + if (opicprop) { + opicplen /= sizeof(u32); + for (i = 0; i < opicplen; i++) { + if (count > 15) + break; + virqs[count] = irq_create_mapping(NULL, *(opicprop++), + IRQ_TYPE_NONE); + if (virqs[count] == NO_IRQ) + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", np->full_name); + else + count++; + } - if (request_irq(irq_offset_up(virq), handler, 0, name, NULL)) { + } + /* Else use normal interrupt tree parsing */ + else { + /* First try to do a proper OF tree parsing */ + for (index = 0; of_irq_map_one(np, index, &oirq) == 0; + index++) { + if (count > 15) + break; + virqs[count] = irq_create_of_mapping(oirq.controller, + oirq.specifier, + oirq.size); + if (virqs[count] == NO_IRQ) + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", np->full_name); + else + count++; + } + } + + /* Now request them */ + for (i = 0; i < count; i++) { + if (request_irq(virqs[i], handler, 0, name, NULL)) { printk(KERN_ERR "Unable to request interrupt %d for " - "%s\n", irq_offset_up(virq), np->full_name); + "%s\n", virqs[i], np->full_name); return; } - ireg += n_intr; } } @@ -115,20 +145,14 @@ static int __init init_ras_IRQ(void) /* Internal Errors */ np = of_find_node_by_path("/event-sources/internal-errors"); if (np != NULL) { - request_ras_irqs(np, "open-pic-interrupt", ras_error_interrupt, - "RAS_ERROR"); - request_ras_irqs(np, "interrupts", ras_error_interrupt, - "RAS_ERROR"); + request_ras_irqs(np, ras_error_interrupt, "RAS_ERROR"); of_node_put(np); } /* EPOW Events */ np = of_find_node_by_path("/event-sources/epow-events"); if (np != NULL) { - request_ras_irqs(np, "open-pic-interrupt", ras_epow_interrupt, - "RAS_EPOW"); - request_ras_irqs(np, "interrupts", ras_epow_interrupt, - "RAS_EPOW"); + request_ras_irqs(np, ras_epow_interrupt, "RAS_EPOW"); of_node_put(np); } @@ -162,7 +186,7 @@ ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs) status = rtas_call(ras_check_exception_token, 6, 1, NULL, RAS_VECTOR_OFFSET, - virt_irq_to_real(irq_offset_down(irq)), + irq_map[irq].hwirq, RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, critical, __pa(&ras_log_buf), rtas_get_error_log_max()); @@ -198,7 +222,7 @@ ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs) status = rtas_call(ras_check_exception_token, 6, 1, NULL, RAS_VECTOR_OFFSET, - virt_irq_to_real(irq_offset_down(irq)), + irq_map[irq].hwirq, RTAS_INTERNAL_ERROR, 1 /*Time Critical */, __pa(&ras_log_buf), rtas_get_error_log_max()); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 999509d28af..54a52437265 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -76,6 +76,9 @@ #define DBG(fmt...) #endif +/* move those away to a .h */ +extern void smp_init_pseries_mpic(void); +extern void smp_init_pseries_xics(void); extern void find_udbg_vterm(void); int fwnmi_active; /* TRUE if an FWNMI handler is present */ @@ -83,7 +86,7 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */ static void pseries_shared_idle_sleep(void); static void pseries_dedicated_idle_sleep(void); -struct mpic *pSeries_mpic; +static struct device_node *pSeries_mpic_node; static void pSeries_show_cpuinfo(struct seq_file *m) { @@ -118,63 +121,92 @@ static void __init fwnmi_init(void) fwnmi_active = 1; } -static void __init pSeries_init_mpic(void) +void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs) { - unsigned int *addrp; - struct device_node *np; - unsigned long intack = 0; - - /* All ISUs are setup, complete initialization */ - mpic_init(pSeries_mpic); - - /* Check what kind of cascade ACK we have */ - if (!(np = of_find_node_by_name(NULL, "pci")) - || !(addrp = (unsigned int *) - get_property(np, "8259-interrupt-acknowledge", NULL))) - printk(KERN_ERR "Cannot find pci to get ack address\n"); - else - intack = addrp[prom_n_addr_cells(np)-1]; - of_node_put(np); - - /* Setup the legacy interrupts & controller */ - i8259_init(intack, 0); - - /* Hook cascade to mpic */ - mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL); + unsigned int cascade_irq = i8259_irq(regs); + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq, regs); + desc->chip->eoi(irq); } -static void __init pSeries_setup_mpic(void) +static void __init pseries_mpic_init_IRQ(void) { + struct device_node *np, *old, *cascade = NULL; + unsigned int *addrp; + unsigned long intack = 0; unsigned int *opprop; unsigned long openpic_addr = 0; - unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS]; - struct device_node *root; - int irq_count; + unsigned int cascade_irq; + int naddr, n, i, opplen; + struct mpic *mpic; - /* Find the Open PIC if present */ - root = of_find_node_by_path("/"); - opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); + np = of_find_node_by_path("/"); + naddr = prom_n_addr_cells(np); + opprop = (unsigned int *) get_property(np, "platform-open-pic", &opplen); if (opprop != 0) { - int n = prom_n_addr_cells(root); - - for (openpic_addr = 0; n > 0; --n) - openpic_addr = (openpic_addr << 32) + *opprop++; + openpic_addr = of_read_number(opprop, naddr); printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr); } - of_node_put(root); + of_node_put(np); BUG_ON(openpic_addr == 0); - /* Get the sense values from OF */ - prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS); - /* Setup the openpic driver */ - irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */ - pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY, - 16, 16, irq_count, /* isu size, irq offset, irq count */ - NR_IRQS - 4, /* ipi offset */ - senses, irq_count, /* sense & sense size */ - " MPIC "); + mpic = mpic_alloc(pSeries_mpic_node, openpic_addr, + MPIC_PRIMARY, + 16, 250, /* isu size, irq count */ + " MPIC "); + BUG_ON(mpic == NULL); + + /* Add ISUs */ + opplen /= sizeof(u32); + for (n = 0, i = naddr; i < opplen; i += naddr, n++) { + unsigned long isuaddr = of_read_number(opprop + i, naddr); + mpic_assign_isu(mpic, n, isuaddr); + } + + /* All ISUs are setup, complete initialization */ + mpic_init(mpic); + + /* Look for cascade */ + for_each_node_by_type(np, "interrupt-controller") + if (device_is_compatible(np, "chrp,iic")) { + cascade = np; + break; + } + if (cascade == NULL) + return; + + cascade_irq = irq_of_parse_and_map(cascade, 0); + if (cascade == NO_IRQ) { + printk(KERN_ERR "xics: failed to map cascade interrupt"); + return; + } + + /* Check ACK type */ + for (old = of_node_get(cascade); old != NULL ; old = np) { + np = of_get_parent(old); + of_node_put(old); + if (np == NULL) + break; + if (strcmp(np->name, "pci") != 0) + continue; + addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", + NULL); + if (addrp == NULL) + continue; + naddr = prom_n_addr_cells(np); + intack = addrp[naddr-1]; + if (naddr > 1) + intack |= ((unsigned long)addrp[naddr-2]) << 32; + } + if (intack) + printk(KERN_DEBUG "mpic: PCI 8259 intack at 0x%016lx\n", + intack); + i8259_init(cascade, intack); + of_node_put(cascade); + set_irq_chained_handler(cascade_irq, pseries_8259_cascade); } static void pseries_lpar_enable_pmcs(void) @@ -192,23 +224,67 @@ static void pseries_lpar_enable_pmcs(void) get_lppaca()->pmcregs_in_use = 1; } -static void __init pSeries_setup_arch(void) +#ifdef CONFIG_KEXEC +static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary) { - /* Fixup ppc_md depending on the type of interrupt controller */ - if (ppc64_interrupt_controller == IC_OPEN_PIC) { - ppc_md.init_IRQ = pSeries_init_mpic; - ppc_md.get_irq = mpic_get_irq; - /* Allocate the mpic now, so that find_and_init_phbs() can - * fill the ISUs */ - pSeries_setup_mpic(); - } else { - ppc_md.init_IRQ = xics_init_IRQ; - ppc_md.get_irq = xics_get_irq; + mpic_teardown_this_cpu(secondary); +} + +static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) +{ + /* Don't risk a hypervisor call if we're crashing */ + if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { + unsigned long vpa = __pa(get_lppaca()); + + if (unregister_vpa(hard_smp_processor_id(), vpa)) { + printk("VPA deregistration of cpu %u (hw_cpu_id %d) " + "failed\n", smp_processor_id(), + hard_smp_processor_id()); + } } + xics_teardown_cpu(secondary); +} +#endif /* CONFIG_KEXEC */ +static void __init pseries_discover_pic(void) +{ + struct device_node *np; + char *typep; + + for (np = NULL; (np = of_find_node_by_name(np, + "interrupt-controller"));) { + typep = (char *)get_property(np, "compatible", NULL); + if (strstr(typep, "open-pic")) { + pSeries_mpic_node = of_node_get(np); + ppc_md.init_IRQ = pseries_mpic_init_IRQ; + ppc_md.get_irq = mpic_get_irq; +#ifdef CONFIG_KEXEC + ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic; +#endif +#ifdef CONFIG_SMP + smp_init_pseries_mpic(); +#endif + return; + } else if (strstr(typep, "ppc-xicp")) { + ppc_md.init_IRQ = xics_init_IRQ; +#ifdef CONFIG_KEXEC + ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics; +#endif #ifdef CONFIG_SMP - smp_init_pSeries(); + smp_init_pseries_xics(); #endif + return; + } + } + printk(KERN_ERR "pSeries_discover_pic: failed to recognize" + " interrupt-controller\n"); +} + +static void __init pSeries_setup_arch(void) +{ + /* Discover PIC type and setup ppc_md accordingly */ + pseries_discover_pic(); + /* openpic global configuration register (64-bit format). */ /* openpic Interrupt Source Unit pointer (64-bit format). */ /* python0 facility area (mmio) (64-bit format) REAL address. */ @@ -260,41 +336,11 @@ static int __init pSeries_init_panel(void) } arch_initcall(pSeries_init_panel); -static void __init pSeries_discover_pic(void) -{ - struct device_node *np; - char *typep; - - /* - * Setup interrupt mapping options that are needed for finish_device_tree - * to properly parse the OF interrupt tree & do the virtual irq mapping - */ - __irq_offset_value = NUM_ISA_INTERRUPTS; - ppc64_interrupt_controller = IC_INVALID; - for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) { - typep = (char *)get_property(np, "compatible", NULL); - if (strstr(typep, "open-pic")) { - ppc64_interrupt_controller = IC_OPEN_PIC; - break; - } else if (strstr(typep, "ppc-xicp")) { - ppc64_interrupt_controller = IC_PPC_XIC; - break; - } - } - if (ppc64_interrupt_controller == IC_INVALID) - printk("pSeries_discover_pic: failed to recognize" - " interrupt-controller\n"); - -} - static void pSeries_mach_cpu_die(void) { local_irq_disable(); idle_task_exit(); - /* Some hardware requires clearing the CPPR, while other hardware does not - * it is safe either way - */ - pSeriesLP_cppr_info(0, 0); + xics_teardown_cpu(0); rtas_stop_self(); /* Should never get here... */ BUG(); @@ -332,8 +378,6 @@ static void __init pSeries_init_early(void) iommu_init_early_pSeries(); - pSeries_discover_pic(); - DBG(" <- pSeries_init_early()\n"); } @@ -505,27 +549,6 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) return PCI_PROBE_NORMAL; } -#ifdef CONFIG_KEXEC -static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) -{ - /* Don't risk a hypervisor call if we're crashing */ - if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { - unsigned long vpa = __pa(get_lppaca()); - - if (unregister_vpa(hard_smp_processor_id(), vpa)) { - printk("VPA deregistration of cpu %u (hw_cpu_id %d) " - "failed\n", smp_processor_id(), - hard_smp_processor_id()); - } - } - - if (ppc64_interrupt_controller == IC_OPEN_PIC) - mpic_teardown_this_cpu(secondary); - else - xics_teardown_cpu(secondary); -} -#endif - define_machine(pseries) { .name = "pSeries", .probe = pSeries_probe, @@ -550,7 +573,6 @@ define_machine(pseries) { .system_reset_exception = pSeries_system_reset_exception, .machine_check_exception = pSeries_machine_check_exception, #ifdef CONFIG_KEXEC - .kexec_cpu_down = pseries_kexec_cpu_down, .machine_kexec = default_machine_kexec, .machine_kexec_prepare = default_machine_kexec_prepare, .machine_crash_shutdown = default_machine_crash_shutdown, diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 4ad144df49c..ac61098ff40 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -416,27 +416,12 @@ static struct smp_ops_t pSeries_xics_smp_ops = { #endif /* This is called very early */ -void __init smp_init_pSeries(void) +static void __init smp_init_pseries(void) { int i; DBG(" -> smp_init_pSeries()\n"); - switch (ppc64_interrupt_controller) { -#ifdef CONFIG_MPIC - case IC_OPEN_PIC: - smp_ops = &pSeries_mpic_smp_ops; - break; -#endif -#ifdef CONFIG_XICS - case IC_PPC_XIC: - smp_ops = &pSeries_xics_smp_ops; - break; -#endif - default: - panic("Invalid interrupt controller"); - } - #ifdef CONFIG_HOTPLUG_CPU smp_ops->cpu_disable = pSeries_cpu_disable; smp_ops->cpu_die = pSeries_cpu_die; @@ -471,3 +456,18 @@ void __init smp_init_pSeries(void) DBG(" <- smp_init_pSeries()\n"); } +#ifdef CONFIG_MPIC +void __init smp_init_pseries_mpic(void) +{ + smp_ops = &pSeries_mpic_smp_ops; + + smp_init_pseries(); +} +#endif + +void __init smp_init_pseries_xics(void) +{ + smp_ops = &pSeries_xics_smp_ops; + + smp_init_pseries(); +} diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 4d935d0817f..716972aa977 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -8,6 +8,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +#undef DEBUG + #include <linux/types.h> #include <linux/threads.h> #include <linux/kernel.h> @@ -19,6 +22,7 @@ #include <linux/gfp.h> #include <linux/radix-tree.h> #include <linux/cpu.h> + #include <asm/firmware.h> #include <asm/prom.h> #include <asm/io.h> @@ -31,26 +35,6 @@ #include "xics.h" -static unsigned int xics_startup(unsigned int irq); -static void xics_enable_irq(unsigned int irq); -static void xics_disable_irq(unsigned int irq); -static void xics_mask_and_ack_irq(unsigned int irq); -static void xics_end_irq(unsigned int irq); -static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask); - -static struct hw_interrupt_type xics_pic = { - .typename = " XICS ", - .startup = xics_startup, - .enable = xics_enable_irq, - .disable = xics_disable_irq, - .ack = xics_mask_and_ack_irq, - .end = xics_end_irq, - .set_affinity = xics_set_affinity -}; - -/* This is used to map real irq numbers to virtual */ -static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC); - #define XICS_IPI 2 #define XICS_IRQ_SPURIOUS 0 @@ -59,7 +43,7 @@ static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC); /* * Mark IPIs as higher priority so we can take them inside interrupts that - * arent marked SA_INTERRUPT + * arent marked IRQF_DISABLED */ #define IPI_PRIORITY 4 @@ -81,12 +65,12 @@ struct xics_ipl { static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS]; -static int xics_irq_8259_cascade = 0; -static int xics_irq_8259_cascade_real = 0; static unsigned int default_server = 0xFF; static unsigned int default_distrib_server = 0; static unsigned int interrupt_server_size = 8; +static struct irq_host *xics_host; + /* * XICS only has a single IPI, so encode the messages per CPU */ @@ -98,48 +82,34 @@ static int ibm_set_xive; static int ibm_int_on; static int ibm_int_off; -typedef struct { - int (*xirr_info_get)(int cpu); - void (*xirr_info_set)(int cpu, int val); - void (*cppr_info)(int cpu, u8 val); - void (*qirr_info)(int cpu, u8 val); -} xics_ops; +/* Direct HW low level accessors */ -/* SMP */ -static int pSeries_xirr_info_get(int n_cpu) +static inline unsigned int direct_xirr_info_get(int n_cpu) { return in_be32(&xics_per_cpu[n_cpu]->xirr.word); } -static void pSeries_xirr_info_set(int n_cpu, int value) +static inline void direct_xirr_info_set(int n_cpu, int value) { out_be32(&xics_per_cpu[n_cpu]->xirr.word, value); } -static void pSeries_cppr_info(int n_cpu, u8 value) +static inline void direct_cppr_info(int n_cpu, u8 value) { out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value); } -static void pSeries_qirr_info(int n_cpu, u8 value) +static inline void direct_qirr_info(int n_cpu, u8 value) { out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value); } -static xics_ops pSeries_ops = { - pSeries_xirr_info_get, - pSeries_xirr_info_set, - pSeries_cppr_info, - pSeries_qirr_info -}; -static xics_ops *ops = &pSeries_ops; +/* LPAR low level accessors */ -/* LPAR */ - static inline long plpar_eoi(unsigned long xirr) { return plpar_hcall_norets(H_EOI, xirr); @@ -161,7 +131,7 @@ static inline long plpar_xirr(unsigned long *xirr_ret) return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); } -static int pSeriesLP_xirr_info_get(int n_cpu) +static inline unsigned int lpar_xirr_info_get(int n_cpu) { unsigned long lpar_rc; unsigned long return_value; @@ -169,10 +139,10 @@ static int pSeriesLP_xirr_info_get(int n_cpu) lpar_rc = plpar_xirr(&return_value); if (lpar_rc != H_SUCCESS) panic(" bad return code xirr - rc = %lx \n", lpar_rc); - return (int)return_value; + return (unsigned int)return_value; } -static void pSeriesLP_xirr_info_set(int n_cpu, int value) +static inline void lpar_xirr_info_set(int n_cpu, int value) { unsigned long lpar_rc; unsigned long val64 = value & 0xffffffff; @@ -183,7 +153,7 @@ static void pSeriesLP_xirr_info_set(int n_cpu, int value) val64); } -void pSeriesLP_cppr_info(int n_cpu, u8 value) +static inline void lpar_cppr_info(int n_cpu, u8 value) { unsigned long lpar_rc; @@ -192,7 +162,7 @@ void pSeriesLP_cppr_info(int n_cpu, u8 value) panic("bad return code cppr - rc = %lx\n", lpar_rc); } -static void pSeriesLP_qirr_info(int n_cpu , u8 value) +static inline void lpar_qirr_info(int n_cpu , u8 value) { unsigned long lpar_rc; @@ -201,43 +171,16 @@ static void pSeriesLP_qirr_info(int n_cpu , u8 value) panic("bad return code qirr - rc = %lx\n", lpar_rc); } -xics_ops pSeriesLP_ops = { - pSeriesLP_xirr_info_get, - pSeriesLP_xirr_info_set, - pSeriesLP_cppr_info, - pSeriesLP_qirr_info -}; - -static unsigned int xics_startup(unsigned int virq) -{ - unsigned int irq; - - irq = irq_offset_down(virq); - if (radix_tree_insert(&irq_map, virt_irq_to_real(irq), - &virt_irq_to_real_map[irq]) == -ENOMEM) - printk(KERN_CRIT "Out of memory creating real -> virtual" - " IRQ mapping for irq %u (real 0x%x)\n", - virq, virt_irq_to_real(irq)); - xics_enable_irq(virq); - return 0; /* return value is ignored */ -} -static unsigned int real_irq_to_virt(unsigned int real_irq) -{ - unsigned int *ptr; +/* High level handlers and init code */ - ptr = radix_tree_lookup(&irq_map, real_irq); - if (ptr == NULL) - return NO_IRQ; - return ptr - virt_irq_to_real_map; -} #ifdef CONFIG_SMP -static int get_irq_server(unsigned int irq) +static int get_irq_server(unsigned int virq) { unsigned int server; /* For the moment only implement delivery to all cpus or one cpu */ - cpumask_t cpumask = irq_desc[irq].affinity; + cpumask_t cpumask = irq_desc[virq].affinity; cpumask_t tmp = CPU_MASK_NONE; if (!distribute_irqs) @@ -258,23 +201,28 @@ static int get_irq_server(unsigned int irq) } #else -static int get_irq_server(unsigned int irq) +static int get_irq_server(unsigned int virq) { return default_server; } #endif -static void xics_enable_irq(unsigned int virq) + +static void xics_unmask_irq(unsigned int virq) { unsigned int irq; int call_status; unsigned int server; - irq = virt_irq_to_real(irq_offset_down(virq)); - if (irq == XICS_IPI) + pr_debug("xics: unmask virq %d\n", virq); + + irq = (unsigned int)irq_map[virq].hwirq; + pr_debug(" -> map to hwirq 0x%x\n", irq); + if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) return; server = get_irq_server(virq); + call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); if (call_status != 0) { @@ -293,7 +241,7 @@ static void xics_enable_irq(unsigned int virq) } } -static void xics_disable_real_irq(unsigned int irq) +static void xics_mask_real_irq(unsigned int irq) { int call_status; unsigned int server; @@ -318,75 +266,86 @@ static void xics_disable_real_irq(unsigned int irq) } } -static void xics_disable_irq(unsigned int virq) +static void xics_mask_irq(unsigned int virq) { unsigned int irq; - irq = virt_irq_to_real(irq_offset_down(virq)); - xics_disable_real_irq(irq); + pr_debug("xics: mask virq %d\n", virq); + + irq = (unsigned int)irq_map[virq].hwirq; + if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) + return; + xics_mask_real_irq(irq); +} + +static unsigned int xics_startup(unsigned int virq) +{ + unsigned int irq; + + /* force a reverse mapping of the interrupt so it gets in the cache */ + irq = (unsigned int)irq_map[virq].hwirq; + irq_radix_revmap(xics_host, irq); + + /* unmask it */ + xics_unmask_irq(virq); + return 0; } -static void xics_end_irq(unsigned int irq) +static void xics_eoi_direct(unsigned int virq) { int cpu = smp_processor_id(); + unsigned int irq = (unsigned int)irq_map[virq].hwirq; iosync(); - ops->xirr_info_set(cpu, ((0xff << 24) | - (virt_irq_to_real(irq_offset_down(irq))))); - + direct_xirr_info_set(cpu, (0xff << 24) | irq); } -static void xics_mask_and_ack_irq(unsigned int irq) + +static void xics_eoi_lpar(unsigned int virq) { int cpu = smp_processor_id(); + unsigned int irq = (unsigned int)irq_map[virq].hwirq; - if (irq < irq_offset_value()) { - i8259_pic.ack(irq); - iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | - xics_irq_8259_cascade_real)); - iosync(); - } + iosync(); + lpar_xirr_info_set(cpu, (0xff << 24) | irq); } -int xics_get_irq(struct pt_regs *regs) +static inline unsigned int xics_remap_irq(unsigned int vec) { - unsigned int cpu = smp_processor_id(); - unsigned int vec; - int irq; + unsigned int irq; - vec = ops->xirr_info_get(cpu); - /* (vec >> 24) == old priority */ vec &= 0x00ffffff; - /* for sanity, this had better be < NR_IRQS - 16 */ - if (vec == xics_irq_8259_cascade_real) { - irq = i8259_irq(regs); - xics_end_irq(irq_offset_up(xics_irq_8259_cascade)); - } else if (vec == XICS_IRQ_SPURIOUS) { - irq = -1; - } else { - irq = real_irq_to_virt(vec); - if (irq == NO_IRQ) - irq = real_irq_to_virt_slowpath(vec); - if (irq == NO_IRQ) { - printk(KERN_ERR "Interrupt %u (real) is invalid," - " disabling it.\n", vec); - xics_disable_real_irq(vec); - } else - irq = irq_offset_up(irq); - } - return irq; + if (vec == XICS_IRQ_SPURIOUS) + return NO_IRQ; + irq = irq_radix_revmap(xics_host, vec); + if (likely(irq != NO_IRQ)) + return irq; + + printk(KERN_ERR "Interrupt %u (real) is invalid," + " disabling it.\n", vec); + xics_mask_real_irq(vec); + return NO_IRQ; } -#ifdef CONFIG_SMP +static unsigned int xics_get_irq_direct(struct pt_regs *regs) +{ + unsigned int cpu = smp_processor_id(); -static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) + return xics_remap_irq(direct_xirr_info_get(cpu)); +} + +static unsigned int xics_get_irq_lpar(struct pt_regs *regs) { - int cpu = smp_processor_id(); + unsigned int cpu = smp_processor_id(); + + return xics_remap_irq(lpar_xirr_info_get(cpu)); +} - ops->qirr_info(cpu, 0xff); +#ifdef CONFIG_SMP +static irqreturn_t xics_ipi_dispatch(int cpu, struct pt_regs *regs) +{ WARN_ON(cpu_is_offline(cpu)); while (xics_ipi_message[cpu].value) { @@ -418,18 +377,88 @@ static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } +static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + direct_qirr_info(cpu, 0xff); + + return xics_ipi_dispatch(cpu, regs); +} + +static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + lpar_qirr_info(cpu, 0xff); + + return xics_ipi_dispatch(cpu, regs); +} + void xics_cause_IPI(int cpu) { - ops->qirr_info(cpu, IPI_PRIORITY); + if (firmware_has_feature(FW_FEATURE_LPAR)) + lpar_qirr_info(cpu, IPI_PRIORITY); + else + direct_qirr_info(cpu, IPI_PRIORITY); } + #endif /* CONFIG_SMP */ +static void xics_set_cpu_priority(int cpu, unsigned char cppr) +{ + if (firmware_has_feature(FW_FEATURE_LPAR)) + lpar_cppr_info(cpu, cppr); + else + direct_cppr_info(cpu, cppr); + iosync(); +} + +static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) +{ + unsigned int irq; + int status; + int xics_status[2]; + unsigned long newmask; + cpumask_t tmp = CPU_MASK_NONE; + + irq = (unsigned int)irq_map[virq].hwirq; + if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) + return; + + status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); + + if (status) { + printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive " + "returns %d\n", irq, status); + return; + } + + /* For the moment only implement delivery to all cpus or one cpu */ + if (cpus_equal(cpumask, CPU_MASK_ALL)) { + newmask = default_distrib_server; + } else { + cpus_and(tmp, cpu_online_map, cpumask); + if (cpus_empty(tmp)) + return; + newmask = get_hard_smp_processor_id(first_cpu(tmp)); + } + + status = rtas_call(ibm_set_xive, 3, 1, NULL, + irq, newmask, xics_status[1]); + + if (status) { + printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " + "returns %d\n", irq, status); + return; + } +} + void xics_setup_cpu(void) { int cpu = smp_processor_id(); - ops->cppr_info(cpu, 0xff); - iosync(); + xics_set_cpu_priority(cpu, 0xff); /* * Put the calling processor into the GIQ. This is really only @@ -442,72 +471,266 @@ void xics_setup_cpu(void) (1UL << interrupt_server_size) - 1 - default_distrib_server, 1); } -void xics_init_IRQ(void) + +static struct irq_chip xics_pic_direct = { + .typename = " XICS ", + .startup = xics_startup, + .mask = xics_mask_irq, + .unmask = xics_unmask_irq, + .eoi = xics_eoi_direct, + .set_affinity = xics_set_affinity +}; + + +static struct irq_chip xics_pic_lpar = { + .typename = " XICS ", + .startup = xics_startup, + .mask = xics_mask_irq, + .unmask = xics_unmask_irq, + .eoi = xics_eoi_lpar, + .set_affinity = xics_set_affinity +}; + + +static int xics_host_match(struct irq_host *h, struct device_node *node) +{ + /* IBM machines have interrupt parents of various funky types for things + * like vdevices, events, etc... The trick we use here is to match + * everything here except the legacy 8259 which is compatible "chrp,iic" + */ + return !device_is_compatible(node, "chrp,iic"); +} + +static int xics_host_map_direct(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + unsigned int sense = flags & IRQ_TYPE_SENSE_MASK; + + pr_debug("xics: map_direct virq %d, hwirq 0x%lx, flags: 0x%x\n", + virq, hw, flags); + + if (sense && sense != IRQ_TYPE_LEVEL_LOW) + printk(KERN_WARNING "xics: using unsupported sense 0x%x" + " for irq %d (h: 0x%lx)\n", flags, virq, hw); + + get_irq_desc(virq)->status |= IRQ_LEVEL; + set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq); + return 0; +} + +static int xics_host_map_lpar(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + unsigned int sense = flags & IRQ_TYPE_SENSE_MASK; + + pr_debug("xics: map_lpar virq %d, hwirq 0x%lx, flags: 0x%x\n", + virq, hw, flags); + + if (sense && sense != IRQ_TYPE_LEVEL_LOW) + printk(KERN_WARNING "xics: using unsupported sense 0x%x" + " for irq %d (h: 0x%lx)\n", flags, virq, hw); + + get_irq_desc(virq)->status |= IRQ_LEVEL; + set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq); + return 0; +} + +static int xics_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags) + +{ + /* Current xics implementation translates everything + * to level. It is not technically right for MSIs but this + * is irrelevant at this point. We might get smarter in the future + */ + *out_hwirq = intspec[0]; + *out_flags = IRQ_TYPE_LEVEL_LOW; + + return 0; +} + +static struct irq_host_ops xics_host_direct_ops = { + .match = xics_host_match, + .map = xics_host_map_direct, + .xlate = xics_host_xlate, +}; + +static struct irq_host_ops xics_host_lpar_ops = { + .match = xics_host_match, + .map = xics_host_map_lpar, + .xlate = xics_host_xlate, +}; + +static void __init xics_init_host(void) +{ + struct irq_host_ops *ops; + + if (firmware_has_feature(FW_FEATURE_LPAR)) + ops = &xics_host_lpar_ops; + else + ops = &xics_host_direct_ops; + xics_host = irq_alloc_host(IRQ_HOST_MAP_TREE, 0, ops, + XICS_IRQ_SPURIOUS); + BUG_ON(xics_host == NULL); + irq_set_default_host(xics_host); +} + +static void __init xics_map_one_cpu(int hw_id, unsigned long addr, + unsigned long size) { +#ifdef CONFIG_SMP int i; - unsigned long intr_size = 0; - struct device_node *np; - uint *ireg, ilen, indx = 0; - unsigned long intr_base = 0; - struct xics_interrupt_node { - unsigned long addr; - unsigned long size; - } intnodes[NR_CPUS]; - ppc64_boot_msg(0x20, "XICS Init"); + /* This may look gross but it's good enough for now, we don't quite + * have a hard -> linux processor id matching. + */ + for_each_possible_cpu(i) { + if (!cpu_present(i)) + continue; + if (hw_id == get_hard_smp_processor_id(i)) { + xics_per_cpu[i] = ioremap(addr, size); + return; + } + } +#else + if (hw_id != 0) + return; + xics_per_cpu[0] = ioremap(addr, size); +#endif /* CONFIG_SMP */ +} - ibm_get_xive = rtas_token("ibm,get-xive"); - ibm_set_xive = rtas_token("ibm,set-xive"); - ibm_int_on = rtas_token("ibm,int-on"); - ibm_int_off = rtas_token("ibm,int-off"); +static void __init xics_init_one_node(struct device_node *np, + unsigned int *indx) +{ + unsigned int ilen; + u32 *ireg; - np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation"); - if (!np) - panic("xics_init_IRQ: can't find interrupt presentation"); + /* This code does the theorically broken assumption that the interrupt + * server numbers are the same as the hard CPU numbers. + * This happens to be the case so far but we are playing with fire... + * should be fixed one of these days. -BenH. + */ + ireg = (u32 *)get_property(np, "ibm,interrupt-server-ranges", NULL); -nextnode: - ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", NULL); + /* Do that ever happen ? we'll know soon enough... but even good'old + * f80 does have that property .. + */ + WARN_ON(ireg == NULL); if (ireg) { /* * set node starting index for this node */ - indx = *ireg; + *indx = *ireg; } - - ireg = (uint *)get_property(np, "reg", &ilen); + ireg = (u32 *)get_property(np, "reg", &ilen); if (!ireg) panic("xics_init_IRQ: can't find interrupt reg property"); - while (ilen) { - intnodes[indx].addr = (unsigned long)*ireg++ << 32; - ilen -= sizeof(uint); - intnodes[indx].addr |= *ireg++; - ilen -= sizeof(uint); - intnodes[indx].size = (unsigned long)*ireg++ << 32; - ilen -= sizeof(uint); - intnodes[indx].size |= *ireg++; - ilen -= sizeof(uint); - indx++; - if (indx >= NR_CPUS) break; + while (ilen >= (4 * sizeof(u32))) { + unsigned long addr, size; + + /* XXX Use proper OF parsing code here !!! */ + addr = (unsigned long)*ireg++ << 32; + ilen -= sizeof(u32); + addr |= *ireg++; + ilen -= sizeof(u32); + size = (unsigned long)*ireg++ << 32; + ilen -= sizeof(u32); + size |= *ireg++; + ilen -= sizeof(u32); + xics_map_one_cpu(*indx, addr, size); + (*indx)++; + } +} + + +static void __init xics_setup_8259_cascade(void) +{ + struct device_node *np, *old, *found = NULL; + int cascade, naddr; + u32 *addrp; + unsigned long intack = 0; + + for_each_node_by_type(np, "interrupt-controller") + if (device_is_compatible(np, "chrp,iic")) { + found = np; + break; + } + if (found == NULL) { + printk(KERN_DEBUG "xics: no ISA interrupt controller\n"); + return; + } + cascade = irq_of_parse_and_map(found, 0); + if (cascade == NO_IRQ) { + printk(KERN_ERR "xics: failed to map cascade interrupt"); + return; + } + pr_debug("xics: cascade mapped to irq %d\n", cascade); + + for (old = of_node_get(found); old != NULL ; old = np) { + np = of_get_parent(old); + of_node_put(old); + if (np == NULL) + break; + if (strcmp(np->name, "pci") != 0) + continue; + addrp = (u32 *)get_property(np, "8259-interrupt-acknowledge", NULL); + if (addrp == NULL) + continue; + naddr = prom_n_addr_cells(np); + intack = addrp[naddr-1]; + if (naddr > 1) + intack |= ((unsigned long)addrp[naddr-2]) << 32; + } + if (intack) + printk(KERN_DEBUG "xics: PCI 8259 intack at 0x%016lx\n", intack); + i8259_init(found, intack); + of_node_put(found); + set_irq_chained_handler(cascade, pseries_8259_cascade); +} + +void __init xics_init_IRQ(void) +{ + int i; + struct device_node *np; + u32 *ireg, ilen, indx = 0; + int found = 0; + + ppc64_boot_msg(0x20, "XICS Init"); + + ibm_get_xive = rtas_token("ibm,get-xive"); + ibm_set_xive = rtas_token("ibm,set-xive"); + ibm_int_on = rtas_token("ibm,int-on"); + ibm_int_off = rtas_token("ibm,int-off"); + + for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") { + found = 1; + if (firmware_has_feature(FW_FEATURE_LPAR)) + break; + xics_init_one_node(np, &indx); } + if (found == 0) + return; - np = of_find_node_by_type(np, "PowerPC-External-Interrupt-Presentation"); - if ((indx < NR_CPUS) && np) goto nextnode; + xics_init_host(); /* Find the server numbers for the boot cpu. */ for (np = of_find_node_by_type(NULL, "cpu"); np; np = of_find_node_by_type(np, "cpu")) { - ireg = (uint *)get_property(np, "reg", &ilen); + ireg = (u32 *)get_property(np, "reg", &ilen); if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { - ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", - &ilen); + ireg = (u32 *)get_property(np, + "ibm,ppc-interrupt-gserver#s", + &ilen); i = ilen / sizeof(int); if (ireg && i > 0) { default_server = ireg[0]; - default_distrib_server = ireg[i-1]; /* take last element */ + /* take last element */ + default_distrib_server = ireg[i-1]; } - ireg = (uint *)get_property(np, + ireg = (u32 *)get_property(np, "ibm,interrupt-server#-size", NULL); if (ireg) interrupt_server_size = *ireg; @@ -516,132 +739,48 @@ nextnode: } of_node_put(np); - intr_base = intnodes[0].addr; - intr_size = intnodes[0].size; - - np = of_find_node_by_type(NULL, "interrupt-controller"); - if (!np) { - printk(KERN_DEBUG "xics: no ISA interrupt controller\n"); - xics_irq_8259_cascade_real = -1; - xics_irq_8259_cascade = -1; - } else { - ireg = (uint *) get_property(np, "interrupts", NULL); - if (!ireg) - panic("xics_init_IRQ: can't find ISA interrupts property"); - - xics_irq_8259_cascade_real = *ireg; - xics_irq_8259_cascade - = virt_irq_create_mapping(xics_irq_8259_cascade_real); - i8259_init(0, 0); - of_node_put(np); - } - if (firmware_has_feature(FW_FEATURE_LPAR)) - ops = &pSeriesLP_ops; - else { -#ifdef CONFIG_SMP - for_each_possible_cpu(i) { - int hard_id; - - /* FIXME: Do this dynamically! --RR */ - if (!cpu_present(i)) - continue; - - hard_id = get_hard_smp_processor_id(i); - xics_per_cpu[i] = ioremap(intnodes[hard_id].addr, - intnodes[hard_id].size); - } -#else - xics_per_cpu[0] = ioremap(intr_base, intr_size); -#endif /* CONFIG_SMP */ - } - - for (i = irq_offset_value(); i < NR_IRQS; ++i) - get_irq_desc(i)->chip = &xics_pic; + ppc_md.get_irq = xics_get_irq_lpar; + else + ppc_md.get_irq = xics_get_irq_direct; xics_setup_cpu(); + xics_setup_8259_cascade(); + ppc64_boot_msg(0x21, "XICS Done"); } -/* - * We cant do this in init_IRQ because we need the memory subsystem up for - * request_irq() - */ -static int __init xics_setup_i8259(void) -{ - if (ppc64_interrupt_controller == IC_PPC_XIC && - xics_irq_8259_cascade != -1) { - if (request_irq(irq_offset_up(xics_irq_8259_cascade), - no_action, 0, "8259 cascade", NULL)) - printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 " - "cascade\n"); - } - return 0; -} -arch_initcall(xics_setup_i8259); #ifdef CONFIG_SMP void xics_request_IPIs(void) { - virt_irq_to_real_map[XICS_IPI] = XICS_IPI; + unsigned int ipi; - /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ - request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, SA_INTERRUPT, - "IPI", NULL); - get_irq_desc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU; -} -#endif - -static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) -{ - unsigned int irq; - int status; - int xics_status[2]; - unsigned long newmask; - cpumask_t tmp = CPU_MASK_NONE; - - irq = virt_irq_to_real(irq_offset_down(virq)); - if (irq == XICS_IPI || irq == NO_IRQ) - return; - - status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq); + ipi = irq_create_mapping(xics_host, XICS_IPI, 0); + BUG_ON(ipi == NO_IRQ); - if (status) { - printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive " - "returns %d\n", irq, status); - return; - } - - /* For the moment only implement delivery to all cpus or one cpu */ - if (cpus_equal(cpumask, CPU_MASK_ALL)) { - newmask = default_distrib_server; - } else { - cpus_and(tmp, cpu_online_map, cpumask); - if (cpus_empty(tmp)) - return; - newmask = get_hard_smp_processor_id(first_cpu(tmp)); - } - - status = rtas_call(ibm_set_xive, 3, 1, NULL, - irq, newmask, xics_status[1]); - - if (status) { - printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " - "returns %d\n", irq, status); - return; - } + /* + * IPIs are marked IRQF_DISABLED as they must run with irqs + * disabled + */ + set_irq_handler(ipi, handle_percpu_irq); + if (firmware_has_feature(FW_FEATURE_LPAR)) + request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED, + "IPI", NULL); + else + request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED, + "IPI", NULL); } +#endif /* CONFIG_SMP */ void xics_teardown_cpu(int secondary) { int cpu = smp_processor_id(); + unsigned int ipi; + struct irq_desc *desc; - ops->cppr_info(cpu, 0x00); - iosync(); - - /* Clear IPI */ - ops->qirr_info(cpu, 0xff); + xics_set_cpu_priority(cpu, 0); /* * we need to EOI the IPI if we got here from kexec down IPI @@ -650,7 +789,13 @@ void xics_teardown_cpu(int secondary) * should we be flagging idle loop instead? * or creating some task to be scheduled? */ - ops->xirr_info_set(cpu, XICS_IPI); + + ipi = irq_find_mapping(xics_host, XICS_IPI); + if (ipi == XICS_IRQ_SPURIOUS) + return; + desc = get_irq_desc(ipi); + if (desc->chip && desc->chip->eoi) + desc->chip->eoi(XICS_IPI); /* * Some machines need to have at least one cpu in the GIQ, @@ -658,8 +803,8 @@ void xics_teardown_cpu(int secondary) */ if (secondary) rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, - (1UL << interrupt_server_size) - 1 - - default_distrib_server, 0); + (1UL << interrupt_server_size) - 1 - + default_distrib_server, 0); } #ifdef CONFIG_HOTPLUG_CPU @@ -671,8 +816,7 @@ void xics_migrate_irqs_away(void) unsigned int irq, virq, cpu = smp_processor_id(); /* Reject any interrupt that was queued to us... */ - ops->cppr_info(cpu, 0); - iosync(); + xics_set_cpu_priority(cpu, 0); /* remove ourselves from the global interrupt queue */ status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, @@ -680,24 +824,23 @@ void xics_migrate_irqs_away(void) WARN_ON(status < 0); /* Allow IPIs again... */ - ops->cppr_info(cpu, DEFAULT_PRIORITY); - iosync(); + xics_set_cpu_priority(cpu, DEFAULT_PRIORITY); for_each_irq(virq) { - irq_desc_t *desc; + struct irq_desc *desc; int xics_status[2]; unsigned long flags; /* We cant set affinity on ISA interrupts */ - if (virq < irq_offset_value()) + if (virq < NUM_ISA_INTERRUPTS) continue; - - desc = get_irq_desc(virq); - irq = virt_irq_to_real(irq_offset_down(virq)); - + if (irq_map[virq].host != xics_host) + continue; + irq = (unsigned int)irq_map[virq].hwirq; /* We need to get IPIs still. */ - if (irq == XICS_IPI || irq == NO_IRQ) + if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) continue; + desc = get_irq_desc(virq); /* We only need to migrate enabled IRQS */ if (desc == NULL || desc->chip == NULL diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h index e14c70868f1..6ee1055b0ff 100644 --- a/arch/powerpc/platforms/pseries/xics.h +++ b/arch/powerpc/platforms/pseries/xics.h @@ -14,13 +14,12 @@ #include <linux/cache.h> -void xics_init_IRQ(void); -int xics_get_irq(struct pt_regs *); -void xics_setup_cpu(void); -void xics_teardown_cpu(int secondary); -void xics_cause_IPI(int cpu); -void xics_request_IPIs(void); -void xics_migrate_irqs_away(void); +extern void xics_init_IRQ(void); +extern void xics_setup_cpu(void); +extern void xics_teardown_cpu(int secondary); +extern void xics_cause_IPI(int cpu); +extern void xics_request_IPIs(void); +extern void xics_migrate_irqs_away(void); /* first argument is ignored for now*/ void pSeriesLP_cppr_info(int n_cpu, u8 value); @@ -31,4 +30,8 @@ struct xics_ipi_struct { extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; +struct irq_desc; +extern void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs); + #endif /* _POWERPC_KERNEL_XICS_H */ diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 054bd8b41ef..cebfae24260 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -4,7 +4,6 @@ endif obj-$(CONFIG_MPIC) += mpic.o obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o -obj-$(CONFIG_PPC_I8259) += i8259.o obj-$(CONFIG_PPC_MPC106) += grackle.o obj-$(CONFIG_BOOKE) += dcr.o obj-$(CONFIG_40x) += dcr.o @@ -14,3 +13,7 @@ obj-$(CONFIG_PPC_83xx) += ipic.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o obj-$(CONFIG_PPC_TODC) += todc.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o + +ifeq ($(CONFIG_PPC_MERGE),y) +obj-$(CONFIG_PPC_I8259) += i8259.o + endif diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index 2bff30f6d63..72c73a6105c 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -6,11 +6,16 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#undef DEBUG + #include <linux/init.h> #include <linux/ioport.h> #include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/delay.h> #include <asm/io.h> #include <asm/i8259.h> +#include <asm/prom.h> static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */ @@ -20,7 +25,8 @@ static unsigned char cached_8259[2] = { 0xff, 0xff }; static DEFINE_SPINLOCK(i8259_lock); -static int i8259_pic_irq_offset; +static struct device_node *i8259_node; +static struct irq_host *i8259_host; /* * Acknowledge the IRQ using either the PCI host bridge's interrupt @@ -28,16 +34,18 @@ static int i8259_pic_irq_offset; * which is called. It should be noted that polling is broken on some * IBM and Motorola PReP boxes so we must use the int-ack feature on them. */ -int i8259_irq(struct pt_regs *regs) +unsigned int i8259_irq(struct pt_regs *regs) { int irq; - - spin_lock(&i8259_lock); + int lock = 0; /* Either int-ack or poll for the IRQ */ if (pci_intack) irq = readb(pci_intack); else { + spin_lock(&i8259_lock); + lock = 1; + /* Perform an interrupt acknowledge cycle on controller 1. */ outb(0x0C, 0x20); /* prepare for poll */ irq = inb(0x20) & 7; @@ -62,16 +70,13 @@ int i8259_irq(struct pt_regs *regs) if (!pci_intack) outb(0x0B, 0x20); /* ISR register */ if(~inb(0x20) & 0x80) - irq = -1; - } + irq = NO_IRQ; + } else if (irq == 0xff) + irq = NO_IRQ; - spin_unlock(&i8259_lock); - return irq + i8259_pic_irq_offset; -} - -int i8259_irq_cascade(struct pt_regs *regs, void *unused) -{ - return i8259_irq(regs); + if (lock) + spin_unlock(&i8259_lock); + return irq; } static void i8259_mask_and_ack_irq(unsigned int irq_nr) @@ -79,7 +84,6 @@ static void i8259_mask_and_ack_irq(unsigned int irq_nr) unsigned long flags; spin_lock_irqsave(&i8259_lock, flags); - irq_nr -= i8259_pic_irq_offset; if (irq_nr > 7) { cached_A1 |= 1 << (irq_nr-8); inb(0xA1); /* DUMMY */ @@ -105,8 +109,9 @@ static void i8259_mask_irq(unsigned int irq_nr) { unsigned long flags; + pr_debug("i8259_mask_irq(%d)\n", irq_nr); + spin_lock_irqsave(&i8259_lock, flags); - irq_nr -= i8259_pic_irq_offset; if (irq_nr < 8) cached_21 |= 1 << irq_nr; else @@ -119,8 +124,9 @@ static void i8259_unmask_irq(unsigned int irq_nr) { unsigned long flags; + pr_debug("i8259_unmask_irq(%d)\n", irq_nr); + spin_lock_irqsave(&i8259_lock, flags); - irq_nr -= i8259_pic_irq_offset; if (irq_nr < 8) cached_21 &= ~(1 << irq_nr); else @@ -129,19 +135,11 @@ static void i8259_unmask_irq(unsigned int irq_nr) spin_unlock_irqrestore(&i8259_lock, flags); } -static void i8259_end_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) - && irq_desc[irq].action) - i8259_unmask_irq(irq); -} - -struct hw_interrupt_type i8259_pic = { - .typename = " i8259 ", - .enable = i8259_unmask_irq, - .disable = i8259_mask_irq, - .ack = i8259_mask_and_ack_irq, - .end = i8259_end_irq, +static struct irq_chip i8259_pic = { + .typename = " i8259 ", + .mask = i8259_mask_irq, + .unmask = i8259_unmask_irq, + .mask_ack = i8259_mask_and_ack_irq, }; static struct resource pic1_iores = { @@ -165,25 +163,84 @@ static struct resource pic_edgectrl_iores = { .flags = IORESOURCE_BUSY, }; -static struct irqaction i8259_irqaction = { - .handler = no_action, - .flags = SA_INTERRUPT, - .mask = CPU_MASK_NONE, - .name = "82c59 secondary cascade", +static int i8259_host_match(struct irq_host *h, struct device_node *node) +{ + return i8259_node == NULL || i8259_node == node; +} + +static int i8259_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + pr_debug("i8259_host_map(%d, 0x%lx)\n", virq, hw); + + /* We block the internal cascade */ + if (hw == 2) + get_irq_desc(virq)->status |= IRQ_NOREQUEST; + + /* We use the level stuff only for now, we might want to + * be more cautious here but that works for now + */ + get_irq_desc(virq)->status |= IRQ_LEVEL; + set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq); + return 0; +} + +static void i8259_host_unmap(struct irq_host *h, unsigned int virq) +{ + /* Make sure irq is masked in hardware */ + i8259_mask_irq(virq); + + /* remove chip and handler */ + set_irq_chip_and_handler(virq, NULL, NULL); + + /* Make sure it's completed */ + synchronize_irq(virq); +} + +static int i8259_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags) +{ + static unsigned char map_isa_senses[4] = { + IRQ_TYPE_LEVEL_LOW, + IRQ_TYPE_LEVEL_HIGH, + IRQ_TYPE_EDGE_FALLING, + IRQ_TYPE_EDGE_RISING, + }; + + *out_hwirq = intspec[0]; + if (intsize > 1 && intspec[1] < 4) + *out_flags = map_isa_senses[intspec[1]]; + else + *out_flags = IRQ_TYPE_NONE; + + return 0; +} + +static struct irq_host_ops i8259_host_ops = { + .match = i8259_host_match, + .map = i8259_host_map, + .unmap = i8259_host_unmap, + .xlate = i8259_host_xlate, }; -/* - * i8259_init() - * intack_addr - PCI interrupt acknowledge (real) address which will return - * the active irq from the 8259 +/**** + * i8259_init - Initialize the legacy controller + * @node: device node of the legacy PIC (can be NULL, but then, it will match + * all interrupts, so beware) + * @intack_addr: PCI interrupt acknowledge (real) address which will return + * the active irq from the 8259 */ -void __init i8259_init(unsigned long intack_addr, int offset) +void i8259_init(struct device_node *node, unsigned long intack_addr) { unsigned long flags; - int i; + /* initialize the controller */ spin_lock_irqsave(&i8259_lock, flags); - i8259_pic_irq_offset = offset; + + /* Mask all first */ + outb(0xff, 0xA1); + outb(0xff, 0x21); /* init master interrupt controller */ outb(0x11, 0x20); /* Start init sequence */ @@ -197,21 +254,36 @@ void __init i8259_init(unsigned long intack_addr, int offset) outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */ outb(0x01, 0xA1); /* Select 8086 mode */ + /* That thing is slow */ + udelay(100); + /* always read ISR */ outb(0x0B, 0x20); outb(0x0B, 0xA0); - /* Mask all interrupts */ + /* Unmask the internal cascade */ + cached_21 &= ~(1 << 2); + + /* Set interrupt masks */ outb(cached_A1, 0xA1); outb(cached_21, 0x21); spin_unlock_irqrestore(&i8259_lock, flags); - for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) - irq_desc[offset + i].chip = &i8259_pic; + /* create a legacy host */ + if (node) + i8259_node = of_node_get(node); + i8259_host = irq_alloc_host(IRQ_HOST_MAP_LEGACY, 0, &i8259_host_ops, 0); + if (i8259_host == NULL) { + printk(KERN_ERR "i8259: failed to allocate irq host !\n"); + return; + } /* reserve our resources */ - setup_irq(offset + 2, &i8259_irqaction); + /* XXX should we continue doing that ? it seems to cause problems + * with further requesting of PCI IO resources for that range... + * need to look into it. + */ request_resource(&ioport_resource, &pic1_iores); request_resource(&ioport_resource, &pic2_iores); request_resource(&ioport_resource, &pic_edgectrl_iores); @@ -219,4 +291,5 @@ void __init i8259_init(unsigned long intack_addr, int offset) if (intack_addr != 0) pci_intack = ioremap(intack_addr, 1); + printk(KERN_INFO "i8259 legacy interrupt controller initialized\n"); } diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 63ff89575cb..7d31d7cc392 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -100,8 +100,8 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg) if (mpic->flags & MPIC_PRIMARY) cpu = hard_smp_processor_id(); - - return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg); + return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, + mpic->cpuregs[cpu], reg); } static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) @@ -340,27 +340,19 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) #endif /* CONFIG_MPIC_BROKEN_U3 */ +#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) + /* Find an mpic associated with a given linux interrupt */ static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) { - struct mpic *mpic = mpics; - - while(mpic) { - /* search IPIs first since they may override the main interrupts */ - if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) { - if (is_ipi) - *is_ipi = 1; - return mpic; - } - if (irq >= mpic->irq_offset && - irq < (mpic->irq_offset + mpic->irq_count)) { - if (is_ipi) - *is_ipi = 0; - return mpic; - } - mpic = mpic -> next; - } - return NULL; + unsigned int src = mpic_irq_to_hw(irq); + + if (irq < NUM_ISA_INTERRUPTS) + return NULL; + if (is_ipi) + *is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3); + + return irq_desc[irq].chip_data; } /* Convert a cpu mask from logical to physical cpu numbers. */ @@ -378,14 +370,14 @@ static inline u32 mpic_physmask(u32 cpumask) /* Get the mpic structure from the IPI number */ static inline struct mpic * mpic_from_ipi(unsigned int ipi) { - return container_of(irq_desc[ipi].chip, struct mpic, hc_ipi); + return irq_desc[ipi].chip_data; } #endif /* Get the mpic structure from the irq number */ static inline struct mpic * mpic_from_irq(unsigned int irq) { - return container_of(irq_desc[irq].chip, struct mpic, hc_irq); + return irq_desc[irq].chip_data; } /* Send an EOI */ @@ -398,9 +390,7 @@ static inline void mpic_eoi(struct mpic *mpic) #ifdef CONFIG_SMP static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { - struct mpic *mpic = dev_id; - - smp_message_recv(irq - mpic->ipi_offset, regs); + smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0, regs); return IRQ_HANDLED; } #endif /* CONFIG_SMP */ @@ -410,11 +400,11 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs) */ -static void mpic_enable_irq(unsigned int irq) +static void mpic_unmask_irq(unsigned int irq) { unsigned int loops = 100000; struct mpic *mpic = mpic_from_irq(irq); - unsigned int src = irq - mpic->irq_offset; + unsigned int src = mpic_irq_to_hw(irq); DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); @@ -429,39 +419,13 @@ static void mpic_enable_irq(unsigned int irq) break; } } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); - -#ifdef CONFIG_MPIC_BROKEN_U3 - if (mpic->flags & MPIC_BROKEN_U3) { - unsigned int src = irq - mpic->irq_offset; - if (mpic_is_ht_interrupt(mpic, src) && - (irq_desc[irq].status & IRQ_LEVEL)) - mpic_ht_end_irq(mpic, src); - } -#endif /* CONFIG_MPIC_BROKEN_U3 */ -} - -static unsigned int mpic_startup_irq(unsigned int irq) -{ -#ifdef CONFIG_MPIC_BROKEN_U3 - struct mpic *mpic = mpic_from_irq(irq); - unsigned int src = irq - mpic->irq_offset; -#endif /* CONFIG_MPIC_BROKEN_U3 */ - - mpic_enable_irq(irq); - -#ifdef CONFIG_MPIC_BROKEN_U3 - if (mpic_is_ht_interrupt(mpic, src)) - mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); -#endif /* CONFIG_MPIC_BROKEN_U3 */ - - return 0; } -static void mpic_disable_irq(unsigned int irq) +static void mpic_mask_irq(unsigned int irq) { unsigned int loops = 100000; struct mpic *mpic = mpic_from_irq(irq); - unsigned int src = irq - mpic->irq_offset; + unsigned int src = mpic_irq_to_hw(irq); DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); @@ -478,23 +442,58 @@ static void mpic_disable_irq(unsigned int irq) } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); } -static void mpic_shutdown_irq(unsigned int irq) +static void mpic_end_irq(unsigned int irq) { + struct mpic *mpic = mpic_from_irq(irq); + +#ifdef DEBUG_IRQ + DBG("%s: end_irq: %d\n", mpic->name, irq); +#endif + /* We always EOI on end_irq() even for edge interrupts since that + * should only lower the priority, the MPIC should have properly + * latched another edge interrupt coming in anyway + */ + + mpic_eoi(mpic); +} + #ifdef CONFIG_MPIC_BROKEN_U3 + +static void mpic_unmask_ht_irq(unsigned int irq) +{ struct mpic *mpic = mpic_from_irq(irq); - unsigned int src = irq - mpic->irq_offset; + unsigned int src = mpic_irq_to_hw(irq); - if (mpic_is_ht_interrupt(mpic, src)) - mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); + mpic_unmask_irq(irq); -#endif /* CONFIG_MPIC_BROKEN_U3 */ + if (irq_desc[irq].status & IRQ_LEVEL) + mpic_ht_end_irq(mpic, src); +} + +static unsigned int mpic_startup_ht_irq(unsigned int irq) +{ + struct mpic *mpic = mpic_from_irq(irq); + unsigned int src = mpic_irq_to_hw(irq); + + mpic_unmask_irq(irq); + mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status); - mpic_disable_irq(irq); + return 0; } -static void mpic_end_irq(unsigned int irq) +static void mpic_shutdown_ht_irq(unsigned int irq) { struct mpic *mpic = mpic_from_irq(irq); + unsigned int src = mpic_irq_to_hw(irq); + + mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status); + mpic_mask_irq(irq); +} + +static void mpic_end_ht_irq(unsigned int irq) +{ + struct mpic *mpic = mpic_from_irq(irq); + unsigned int src = mpic_irq_to_hw(irq); #ifdef DEBUG_IRQ DBG("%s: end_irq: %d\n", mpic->name, irq); @@ -504,30 +503,25 @@ static void mpic_end_irq(unsigned int irq) * latched another edge interrupt coming in anyway */ -#ifdef CONFIG_MPIC_BROKEN_U3 - if (mpic->flags & MPIC_BROKEN_U3) { - unsigned int src = irq - mpic->irq_offset; - if (mpic_is_ht_interrupt(mpic, src) && - (irq_desc[irq].status & IRQ_LEVEL)) - mpic_ht_end_irq(mpic, src); - } -#endif /* CONFIG_MPIC_BROKEN_U3 */ - + if (irq_desc[irq].status & IRQ_LEVEL) + mpic_ht_end_irq(mpic, src); mpic_eoi(mpic); } +#endif /* CONFIG_MPIC_BROKEN_U3 */ + #ifdef CONFIG_SMP -static void mpic_enable_ipi(unsigned int irq) +static void mpic_unmask_ipi(unsigned int irq) { struct mpic *mpic = mpic_from_ipi(irq); - unsigned int src = irq - mpic->ipi_offset; + unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0; DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); } -static void mpic_disable_ipi(unsigned int irq) +static void mpic_mask_ipi(unsigned int irq) { /* NEVER disable an IPI... that's just plain wrong! */ } @@ -540,7 +534,7 @@ static void mpic_end_ipi(unsigned int irq) * IPIs are marked IRQ_PER_CPU. This has the side effect of * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from * applying to them. We EOI them late to avoid re-entering. - * We mark IPI's with SA_INTERRUPT as they must run with + * We mark IPI's with IRQF_DISABLED as they must run with * irqs disabled. */ mpic_eoi(mpic); @@ -551,29 +545,176 @@ static void mpic_end_ipi(unsigned int irq) static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) { struct mpic *mpic = mpic_from_irq(irq); + unsigned int src = mpic_irq_to_hw(irq); cpumask_t tmp; cpus_and(tmp, cpumask, cpu_online_map); - mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION, + mpic_irq_write(src, MPIC_IRQ_DESTINATION, mpic_physmask(cpus_addr(tmp)[0])); } +static unsigned int mpic_flags_to_vecpri(unsigned int flags, int *level) +{ + unsigned int vecpri; + + /* Now convert sense value */ + switch(flags & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_RISING: + vecpri = MPIC_VECPRI_SENSE_EDGE | + MPIC_VECPRI_POLARITY_POSITIVE; + *level = 0; + break; + case IRQ_TYPE_EDGE_FALLING: + vecpri = MPIC_VECPRI_SENSE_EDGE | + MPIC_VECPRI_POLARITY_NEGATIVE; + *level = 0; + break; + case IRQ_TYPE_LEVEL_HIGH: + vecpri = MPIC_VECPRI_SENSE_LEVEL | + MPIC_VECPRI_POLARITY_POSITIVE; + *level = 1; + break; + case IRQ_TYPE_LEVEL_LOW: + default: + vecpri = MPIC_VECPRI_SENSE_LEVEL | + MPIC_VECPRI_POLARITY_NEGATIVE; + *level = 1; + } + return vecpri; +} + +static struct irq_chip mpic_irq_chip = { + .mask = mpic_mask_irq, + .unmask = mpic_unmask_irq, + .eoi = mpic_end_irq, +}; + +#ifdef CONFIG_SMP +static struct irq_chip mpic_ipi_chip = { + .mask = mpic_mask_ipi, + .unmask = mpic_unmask_ipi, + .eoi = mpic_end_ipi, +}; +#endif /* CONFIG_SMP */ + +#ifdef CONFIG_MPIC_BROKEN_U3 +static struct irq_chip mpic_irq_ht_chip = { + .startup = mpic_startup_ht_irq, + .shutdown = mpic_shutdown_ht_irq, + .mask = mpic_mask_irq, + .unmask = mpic_unmask_ht_irq, + .eoi = mpic_end_ht_irq, +}; +#endif /* CONFIG_MPIC_BROKEN_U3 */ + + +static int mpic_host_match(struct irq_host *h, struct device_node *node) +{ + struct mpic *mpic = h->host_data; + + /* Exact match, unless mpic node is NULL */ + return mpic->of_node == NULL || mpic->of_node == node; +} + +static int mpic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw, unsigned int flags) +{ + struct irq_desc *desc = get_irq_desc(virq); + struct irq_chip *chip; + struct mpic *mpic = h->host_data; + unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL | + MPIC_VECPRI_POLARITY_NEGATIVE; + int level; + + pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n", + virq, hw, flags); + + if (hw == MPIC_VEC_SPURRIOUS) + return -EINVAL; +#ifdef CONFIG_SMP + else if (hw >= MPIC_VEC_IPI_0) { + WARN_ON(!(mpic->flags & MPIC_PRIMARY)); + + pr_debug("mpic: mapping as IPI\n"); + set_irq_chip_data(virq, mpic); + set_irq_chip_and_handler(virq, &mpic->hc_ipi, + handle_percpu_irq); + return 0; + } +#endif /* CONFIG_SMP */ + + if (hw >= mpic->irq_count) + return -EINVAL; + + /* If no sense provided, check default sense array */ + if (((flags & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE) && + mpic->senses && hw < mpic->senses_count) + flags |= mpic->senses[hw]; + + vecpri = mpic_flags_to_vecpri(flags, &level); + if (level) + desc->status |= IRQ_LEVEL; + chip = &mpic->hc_irq; + +#ifdef CONFIG_MPIC_BROKEN_U3 + /* Check for HT interrupts, override vecpri */ + if (mpic_is_ht_interrupt(mpic, hw)) { + vecpri &= ~(MPIC_VECPRI_SENSE_MASK | + MPIC_VECPRI_POLARITY_MASK); + vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; + chip = &mpic->hc_ht_irq; + } +#endif + + /* Reconfigure irq */ + vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT); + mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri); + + pr_debug("mpic: mapping as IRQ\n"); + + set_irq_chip_data(virq, mpic); + set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); + return 0; +} + +static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_flags) + +{ + static unsigned char map_mpic_senses[4] = { + IRQ_TYPE_EDGE_RISING, + IRQ_TYPE_LEVEL_LOW, + IRQ_TYPE_LEVEL_HIGH, + IRQ_TYPE_EDGE_FALLING, + }; + + *out_hwirq = intspec[0]; + if (intsize > 1 && intspec[1] < 4) + *out_flags = map_mpic_senses[intspec[1]]; + else + *out_flags = IRQ_TYPE_NONE; + + return 0; +} + +static struct irq_host_ops mpic_host_ops = { + .match = mpic_host_match, + .map = mpic_host_map, + .xlate = mpic_host_xlate, +}; /* * Exported functions */ - -struct mpic * __init mpic_alloc(unsigned long phys_addr, +struct mpic * __init mpic_alloc(struct device_node *node, + unsigned long phys_addr, unsigned int flags, unsigned int isu_size, - unsigned int irq_offset, unsigned int irq_count, - unsigned int ipi_offset, - unsigned char *senses, - unsigned int senses_count, const char *name) { struct mpic *mpic; @@ -585,33 +726,38 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr, if (mpic == NULL) return NULL; - memset(mpic, 0, sizeof(struct mpic)); mpic->name = name; + mpic->of_node = node ? of_node_get(node) : NULL; + mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256, + &mpic_host_ops, + MPIC_VEC_SPURRIOUS); + if (mpic->irqhost == NULL) { + of_node_put(node); + return NULL; + } + + mpic->irqhost->host_data = mpic; + mpic->hc_irq = mpic_irq_chip; mpic->hc_irq.typename = name; - mpic->hc_irq.startup = mpic_startup_irq; - mpic->hc_irq.shutdown = mpic_shutdown_irq; - mpic->hc_irq.enable = mpic_enable_irq; - mpic->hc_irq.disable = mpic_disable_irq; - mpic->hc_irq.end = mpic_end_irq; if (flags & MPIC_PRIMARY) mpic->hc_irq.set_affinity = mpic_set_affinity; +#ifdef CONFIG_MPIC_BROKEN_U3 + mpic->hc_ht_irq = mpic_irq_ht_chip; + mpic->hc_ht_irq.typename = name; + if (flags & MPIC_PRIMARY) + mpic->hc_ht_irq.set_affinity = mpic_set_affinity; +#endif /* CONFIG_MPIC_BROKEN_U3 */ #ifdef CONFIG_SMP + mpic->hc_ipi = mpic_ipi_chip; mpic->hc_ipi.typename = name; - mpic->hc_ipi.enable = mpic_enable_ipi; - mpic->hc_ipi.disable = mpic_disable_ipi; - mpic->hc_ipi.end = mpic_end_ipi; #endif /* CONFIG_SMP */ mpic->flags = flags; mpic->isu_size = isu_size; - mpic->irq_offset = irq_offset; mpic->irq_count = irq_count; - mpic->ipi_offset = ipi_offset; mpic->num_sources = 0; /* so far */ - mpic->senses = senses; - mpic->senses_count = senses_count; /* Map the global registers */ mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); @@ -679,8 +825,10 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr, mpic->next = mpics; mpics = mpic; - if (flags & MPIC_PRIMARY) + if (flags & MPIC_PRIMARY) { mpic_primary = mpic; + irq_set_default_host(mpic->irqhost); + } return mpic; } @@ -697,26 +845,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, mpic->num_sources = isu_first + mpic->isu_size; } -void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler, - void *data) +void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count) { - struct mpic *mpic = mpic_find(irq, NULL); - unsigned long flags; - - /* Synchronization here is a bit dodgy, so don't try to replace cascade - * interrupts on the fly too often ... but normally it's set up at boot. - */ - spin_lock_irqsave(&mpic_lock, flags); - if (mpic->cascade) - mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset); - mpic->cascade = NULL; - wmb(); - mpic->cascade_vec = irq - mpic->irq_offset; - mpic->cascade_data = data; - wmb(); - mpic->cascade = handler; - mpic_enable_irq(irq); - spin_unlock_irqrestore(&mpic_lock, flags); + mpic->senses = senses; + mpic->senses_count = count; } void __init mpic_init(struct mpic *mpic) @@ -724,6 +856,11 @@ void __init mpic_init(struct mpic *mpic) int i; BUG_ON(mpic->num_sources == 0); + WARN_ON(mpic->num_sources > MPIC_VEC_IPI_0); + + /* Sanitize source count */ + if (mpic->num_sources > MPIC_VEC_IPI_0) + mpic->num_sources = MPIC_VEC_IPI_0; printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); @@ -747,12 +884,6 @@ void __init mpic_init(struct mpic *mpic) MPIC_VECPRI_MASK | (10 << MPIC_VECPRI_PRIORITY_SHIFT) | (MPIC_VEC_IPI_0 + i)); -#ifdef CONFIG_SMP - if (!(mpic->flags & MPIC_PRIMARY)) - continue; - irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU; - irq_desc[mpic->ipi_offset+i].chip = &mpic->hc_ipi; -#endif /* CONFIG_SMP */ } /* Initialize interrupt sources */ @@ -763,31 +894,21 @@ void __init mpic_init(struct mpic *mpic) /* Do the HT PIC fixups on U3 broken mpic */ DBG("MPIC flags: %x\n", mpic->flags); if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) - mpic_scan_ht_pics(mpic); + mpic_scan_ht_pics(mpic); #endif /* CONFIG_MPIC_BROKEN_U3 */ for (i = 0; i < mpic->num_sources; i++) { /* start with vector = source number, and masked */ u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT); - int level = 0; + int level = 1; - /* if it's an IPI, we skip it */ - if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) && - (mpic->irq_offset + i) < (mpic->ipi_offset + i + 4)) - continue; - /* do senses munging */ - if (mpic->senses && i < mpic->senses_count) { - if (mpic->senses[i] & IRQ_SENSE_LEVEL) - vecpri |= MPIC_VECPRI_SENSE_LEVEL; - if (mpic->senses[i] & IRQ_POLARITY_POSITIVE) - vecpri |= MPIC_VECPRI_POLARITY_POSITIVE; - } else + if (mpic->senses && i < mpic->senses_count) + vecpri = mpic_flags_to_vecpri(mpic->senses[i], + &level); + else vecpri |= MPIC_VECPRI_SENSE_LEVEL; - /* remember if it was a level interrupts */ - level = (vecpri & MPIC_VECPRI_SENSE_LEVEL); - /* deal with broken U3 */ if (mpic->flags & MPIC_BROKEN_U3) { #ifdef CONFIG_MPIC_BROKEN_U3 @@ -808,12 +929,6 @@ void __init mpic_init(struct mpic *mpic) mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); mpic_irq_write(i, MPIC_IRQ_DESTINATION, 1 << hard_smp_processor_id()); - - /* init linux descriptors */ - if (i < mpic->irq_count) { - irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0; - irq_desc[mpic->irq_offset+i].chip = &mpic->hc_irq; - } } /* Init spurrious vector */ @@ -854,19 +969,20 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) { int is_ipi; struct mpic *mpic = mpic_find(irq, &is_ipi); + unsigned int src = mpic_irq_to_hw(irq); unsigned long flags; u32 reg; spin_lock_irqsave(&mpic_lock, flags); if (is_ipi) { - reg = mpic_ipi_read(irq - mpic->ipi_offset) & + reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) & ~MPIC_VECPRI_PRIORITY_MASK; - mpic_ipi_write(irq - mpic->ipi_offset, + mpic_ipi_write(src - MPIC_VEC_IPI_0, reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); } else { - reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI) + reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & ~MPIC_VECPRI_PRIORITY_MASK; - mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI, + mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); } spin_unlock_irqrestore(&mpic_lock, flags); @@ -876,14 +992,15 @@ unsigned int mpic_irq_get_priority(unsigned int irq) { int is_ipi; struct mpic *mpic = mpic_find(irq, &is_ipi); + unsigned int src = mpic_irq_to_hw(irq); unsigned long flags; u32 reg; spin_lock_irqsave(&mpic_lock, flags); if (is_ipi) - reg = mpic_ipi_read(irq - mpic->ipi_offset); + reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); else - reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI); + reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); spin_unlock_irqrestore(&mpic_lock, flags); return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; } @@ -978,37 +1095,20 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); } -int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) +unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) { - u32 irq; + u32 src; - irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; -#ifdef DEBUG_LOW - DBG("%s: get_one_irq(): %d\n", mpic->name, irq); -#endif - if (mpic->cascade && irq == mpic->cascade_vec) { + src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; #ifdef DEBUG_LOW - DBG("%s: cascading ...\n", mpic->name); -#endif - irq = mpic->cascade(regs, mpic->cascade_data); - mpic_eoi(mpic); - return irq; - } - if (unlikely(irq == MPIC_VEC_SPURRIOUS)) - return -1; - if (irq < MPIC_VEC_IPI_0) { -#ifdef DEBUG_IRQ - DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset); -#endif - return irq + mpic->irq_offset; - } -#ifdef DEBUG_IPI - DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0); + DBG("%s: get_one_irq(): %d\n", mpic->name, src); #endif - return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset; + if (unlikely(src == MPIC_VEC_SPURRIOUS)) + return NO_IRQ; + return irq_linear_revmap(mpic->irqhost, src); } -int mpic_get_irq(struct pt_regs *regs) +unsigned int mpic_get_irq(struct pt_regs *regs) { struct mpic *mpic = mpic_primary; @@ -1022,22 +1122,27 @@ int mpic_get_irq(struct pt_regs *regs) void mpic_request_ipis(void) { struct mpic *mpic = mpic_primary; - + int i; + static char *ipi_names[] = { + "IPI0 (call function)", + "IPI1 (reschedule)", + "IPI2 (unused)", + "IPI3 (debugger break)", + }; BUG_ON(mpic == NULL); - - printk("requesting IPIs ... \n"); - - /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ - request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT, - "IPI0 (call function)", mpic); - request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT, - "IPI1 (reschedule)", mpic); - request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT, - "IPI2 (unused)", mpic); - request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT, - "IPI3 (debugger break)", mpic); - - printk("IPIs requested... \n"); + + printk(KERN_INFO "mpic: requesting IPIs ... \n"); + + for (i = 0; i < 4; i++) { + unsigned int vipi = irq_create_mapping(mpic->irqhost, + MPIC_VEC_IPI_0 + i, 0); + if (vipi == NO_IRQ) { + printk(KERN_ERR "Failed to map IPI %d\n", i); + break; + } + request_irq(vipi, mpic_ipi_action, IRQF_DISABLED, + ipi_names[i], mpic); + } } void smp_mpic_message_pass(int target, int msg) diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c index cd5f3faa4b2..e347fe88316 100644 --- a/arch/ppc/8260_io/fcc_enet.c +++ b/arch/ppc/8260_io/fcc_enet.c @@ -2116,7 +2116,7 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev) #ifdef PHY_INTERRUPT #ifdef CONFIG_ADS8272 - if (request_irq(PHY_INTERRUPT, mii_link_interrupt, SA_SHIRQ, + if (request_irq(PHY_INTERRUPT, mii_link_interrupt, IRQF_SHARED, "mii", dev) < 0) printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT); #else diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c index 026ace32072..d90cd24d018 100644 --- a/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -131,7 +131,7 @@ static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction cpm2_irqaction = { .handler = cpm2_cascade, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "cpm2_cascade", }; diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index 139cf0d0085..75204588a3e 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c @@ -136,7 +136,7 @@ static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction cpm2_irqaction = { .handler = cpm2_cascade, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "cpm2_cascade", }; diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c index 224612412cb..495aa79bb3a 100644 --- a/arch/ppc/platforms/85xx/stx_gp3.c +++ b/arch/ppc/platforms/85xx/stx_gp3.c @@ -166,7 +166,7 @@ static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction cpm2_irqaction = { .handler = cpm2_cascade, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "cpm2_cascade", }; diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c index 1c90f113cc8..189ed4175f9 100644 --- a/arch/ppc/platforms/85xx/tqm85xx.c +++ b/arch/ppc/platforms/85xx/tqm85xx.c @@ -190,7 +190,7 @@ static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction cpm2_irqaction = { .handler = cpm2_cascade, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "cpm2_cascade", }; diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index 71af4b48862..e0f112a1fd0 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -837,7 +837,7 @@ static void smp_hdpu_setup_cpu(int cpu_nr) mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, 0xff); mv64x60_write(&bh, MV64360_CPU0_DOORBELL_MASK, 0xff); request_irq(60, hdpu_smp_cpu0_int_handler, - SA_INTERRUPT, hdpu_smp0, 0); + IRQF_DISABLED, hdpu_smp0, 0); } if (cpu_nr == 1) { @@ -857,7 +857,7 @@ static void smp_hdpu_setup_cpu(int cpu_nr) mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, 0x0); mv64x60_write(&bh, MV64360_CPU1_DOORBELL_MASK, 0xff); request_irq(28, hdpu_smp_cpu1_int_handler, - SA_INTERRUPT, hdpu_smp1, 0); + IRQF_DISABLED, hdpu_smp1, 0); } } diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index 97d6c21091e..3bb530af029 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c @@ -1310,7 +1310,7 @@ static void ppc7d_init2(void) /* Hook up i8259 interrupt which is connected to GPP28 */ request_irq(mv64360_irq_base + MV64x60_IRQ_GPP28, ppc7d_i8259_intr, - SA_INTERRUPT, "I8259 (GPP28) interrupt", (void *)0); + IRQF_DISABLED, "I8259 (GPP28) interrupt", (void *)0); /* Configure MPP16 as watchdog NMI, MPP17 as watchdog WDE */ spin_lock_irqsave(&mv64x60_lock, flags); diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c index 8cff1e30334..60b769c7f3f 100644 --- a/arch/ppc/platforms/sbc82xx.c +++ b/arch/ppc/platforms/sbc82xx.c @@ -145,7 +145,7 @@ static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id, struct pt_regs *re static struct irqaction sbc82xx_i8259_irqaction = { .handler = sbc82xx_i8259_demux, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "i8259 demux", }; diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 490749ca88f..2497bbc07e7 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -104,3 +104,5 @@ obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o \ ifeq ($(CONFIG_PPC_MPC52xx),y) obj-$(CONFIG_PCI) += mpc52xx_pci.o endif + +obj-$(CONFIG_PPC_I8259) += i8259.o diff --git a/arch/ppc/syslib/btext.c b/arch/ppc/syslib/btext.c index 51ab6e90fe2..d11667046f2 100644 --- a/arch/ppc/syslib/btext.c +++ b/arch/ppc/syslib/btext.c @@ -6,7 +6,7 @@ #include <linux/kernel.h> #include <linux/string.h> #include <linux/init.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <asm/sections.h> #include <asm/bootx.h> diff --git a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c index 91096b38ae7..7fd550a7d58 100644 --- a/arch/ppc/syslib/gt64260_pic.c +++ b/arch/ppc/syslib/gt64260_pic.c @@ -297,7 +297,7 @@ gt64260_register_hdlrs(void) /* Register CPU interface error interrupt handler */ if ((rc = request_irq(MV64x60_IRQ_CPU_ERR, - gt64260_cpu_error_int_handler, SA_INTERRUPT, CPU_INTR_STR, 0))) + gt64260_cpu_error_int_handler, IRQF_DISABLED, CPU_INTR_STR, 0))) printk(KERN_WARNING "Can't register cpu error handler: %d", rc); mv64x60_write(&bh, MV64x60_CPU_ERR_MASK, 0); @@ -305,7 +305,7 @@ gt64260_register_hdlrs(void) /* Register PCI 0 error interrupt handler */ if ((rc = request_irq(MV64360_IRQ_PCI0, gt64260_pci_error_int_handler, - SA_INTERRUPT, PCI0_INTR_STR, (void *)0))) + IRQF_DISABLED, PCI0_INTR_STR, (void *)0))) printk(KERN_WARNING "Can't register pci 0 error handler: %d", rc); @@ -314,7 +314,7 @@ gt64260_register_hdlrs(void) /* Register PCI 1 error interrupt handler */ if ((rc = request_irq(MV64360_IRQ_PCI1, gt64260_pci_error_int_handler, - SA_INTERRUPT, PCI1_INTR_STR, (void *)1))) + IRQF_DISABLED, PCI1_INTR_STR, (void *)1))) printk(KERN_WARNING "Can't register pci 1 error handler: %d", rc); diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c new file mode 100644 index 00000000000..eb35353af83 --- /dev/null +++ b/arch/ppc/syslib/i8259.c @@ -0,0 +1,212 @@ +/* + * i8259 interrupt controller driver. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/interrupt.h> +#include <asm/io.h> +#include <asm/i8259.h> + +static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */ + +static unsigned char cached_8259[2] = { 0xff, 0xff }; +#define cached_A1 (cached_8259[0]) +#define cached_21 (cached_8259[1]) + +static DEFINE_SPINLOCK(i8259_lock); + +static int i8259_pic_irq_offset; + +/* + * Acknowledge the IRQ using either the PCI host bridge's interrupt + * acknowledge feature or poll. How i8259_init() is called determines + * which is called. It should be noted that polling is broken on some + * IBM and Motorola PReP boxes so we must use the int-ack feature on them. + */ +int i8259_irq(struct pt_regs *regs) +{ + int irq; + + spin_lock(&i8259_lock); + + /* Either int-ack or poll for the IRQ */ + if (pci_intack) + irq = readb(pci_intack); + else { + /* Perform an interrupt acknowledge cycle on controller 1. */ + outb(0x0C, 0x20); /* prepare for poll */ + irq = inb(0x20) & 7; + if (irq == 2 ) { + /* + * Interrupt is cascaded so perform interrupt + * acknowledge on controller 2. + */ + outb(0x0C, 0xA0); /* prepare for poll */ + irq = (inb(0xA0) & 7) + 8; + } + } + + if (irq == 7) { + /* + * This may be a spurious interrupt. + * + * Read the interrupt status register (ISR). If the most + * significant bit is not set then there is no valid + * interrupt. + */ + if (!pci_intack) + outb(0x0B, 0x20); /* ISR register */ + if(~inb(0x20) & 0x80) + irq = -1; + } + + spin_unlock(&i8259_lock); + return irq + i8259_pic_irq_offset; +} + +static void i8259_mask_and_ack_irq(unsigned int irq_nr) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259_lock, flags); + irq_nr -= i8259_pic_irq_offset; + if (irq_nr > 7) { + cached_A1 |= 1 << (irq_nr-8); + inb(0xA1); /* DUMMY */ + outb(cached_A1, 0xA1); + outb(0x20, 0xA0); /* Non-specific EOI */ + outb(0x20, 0x20); /* Non-specific EOI to cascade */ + } else { + cached_21 |= 1 << irq_nr; + inb(0x21); /* DUMMY */ + outb(cached_21, 0x21); + outb(0x20, 0x20); /* Non-specific EOI */ + } + spin_unlock_irqrestore(&i8259_lock, flags); +} + +static void i8259_set_irq_mask(int irq_nr) +{ + outb(cached_A1,0xA1); + outb(cached_21,0x21); +} + +static void i8259_mask_irq(unsigned int irq_nr) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259_lock, flags); + irq_nr -= i8259_pic_irq_offset; + if (irq_nr < 8) + cached_21 |= 1 << irq_nr; + else + cached_A1 |= 1 << (irq_nr-8); + i8259_set_irq_mask(irq_nr); + spin_unlock_irqrestore(&i8259_lock, flags); +} + +static void i8259_unmask_irq(unsigned int irq_nr) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259_lock, flags); + irq_nr -= i8259_pic_irq_offset; + if (irq_nr < 8) + cached_21 &= ~(1 << irq_nr); + else + cached_A1 &= ~(1 << (irq_nr-8)); + i8259_set_irq_mask(irq_nr); + spin_unlock_irqrestore(&i8259_lock, flags); +} + +static struct irq_chip i8259_pic = { + .typename = " i8259 ", + .mask = i8259_mask_irq, + .unmask = i8259_unmask_irq, + .mask_ack = i8259_mask_and_ack_irq, +}; + +static struct resource pic1_iores = { + .name = "8259 (master)", + .start = 0x20, + .end = 0x21, + .flags = IORESOURCE_BUSY, +}; + +static struct resource pic2_iores = { + .name = "8259 (slave)", + .start = 0xa0, + .end = 0xa1, + .flags = IORESOURCE_BUSY, +}; + +static struct resource pic_edgectrl_iores = { + .name = "8259 edge control", + .start = 0x4d0, + .end = 0x4d1, + .flags = IORESOURCE_BUSY, +}; + +static struct irqaction i8259_irqaction = { + .handler = no_action, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, + .name = "82c59 secondary cascade", +}; + +/* + * i8259_init() + * intack_addr - PCI interrupt acknowledge (real) address which will return + * the active irq from the 8259 + */ +void __init i8259_init(unsigned long intack_addr, int offset) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&i8259_lock, flags); + i8259_pic_irq_offset = offset; + + /* init master interrupt controller */ + outb(0x11, 0x20); /* Start init sequence */ + outb(0x00, 0x21); /* Vector base */ + outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0x21); /* Select 8086 mode */ + + /* init slave interrupt controller */ + outb(0x11, 0xA0); /* Start init sequence */ + outb(0x08, 0xA1); /* Vector base */ + outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */ + outb(0x01, 0xA1); /* Select 8086 mode */ + + /* always read ISR */ + outb(0x0B, 0x20); + outb(0x0B, 0xA0); + + /* Mask all interrupts */ + outb(cached_A1, 0xA1); + outb(cached_21, 0x21); + + spin_unlock_irqrestore(&i8259_lock, flags); + + for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) { + set_irq_chip_and_handler(offset + i, &i8259_pic, + handle_level_irq); + irq_desc[offset + i].status |= IRQ_LEVEL; + } + + /* reserve our resources */ + setup_irq(offset + 2, &i8259_irqaction); + request_resource(&ioport_resource, &pic1_iores); + request_resource(&ioport_resource, &pic2_iores); + request_resource(&ioport_resource, &pic_edgectrl_iores); + + if (intack_addr != 0) + pci_intack = ioremap(intack_addr, 1); + +} diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index 0440d8f4ce1..4b77e6c8c87 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -149,7 +149,7 @@ void __init ibm440gx_l2c_enable(void){ unsigned long flags; /* Install error handler */ - if (request_irq(87, l2c_error_handler, SA_INTERRUPT, "L2C", 0) < 0){ + if (request_irq(87, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0){ printk(KERN_ERR "Cannot install L2C error handler, cache is not enabled\n"); return; } diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c index 63fa5b31339..d3fa264e179 100644 --- a/arch/ppc/syslib/m82xx_pci.c +++ b/arch/ppc/syslib/m82xx_pci.c @@ -139,7 +139,7 @@ pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction pq2pci_irqaction = { .handler = pq2pci_irq_demux, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, .name = "PQ2 PCI cascade", }; diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c index a4244d46838..3f6d162f87c 100644 --- a/arch/ppc/syslib/mv64360_pic.c +++ b/arch/ppc/syslib/mv64360_pic.c @@ -380,7 +380,7 @@ mv64360_register_hdlrs(void) /* Clear old errors and register CPU interface error intr handler */ mv64x60_write(&bh, MV64x60_CPU_ERR_CAUSE, 0); if ((rc = request_irq(MV64x60_IRQ_CPU_ERR + mv64360_irq_base, - mv64360_cpu_error_int_handler, SA_INTERRUPT, CPU_INTR_STR, 0))) + mv64360_cpu_error_int_handler, IRQF_DISABLED, CPU_INTR_STR, 0))) printk(KERN_WARNING "Can't register cpu error handler: %d", rc); mv64x60_write(&bh, MV64x60_CPU_ERR_MASK, 0); @@ -389,14 +389,14 @@ mv64360_register_hdlrs(void) /* Clear old errors and register internal SRAM error intr handler */ mv64x60_write(&bh, MV64360_SRAM_ERR_CAUSE, 0); if ((rc = request_irq(MV64360_IRQ_SRAM_PAR_ERR + mv64360_irq_base, - mv64360_sram_error_int_handler,SA_INTERRUPT,SRAM_INTR_STR, 0))) + mv64360_sram_error_int_handler,IRQF_DISABLED,SRAM_INTR_STR, 0))) printk(KERN_WARNING "Can't register SRAM error handler: %d",rc); /* Clear old errors and register PCI 0 error intr handler */ mv64x60_write(&bh, MV64x60_PCI0_ERR_CAUSE, 0); if ((rc = request_irq(MV64360_IRQ_PCI0 + mv64360_irq_base, mv64360_pci_error_int_handler, - SA_INTERRUPT, PCI0_INTR_STR, (void *)0))) + IRQF_DISABLED, PCI0_INTR_STR, (void *)0))) printk(KERN_WARNING "Can't register pci 0 error handler: %d", rc); @@ -411,7 +411,7 @@ mv64360_register_hdlrs(void) mv64x60_write(&bh, MV64x60_PCI1_ERR_CAUSE, 0); if ((rc = request_irq(MV64360_IRQ_PCI1 + mv64360_irq_base, mv64360_pci_error_int_handler, - SA_INTERRUPT, PCI1_INTR_STR, (void *)1))) + IRQF_DISABLED, PCI1_INTR_STR, (void *)1))) printk(KERN_WARNING "Can't register pci 1 error handler: %d", rc); diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c index 08973663fa2..aa0b9578870 100644 --- a/arch/ppc/syslib/open_pic.c +++ b/arch/ppc/syslib/open_pic.c @@ -575,18 +575,21 @@ void openpic_request_IPIs(void) if (OpenPIC == NULL) return; - /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ + /* + * IPIs are marked IRQF_DISABLED as they must run with irqs + * disabled + */ request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset, - openpic_ipi_action, SA_INTERRUPT, + openpic_ipi_action, IRQF_DISABLED, "IPI0 (call function)", NULL); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1, - openpic_ipi_action, SA_INTERRUPT, + openpic_ipi_action, IRQF_DISABLED, "IPI1 (reschedule)", NULL); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2, - openpic_ipi_action, SA_INTERRUPT, + openpic_ipi_action, IRQF_DISABLED, "IPI2 (invalidate tlb)", NULL); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3, - openpic_ipi_action, SA_INTERRUPT, + openpic_ipi_action, IRQF_DISABLED, "IPI3 (xmon break)", NULL); for ( i = 0; i < OPENPIC_NUM_IPI ; i++ ) @@ -691,7 +694,7 @@ openpic_init_nmi_irq(u_int irq) static struct irqaction openpic_cascade_irqaction = { .handler = no_action, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, }; diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 821a141889d..224fbff7996 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -7,6 +7,14 @@ config MMU bool default y +config LOCKDEP_SUPPORT + bool + default y + +config STACKTRACE_SUPPORT + bool + default y + config RWSEM_GENERIC_SPINLOCK bool diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug index f53b6d5300e..2283933a9a9 100644 --- a/arch/s390/Kconfig.debug +++ b/arch/s390/Kconfig.debug @@ -1,5 +1,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + source "lib/Kconfig.debug" endmenu diff --git a/arch/s390/Makefile b/arch/s390/Makefile index b3791fb094a..74ef57dcfa6 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -34,6 +34,11 @@ cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5) cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900) cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) +# +# Prevent tail-call optimizations, to get clearer backtraces: +# +cflags-$(CONFIG_FRAME_POINTER) += -fno-optimize-sibling-calls + # old style option for packed stacks ifeq ($(call cc-option-yn,-mkernel-backchain),y) cflags-$(CONFIG_PACK_STACK) += -mkernel-backchain -D__PACK_STACK diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 9269b5788fa..eabf00a6f77 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o obj-$(CONFIG_VIRT_TIMER) += vtime.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o # Kexec part S390_KEXEC_OBJS := machine_kexec.o crash.o diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index d8948c342ca..5b5799ac8f8 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -58,6 +58,21 @@ STACK_SIZE = 1 << STACK_SHIFT #define BASED(name) name-system_call(%r13) +#ifdef CONFIG_TRACE_IRQFLAGS + .macro TRACE_IRQS_ON + l %r1,BASED(.Ltrace_irq_on) + basr %r14,%r1 + .endm + + .macro TRACE_IRQS_OFF + l %r1,BASED(.Ltrace_irq_off) + basr %r14,%r1 + .endm +#else +#define TRACE_IRQS_ON +#define TRACE_IRQS_OFF +#endif + /* * Register usage in interrupt handlers: * R9 - pointer to current task structure @@ -361,6 +376,7 @@ ret_from_fork: st %r15,SP_R15(%r15) # store stack pointer for new kthread 0: l %r1,BASED(.Lschedtail) basr %r14,%r1 + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_return) @@ -516,6 +532,7 @@ pgm_no_vtime3: mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_do_svc) @@ -539,9 +556,11 @@ io_int_handler: io_no_vtime: #endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handler + TRACE_IRQS_ON io_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -651,10 +670,12 @@ ext_int_handler: ext_no_vtime: #endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # get interruption code l %r1,BASED(.Ldo_extint) basr %r14,%r1 + TRACE_IRQS_ON b BASED(io_return) __critical_end: @@ -731,8 +752,10 @@ mcck_no_vtime: stosm __SF_EMPTY(%r15),0x04 # turn dat on tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bno BASED(mcck_return) + TRACE_IRQS_OFF l %r1,BASED(.Ls390_handle_mcck) basr %r14,%r1 # call machine check handler + TRACE_IRQS_ON mcck_return: mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit @@ -1012,7 +1035,11 @@ cleanup_io_leave_insn: .Lvfork: .long sys_vfork .Lschedtail: .long schedule_tail .Lsysc_table: .long sys_call_table - +#ifdef CONFIG_TRACE_IRQFLAGS +.Ltrace_irq_on:.long trace_hardirqs_on +.Ltrace_irq_off: + .long trace_hardirqs_off +#endif .Lcritical_start: .long __critical_start + 0x80000000 .Lcritical_end: diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 1ca499fa54b..56f5f613b86 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -58,6 +58,19 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ #define BASED(name) name-system_call(%r13) +#ifdef CONFIG_TRACE_IRQFLAGS + .macro TRACE_IRQS_ON + brasl %r14,trace_hardirqs_on + .endm + + .macro TRACE_IRQS_OFF + brasl %r14,trace_hardirqs_off + .endm +#else +#define TRACE_IRQS_ON +#define TRACE_IRQS_OFF +#endif + .macro STORE_TIMER lc_offset #ifdef CONFIG_VIRT_CPU_ACCOUNTING stpt \lc_offset @@ -354,6 +367,7 @@ ret_from_fork: jo 0f stg %r15,SP_R15(%r15) # store stack pointer for new kthread 0: brasl %r14,schedule_tail + TRACE_IRQS_ON stosm 24(%r15),0x03 # reenable interrupts j sysc_return @@ -535,6 +549,7 @@ pgm_no_vtime3: mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts j sysc_do_svc @@ -557,8 +572,10 @@ io_int_handler: io_no_vtime: #endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler + TRACE_IRQS_ON io_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -665,9 +682,11 @@ ext_int_handler: ext_no_vtime: #endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area llgh %r3,__LC_EXT_INT_CODE # get interruption code brasl %r14,do_extint + TRACE_IRQS_ON j io_return __critical_end: @@ -743,7 +762,9 @@ mcck_no_vtime: stosm __SF_EMPTY(%r15),0x04 # turn dat on tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jno mcck_return + TRACE_IRQS_OFF brasl %r14,s390_handle_mcck + TRACE_IRQS_ON mcck_return: mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 480b6a5fef3..1eef5091861 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -69,10 +69,6 @@ asmlinkage void do_softirq(void) local_irq_save(flags); - account_system_vtime(current); - - local_bh_disable(); - if (local_softirq_pending()) { /* Get current stack pointer. */ asm volatile("la %0,0(15)" : "=a" (old)); @@ -95,10 +91,6 @@ asmlinkage void do_softirq(void) __do_softirq(); } - account_system_vtime(current); - - __local_bh_enable(); - local_irq_restore(flags); } diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 1f939919179..78c8e5548ca 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -142,6 +142,7 @@ static void default_idle(void) return; } + trace_hardirqs_on(); /* Wait for external, I/O or machine check interrupt. */ __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT); diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c new file mode 100644 index 00000000000..de83f38288d --- /dev/null +++ b/arch/s390/kernel/stacktrace.c @@ -0,0 +1,90 @@ +/* + * arch/s390/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> + */ + +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/kallsyms.h> + +static inline unsigned long save_context_stack(struct stack_trace *trace, + unsigned int *skip, + unsigned long sp, + unsigned long low, + unsigned long high) +{ + struct stack_frame *sf; + struct pt_regs *regs; + unsigned long addr; + + while(1) { + sp &= PSW_ADDR_INSN; + if (sp < low || sp > high) + return sp; + sf = (struct stack_frame *)sp; + while(1) { + addr = sf->gprs[8] & PSW_ADDR_INSN; + if (!(*skip)) + trace->entries[trace->nr_entries++] = addr; + else + (*skip)--; + if (trace->nr_entries >= trace->max_entries) + return sp; + low = sp; + sp = sf->back_chain & PSW_ADDR_INSN; + if (!sp) + break; + if (sp <= low || sp > high - sizeof(*sf)) + return sp; + sf = (struct stack_frame *)sp; + } + /* Zero backchain detected, check for interrupt frame. */ + sp = (unsigned long)(sf + 1); + if (sp <= low || sp > high - sizeof(*regs)) + return sp; + regs = (struct pt_regs *)sp; + addr = regs->psw.addr & PSW_ADDR_INSN; + if (!(*skip)) + trace->entries[trace->nr_entries++] = addr; + else + (*skip)--; + if (trace->nr_entries >= trace->max_entries) + return sp; + low = sp; + sp = regs->gprs[15]; + } +} + +void save_stack_trace(struct stack_trace *trace, + struct task_struct *task, int all_contexts, + unsigned int skip) +{ + register unsigned long sp asm ("15"); + unsigned long orig_sp; + + sp &= PSW_ADDR_INSN; + orig_sp = sp; + + sp = save_context_stack(trace, &skip, sp, + S390_lowcore.panic_stack - PAGE_SIZE, + S390_lowcore.panic_stack); + if ((sp != orig_sp) && !all_contexts) + return; + sp = save_context_stack(trace, &skip, sp, + S390_lowcore.async_stack - ASYNC_SIZE, + S390_lowcore.async_stack); + if ((sp != orig_sp) && !all_contexts) + return; + if (task) + save_context_stack(trace, &skip, sp, + (unsigned long) task_stack_page(task), + (unsigned long) task_stack_page(task) + THREAD_SIZE); + else + save_context_stack(trace, &skip, sp, S390_lowcore.thread_info, + S390_lowcore.thread_info + THREAD_SIZE); + return; +} diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c index 046b896d04f..f1f7c70c940 100644 --- a/arch/sh/boards/snapgear/setup.c +++ b/arch/sh/boards/snapgear/setup.c @@ -50,7 +50,7 @@ static int __init eraseconfig_init(void) { printk("SnapGear: EraseConfig init\n"); /* Setup "EraseConfig" switch on external IRQ 0 */ - if (request_irq(IRL0_IRQ, eraseconfig_interrupt, SA_INTERRUPT, + if (request_irq(IRL0_IRQ, eraseconfig_interrupt, IRQF_DISABLED, "Erase Config", NULL)) printk("SnapGear: failed to register IRQ%d for Reset witch\n", IRL0_IRQ); diff --git a/arch/sh/cchips/hd6446x/hd64461/setup.c b/arch/sh/cchips/hd6446x/hd64461/setup.c index 9b361a91a1a..ad126016720 100644 --- a/arch/sh/cchips/hd6446x/hd64461/setup.c +++ b/arch/sh/cchips/hd6446x/hd64461/setup.c @@ -133,7 +133,7 @@ int hd64461_irq_demux(int irq) return __irq_demux(irq); } -static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64461", NULL, NULL }; +static struct irqaction irq0 = { hd64461_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "HD64461", NULL, NULL }; int __init setup_hd64461(void) { diff --git a/arch/sh/cchips/hd6446x/hd64465/gpio.c b/arch/sh/cchips/hd6446x/hd64465/gpio.c index 9785fdef868..72320d02d69 100644 --- a/arch/sh/cchips/hd6446x/hd64465/gpio.c +++ b/arch/sh/cchips/hd6446x/hd64465/gpio.c @@ -170,7 +170,7 @@ static int __init hd64465_gpio_init(void) if (!request_region(HD64465_REG_GPACR, 0x1000, MODNAME)) return -EBUSY; if (request_irq(HD64465_IRQ_GPIO, hd64465_gpio_interrupt, - SA_INTERRUPT, MODNAME, 0)) + IRQF_DISABLED, MODNAME, 0)) goto out_irqfailed; printk("HD64465 GPIO layer on irq %d\n", HD64465_IRQ_GPIO); diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c index b2b0aa48a3a..d2b2851bc44 100644 --- a/arch/sh/cchips/hd6446x/hd64465/setup.c +++ b/arch/sh/cchips/hd6446x/hd64465/setup.c @@ -153,7 +153,7 @@ int hd64465_irq_demux(int irq) return irq; } -static struct irqaction irq0 = { hd64465_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "HD64465", NULL, NULL}; +static struct irqaction irq0 = { hd64465_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "HD64465", NULL, NULL}; static int __init setup_hd64465(void) diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c index 6a74464dab2..0dc1fb8f968 100644 --- a/arch/sh/cchips/voyagergx/irq.c +++ b/arch/sh/cchips/voyagergx/irq.c @@ -165,7 +165,7 @@ int voyagergx_irq_demux(int irq) static struct irqaction irq0 = { .name = "voyagergx", .handler = voyagergx_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, }; diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index 5afab6f56ec..0f866f8789f 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c @@ -56,7 +56,7 @@ static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction g2_dma_irq = { .name = "g2 DMA handler", .handler = g2_dma_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, }; static int g2_enable_dma(struct dma_channel *chan) diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index df604975ccc..30a580aa7cb 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c @@ -70,7 +70,7 @@ static int pvr2_xfer_dma(struct dma_channel *chan) static struct irqaction pvr2_dma_irq = { .name = "pvr2 DMA handler", .handler = pvr2_dma_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, }; static struct dma_ops pvr2_dma_ops = { diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index fecd8f8d046..e028a2d2a4e 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -90,7 +90,7 @@ static int sh_dmac_request_dma(struct dma_channel *chan) chan->chan); return request_irq(get_dmte_irq(chan->chan), dma_tei, - SA_INTERRUPT, name, chan); + IRQF_DISABLED, name, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) @@ -258,7 +258,7 @@ static int __init sh_dmac_init(void) #ifdef CONFIG_CPU_SH4 make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - i = request_irq(DMAE_IRQ, dma_err, SA_INTERRUPT, "DMAC Address Error", 0); + i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0); if (i < 0) return i; #endif diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c index 21f3017e5c2..7c81b8b65bb 100644 --- a/arch/sh/drivers/pci/pci-st40.c +++ b/arch/sh/drivers/pci/pci-st40.c @@ -447,7 +447,7 @@ static int __init pcibios_init(void) PHYSADDR(memory_end) - PHYSADDR(memory_start)); if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, - SA_INTERRUPT, "st40pci", NULL)) { + IRQF_DISABLED, "st40pci", NULL)) { printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); return -EIO; } diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 96a64cb1310..d4212add53b 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -107,7 +107,7 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, static struct irqaction tmu_irq = { .name = "timer", .handler = tmu_timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .mask = CPU_MASK_NONE, }; diff --git a/arch/sh64/kernel/dma.c b/arch/sh64/kernel/dma.c index 09cd9f4670b..32c6f0549bf 100644 --- a/arch/sh64/kernel/dma.c +++ b/arch/sh64/kernel/dma.c @@ -115,7 +115,7 @@ static irqreturn_t dma_mte(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction irq_dmte = { .handler = dma_mte, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "DMA MTE", }; @@ -152,7 +152,7 @@ static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) static struct irqaction irq_derr = { .handler = dma_err, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "DMA Error", }; diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c index 3c04951ff73..9dae689b6a9 100644 --- a/arch/sh64/kernel/pci_sh5.c +++ b/arch/sh64/kernel/pci_sh5.c @@ -473,13 +473,13 @@ static void __init pcibios_size_bridges(void) static int __init pcibios_init(void) { if (request_irq(IRQ_ERR, pcish5_err_irq, - SA_INTERRUPT, "PCI Error",NULL) < 0) { + IRQF_DISABLED, "PCI Error",NULL) < 0) { printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n"); return -EINVAL; } if (request_irq(IRQ_SERR, pcish5_serr_irq, - SA_INTERRUPT, "PCI SERR interrupt", NULL) < 0) { + IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) { printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n"); return -EINVAL; } diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c index ba9eb992f4a..b8162e59030 100644 --- a/arch/sh64/kernel/time.c +++ b/arch/sh64/kernel/time.c @@ -484,8 +484,8 @@ static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id, return IRQ_HANDLED; } -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL}; -static struct irqaction irq1 = { sh64_rtc_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "rtc", NULL, NULL}; +static struct irqaction irq0 = { timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL}; +static struct irqaction irq1 = { sh64_rtc_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "rtc", NULL, NULL}; void __init time_init(void) { diff --git a/arch/sh64/mach-cayman/irq.c b/arch/sh64/mach-cayman/irq.c index cac94219dd5..228ce61c351 100644 --- a/arch/sh64/mach-cayman/irq.c +++ b/arch/sh64/mach-cayman/irq.c @@ -44,13 +44,13 @@ static irqreturn_t cayman_interrupt_pci2(int irq, void *dev_id, struct pt_regs * static struct irqaction cayman_action_smsc = { .name = "Cayman SMSC Mux", .handler = cayman_interrupt_smsc, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, }; static struct irqaction cayman_action_pci2 = { .name = "Cayman PCI2 Mux", .handler = cayman_interrupt_pci2, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, }; static void enable_cayman_irq(unsigned int irq) diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index b81af076ef4..cde73327ca9 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -191,11 +191,11 @@ int show_interrupts(struct seq_file *p, void *v) } #endif seq_printf(p, " %c %s", - (action->flags & SA_INTERRUPT) ? '+' : ' ', + (action->flags & IRQF_DISABLED) ? '+' : ' ', action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", + (action->flags & IRQF_DISABLED) ? " +" : "", action->name); } seq_putc(p, '\n'); @@ -243,7 +243,7 @@ void free_irq(unsigned int irq, void *dev_id) printk("Trying to free free shared IRQ%d\n",irq); goto out_unlock; } - } else if (action->flags & SA_SHIRQ) { + } else if (action->flags & IRQF_SHARED) { printk("Trying to free shared IRQ%d with NULL device ID\n", irq); goto out_unlock; } @@ -395,9 +395,9 @@ int request_fast_irq(unsigned int irq, action = sparc_irq[cpu_irq].action; if(action) { - if(action->flags & SA_SHIRQ) + if(action->flags & IRQF_SHARED) panic("Trying to register fast irq when already shared.\n"); - if(irqflags & SA_SHIRQ) + if(irqflags & IRQF_SHARED) panic("Trying to register fast irq as shared.\n"); /* Anyway, someone already owns it so cannot be made fast. */ @@ -497,11 +497,11 @@ int request_irq(unsigned int irq, actionp = &sparc_irq[cpu_irq].action; action = *actionp; if (action) { - if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ)) { + if (!(action->flags & IRQF_SHARED) || !(irqflags & IRQF_SHARED)) { ret = -EBUSY; goto out_unlock; } - if ((action->flags & SA_INTERRUPT) != (irqflags & SA_INTERRUPT)) { + if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); ret = -EBUSY; goto out_unlock; diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 22422ff1060..bfd31aac2df 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -745,7 +745,7 @@ void __init pci_time_init(void) writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), pcic->pcic_regs+PCI_COUNTER_IRQ); irq = request_irq(timer_irq, pcic_timer_handler, - (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); prom_halt(); diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 50e988b9c8c..4be2c86ea54 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c @@ -179,7 +179,7 @@ static void __init sun4c_init_timers(irqreturn_t (*counter_fn)(int, void *, stru irq = request_irq(TIMER_IRQ, counter_fn, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index cbf8ee81cf5..74eed9775ac 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -107,13 +107,13 @@ found_it: seq_printf(p, "%3d: ", i); kstat_cpu(cpu_logical_map(x)).irqs[i]); #endif seq_printf(p, "%c %s", - (action->flags & SA_INTERRUPT) ? '+' : ' ', + (action->flags & IRQF_DISABLED) ? '+' : ' ', action->name); action = action->next; for (;;) { for (; action; action = action->next) { seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", + (action->flags & IRQF_DISABLED) ? " +" : "", action->name); } if (!sbusl) break; @@ -160,7 +160,7 @@ void sun4d_free_irq(unsigned int irq, void *dev_id) printk("Trying to free free shared IRQ%d\n",irq); goto out_unlock; } - } else if (action->flags & SA_SHIRQ) { + } else if (action->flags & IRQF_SHARED) { printk("Trying to free shared IRQ%d with NULL device ID\n", irq); goto out_unlock; } @@ -298,13 +298,13 @@ int sun4d_request_irq(unsigned int irq, action = *actionp; if (action) { - if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { + if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) { for (tmp = action; tmp->next; tmp = tmp->next); } else { ret = -EBUSY; goto out_unlock; } - if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) { + if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); ret = -EBUSY; goto out_unlock; @@ -490,7 +490,7 @@ static void __init sun4d_init_timers(irqreturn_t (*counter_fn)(int, void *, stru irq = request_irq(TIMER_IRQ, counter_fn, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 38ac672b114..7cefa301efe 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -278,7 +278,7 @@ static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, stru irq = request_irq(TIMER_IRQ, counter_fn, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index 591547af4c6..d3b4daac705 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c @@ -74,7 +74,7 @@ void claim_ticker14(irqreturn_t (*handler)(int, void *, struct pt_regs *), if (!request_irq(irq_nr, handler, - (SA_INTERRUPT | SA_STATIC_ALLOC), + (IRQF_DISABLED | SA_STATIC_ALLOC), "counter14", NULL)) { install_linux_ticker(); diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index a1023bb1a21..8a9b470e1b6 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -140,7 +140,7 @@ int ebus_dma_irq_enable(struct ebus_dma_info *p, int on) if (on) { if (p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) { - if (request_irq(p->irq, ebus_dma_irq, SA_SHIRQ, p->name, p)) + if (request_irq(p->irq, ebus_dma_irq, IRQF_SHARED, p->name, p)) return -EBUSY; } diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index bf7b32b3670..197a7ffd57e 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -863,11 +863,11 @@ static void psycho_register_error_handlers(struct pci_controller_info *p) if (op->num_irqs < 6) return; - request_irq(op->irqs[1], psycho_ue_intr, SA_SHIRQ, "PSYCHO UE", p); - request_irq(op->irqs[2], psycho_ce_intr, SA_SHIRQ, "PSYCHO CE", p); - request_irq(op->irqs[5], psycho_pcierr_intr, SA_SHIRQ, + request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO UE", p); + request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO CE", p); + request_irq(op->irqs[5], psycho_pcierr_intr, IRQF_SHARED, "PSYCHO PCIERR-A", &p->pbm_A); - request_irq(op->irqs[0], psycho_pcierr_intr, SA_SHIRQ, + request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED, "PSYCHO PCIERR-B", &p->pbm_B); /* Enable UE and CE interrupts for controller. */ diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 5e087b0fb4c..45891850b90 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -854,14 +854,14 @@ static void sabre_register_error_handlers(struct pci_controller_info *p) SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); - request_irq(op->irqs[1], sabre_ue_intr, SA_SHIRQ, "SABRE UE", p); + request_irq(op->irqs[1], sabre_ue_intr, IRQF_SHARED, "SABRE UE", p); sabre_write(base + SABRE_CE_AFSR, (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); - request_irq(op->irqs[2], sabre_ce_intr, SA_SHIRQ, "SABRE CE", p); - request_irq(op->irqs[0], sabre_pcierr_intr, SA_SHIRQ, + request_irq(op->irqs[2], sabre_ce_intr, IRQF_SHARED, "SABRE CE", p); + request_irq(op->irqs[0], sabre_pcierr_intr, IRQF_SHARED, "SABRE PCIERR", p); tmp = sabre_read(base + SABRE_PCICTRL); diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 5c6e2a9b91f..75ade83ecc6 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -998,32 +998,32 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p) pbm = pbm_for_ino(p, SCHIZO_UE_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[1], schizo_ue_intr, SA_SHIRQ, + request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED, "TOMATILLO_UE", p); pbm = pbm_for_ino(p, SCHIZO_CE_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[2], schizo_ce_intr, SA_SHIRQ, + request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED, "TOMATILLO CE", p); pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, "TOMATILLO PCIERR-A", pbm); pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, "TOMATILLO PCIERR-B", pbm); pbm = pbm_for_ino(p, SCHIZO_SERR_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[3], schizo_safarierr_intr, SA_SHIRQ, + request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED, "TOMATILLO SERR", p); /* Enable UE and CE interrupts for controller. */ @@ -1106,32 +1106,32 @@ static void schizo_register_error_handlers(struct pci_controller_info *p) pbm = pbm_for_ino(p, SCHIZO_UE_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[1], schizo_ue_intr, SA_SHIRQ, + request_irq(op->irqs[1], schizo_ue_intr, IRQF_SHARED, "SCHIZO_UE", p); pbm = pbm_for_ino(p, SCHIZO_CE_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[2], schizo_ce_intr, SA_SHIRQ, + request_irq(op->irqs[2], schizo_ce_intr, IRQF_SHARED, "SCHIZO CE", p); pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, "SCHIZO PCIERR-A", pbm); pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[0], schizo_pcierr_intr, SA_SHIRQ, + request_irq(op->irqs[0], schizo_pcierr_intr, IRQF_SHARED, "SCHIZO PCIERR-B", pbm); pbm = pbm_for_ino(p, SCHIZO_SERR_INO); op = of_find_device_by_node(pbm->prom_node); if (op) - request_irq(op->irqs[3], schizo_safarierr_intr, SA_SHIRQ, + request_irq(op->irqs[3], schizo_safarierr_intr, IRQF_SHARED, "SCHIZO SERR", p); /* Enable UE and CE interrupts for controller. */ diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index ef68aa4fec6..c49a5779574 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -1065,7 +1065,7 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) irq = sbus_build_irq(sbus, SYSIO_UE_INO); if (request_irq(irq, sysio_ue_handler, - SA_SHIRQ, "SYSIO UE", sbus) < 0) { + IRQF_SHARED, "SYSIO UE", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", sbus->portid); prom_halt(); @@ -1073,7 +1073,7 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) irq = sbus_build_irq(sbus, SYSIO_CE_INO); if (request_irq(irq, sysio_ce_handler, - SA_SHIRQ, "SYSIO CE", sbus) < 0) { + IRQF_SHARED, "SYSIO CE", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", sbus->portid); prom_halt(); @@ -1081,7 +1081,7 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); if (request_irq(irq, sysio_sbus_error_handler, - SA_SHIRQ, "SYSIO SBUS Error", sbus) < 0) { + IRQF_SHARED, "SYSIO SBUS Error", sbus) < 0) { prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", sbus->portid); prom_halt(); diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 5ca57ca3371..ebebaabb78a 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -373,7 +373,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data, int err; /* Interrupts are enabled here because we registered the interrupt with - * SA_INTERRUPT (see line_setup_irq).*/ + * IRQF_DISABLED (see line_setup_irq).*/ spin_lock_irq(&line->lock); err = flush_buffer(line); @@ -406,7 +406,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data, int line_setup_irq(int fd, int input, int output, struct line *line, void *data) { struct line_driver *driver = line->driver; - int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; + int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM; if (input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, @@ -767,7 +767,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) spin_unlock(&winch_handler_lock); if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "winch", winch) < 0) printk("register_winch_irq - failed to register IRQ\n"); } diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 79149314ed0..b414522f768 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -777,7 +777,7 @@ static int mconsole_init(void) register_reboot_notifier(&reboot_notifier); err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "mconsole", (void *)sock); if (err){ printk("Failed to get IRQ for management console\n"); diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 8c7279bb353..501f95675d8 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -128,7 +128,7 @@ static int uml_net_open(struct net_device *dev) } err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, - SA_INTERRUPT | SA_SHIRQ, dev->name, dev); + IRQF_DISABLED | IRQF_SHARED, dev->name, dev); if(err != 0){ printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); err = -ENETUNREACH; diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index 189839e4f1d..73755f37a8a 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -105,7 +105,7 @@ static int port_accept(struct port_list *port) .port = port }); if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "telnetd", conn)){ printk(KERN_ERR "port_accept : failed to get IRQ for " "telnetd\n"); @@ -186,7 +186,7 @@ void *port_data(int port_num) goto out_free; } if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "port", + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "port", port)){ printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); goto out_close; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 0345e255124..602d7286b9e 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -874,7 +874,7 @@ int ubd_driver_init(void){ return(0); } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, - SA_INTERRUPT, "ubd", ubd_dev); + IRQF_DISABLED, "ubd", ubd_dev); if(err != 0) printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return 0; diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c index d269a80f4b0..6036ec85895 100644 --- a/arch/um/drivers/xterm_kern.c +++ b/arch/um/drivers/xterm_kern.c @@ -54,7 +54,7 @@ int xterm_fd(int socket, int *pid_out) init_completion(&data->ready); err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, "xterm", data); if (err){ printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index fae43a3054a..bfd0bdc8cd4 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -474,7 +474,7 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *, } err = um_request_irq(irq, fds[0], IRQ_READ, handler, - SA_INTERRUPT | SA_SAMPLE_RANDOM, name, + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name, (void *) (long) fds[0]); if (err) { printk("init_aio_irq - : um_request_irq failed, err = %d\n", diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c index 1c1300fb1e9..51b67708394 100644 --- a/arch/um/kernel/sigio_kern.c +++ b/arch/um/kernel/sigio_kern.c @@ -31,7 +31,7 @@ int write_sigio_irq(int fd) int err; err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, - SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "write sigio", NULL); if(err){ printk("write_sigio_irq : um_request_irq failed, err = %d\n", diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 820fa3615a3..d7e044b5e5e 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -195,7 +195,7 @@ int __init timer_init(void) int err; user_time_init(); - err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL); + err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); if(err != 0) printk(KERN_ERR "timer_init : request_irq failed - " "errno = %d\n", -err); diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index a9c1443fc54..8368c2dbe63 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -119,7 +119,7 @@ void suspend_new_thread(int fd) panic("read failed in suspend_new_thread, err = %d", -err); } -void schedule_tail(task_t *prev); +void schedule_tail(struct task_struct *prev); static void new_thread_handler(int sig) { diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 7d51dd7201c..37cfe7701f0 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -495,6 +495,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end) { } +#ifdef CONFIG_SMP void alternatives_smp_module_add(struct module *mod, char *name, void *locks, void *locks_end, void *text, void *text_end) @@ -504,3 +505,4 @@ void alternatives_smp_module_add(struct module *mod, char *name, void alternatives_smp_module_del(struct module *mod) { } +#endif diff --git a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c index 92918b8d89e..25d636e79e6 100644 --- a/arch/v850/kernel/gbus_int.c +++ b/arch/v850/kernel/gbus_int.c @@ -154,7 +154,7 @@ static unsigned gbus_int_startup_irq (unsigned irq) /* First enable the CPU interrupt. */ int rval = request_irq (IRQ_GINT(gint), gbus_int_handle_irq, - SA_INTERRUPT, + IRQF_DISABLED, "gbus_int_handler", &gint_num_active_irqs[gint]); if (rval != 0) diff --git a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c index df7027d8543..3be355a029e 100644 --- a/arch/v850/kernel/rte_me2_cb.c +++ b/arch/v850/kernel/rte_me2_cb.c @@ -263,7 +263,7 @@ static unsigned cb_pic_startup_irq (unsigned irq) if (cb_pic_active_irqs == 0) { rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq, - SA_INTERRUPT, "cb_pic_handler", 0); + IRQF_DISABLED, "cb_pic_handler", 0); if (rval != 0) return rval; } diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c index c1e85c2aef6..a0b46695f18 100644 --- a/arch/v850/kernel/time.c +++ b/arch/v850/kernel/time.c @@ -177,7 +177,7 @@ EXPORT_SYMBOL(do_settimeofday); static int timer_dev_id; static struct irqaction timer_irqaction = { timer_interrupt, - SA_INTERRUPT, + IRQF_DISABLED, CPU_MASK_NONE, "timer", &timer_dev_id, diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index e856804c447..28df7d88ce2 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -24,6 +24,14 @@ config X86 bool default y +config LOCKDEP_SUPPORT + bool + default y + +config STACKTRACE_SUPPORT + bool + default y + config SEMAPHORE_SLEEPERS bool default y diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug index 1d92ab56c0f..775d211a5cf 100644 --- a/arch/x86_64/Kconfig.debug +++ b/arch/x86_64/Kconfig.debug @@ -1,5 +1,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + source "lib/Kconfig.debug" config DEBUG_RODATA diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S index 7de8b8fd168..a50b631f4d2 100644 --- a/arch/x86_64/boot/setup.S +++ b/arch/x86_64/boot/setup.S @@ -46,7 +46,7 @@ */ #include <asm/segment.h> -#include <linux/version.h> +#include <linux/utsrelease.h> #include <linux/compile.h> #include <asm/boot.h> #include <asm/e820.h> diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index c536fa98ea3..9b5bb413a6e 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -13,6 +13,7 @@ #include <asm/thread_info.h> #include <asm/segment.h> #include <asm/vsyscall32.h> +#include <asm/irqflags.h> #include <linux/linkage.h> #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) @@ -75,6 +76,10 @@ ENTRY(ia32_sysenter_target) swapgs movq %gs:pda_kernelstack, %rsp addq $(PDA_STACKOFFSET),%rsp + /* + * No need to follow this irqs on/off section: the syscall + * disabled irqs, here we enable it straight after entry: + */ sti movl %ebp,%ebp /* zero extension */ pushq $__USER32_DS @@ -118,6 +123,7 @@ sysenter_do_call: movq %rax,RAX-ARGOFFSET(%rsp) GET_THREAD_INFO(%r10) cli + TRACE_IRQS_OFF testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10) jnz int_ret_from_sys_call andl $~TS_COMPAT,threadinfo_status(%r10) @@ -132,6 +138,7 @@ sysenter_do_call: CFI_REGISTER rsp,rcx movl $VSYSCALL32_SYSEXIT,%edx /* User %eip */ CFI_REGISTER rip,rdx + TRACE_IRQS_ON swapgs sti /* sti only takes effect after the next instruction */ /* sysexit */ @@ -186,6 +193,10 @@ ENTRY(ia32_cstar_target) movl %esp,%r8d CFI_REGISTER rsp,r8 movq %gs:pda_kernelstack,%rsp + /* + * No need to follow this irqs on/off section: the syscall + * disabled irqs and here we enable it straight after entry: + */ sti SAVE_ARGS 8,1,1 movl %eax,%eax /* zero extension */ @@ -220,6 +231,7 @@ cstar_do_call: movq %rax,RAX-ARGOFFSET(%rsp) GET_THREAD_INFO(%r10) cli + TRACE_IRQS_OFF testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10) jnz int_ret_from_sys_call andl $~TS_COMPAT,threadinfo_status(%r10) @@ -228,6 +240,7 @@ cstar_do_call: CFI_REGISTER rip,rcx movl EFLAGS-ARGOFFSET(%rsp),%r11d /*CFI_REGISTER rflags,r11*/ + TRACE_IRQS_ON movl RSP-ARGOFFSET(%rsp),%esp CFI_RESTORE rsp swapgs @@ -286,7 +299,11 @@ ENTRY(ia32_syscall) /*CFI_REL_OFFSET rflags,EFLAGS-RIP*/ /*CFI_REL_OFFSET cs,CS-RIP*/ CFI_REL_OFFSET rip,RIP-RIP - swapgs + swapgs + /* + * No need to follow this irqs on/off section: the syscall + * disabled irqs and here we enable it straight after entry: + */ sti movl %eax,%eax pushq %rax diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile index 819e84ec5b6..b5aaeafc1cd 100644 --- a/arch/x86_64/kernel/Makefile +++ b/arch/x86_64/kernel/Makefile @@ -10,6 +10,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \ setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ pci-dma.o pci-nommu.o alternative.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_X86_MCE) += mce.o obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index ed92c298360..d464dded68c 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -41,13 +41,24 @@ #include <asm/thread_info.h> #include <asm/hw_irq.h> #include <asm/page.h> +#include <asm/irqflags.h> .code64 #ifndef CONFIG_PREEMPT #define retint_kernel retint_restore_args #endif - + + +.macro TRACE_IRQS_IRETQ offset=ARGOFFSET +#ifdef CONFIG_TRACE_IRQFLAGS + bt $9,EFLAGS-\offset(%rsp) /* interrupts off? */ + jnc 1f + TRACE_IRQS_ON +1: +#endif +.endm + /* * C code is not supposed to know about undefined top of stack. Every time * a C function with an pt_regs argument is called from the SYSCALL based @@ -194,6 +205,10 @@ ENTRY(system_call) swapgs movq %rsp,%gs:pda_oldrsp movq %gs:pda_kernelstack,%rsp + /* + * No need to follow this irqs off/on section - it's straight + * and short: + */ sti SAVE_ARGS 8,1 movq %rax,ORIG_RAX-ARGOFFSET(%rsp) @@ -219,10 +234,15 @@ ret_from_sys_call: sysret_check: GET_THREAD_INFO(%rcx) cli + TRACE_IRQS_OFF movl threadinfo_flags(%rcx),%edx andl %edi,%edx CFI_REMEMBER_STATE jnz sysret_careful + /* + * sysretq will re-enable interrupts: + */ + TRACE_IRQS_ON movq RIP-ARGOFFSET(%rsp),%rcx CFI_REGISTER rip,rcx RESTORE_ARGS 0,-ARG_SKIP,1 @@ -237,6 +257,7 @@ sysret_careful: CFI_RESTORE_STATE bt $TIF_NEED_RESCHED,%edx jnc sysret_signal + TRACE_IRQS_ON sti pushq %rdi CFI_ADJUST_CFA_OFFSET 8 @@ -247,6 +268,7 @@ sysret_careful: /* Handle a signal */ sysret_signal: + TRACE_IRQS_ON sti testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx jz 1f @@ -261,6 +283,7 @@ sysret_signal: /* Use IRET because user could have changed frame. This works because ptregscall_common has called FIXUP_TOP_OF_STACK. */ cli + TRACE_IRQS_OFF jmp int_with_check badsys: @@ -309,6 +332,7 @@ ENTRY(int_ret_from_sys_call) CFI_REL_OFFSET r10,R10-ARGOFFSET CFI_REL_OFFSET r11,R11-ARGOFFSET cli + TRACE_IRQS_OFF testl $3,CS-ARGOFFSET(%rsp) je retint_restore_args movl $_TIF_ALLWORK_MASK,%edi @@ -327,6 +351,7 @@ int_with_check: int_careful: bt $TIF_NEED_RESCHED,%edx jnc int_very_careful + TRACE_IRQS_ON sti pushq %rdi CFI_ADJUST_CFA_OFFSET 8 @@ -334,10 +359,12 @@ int_careful: popq %rdi CFI_ADJUST_CFA_OFFSET -8 cli + TRACE_IRQS_OFF jmp int_with_check /* handle signals and tracing -- both require a full stack frame */ int_very_careful: + TRACE_IRQS_ON sti SAVE_REST /* Check for syscall exit trace */ @@ -351,6 +378,7 @@ int_very_careful: CFI_ADJUST_CFA_OFFSET -8 andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi cli + TRACE_IRQS_OFF jmp int_restore_rest int_signal: @@ -363,6 +391,7 @@ int_signal: int_restore_rest: RESTORE_REST cli + TRACE_IRQS_OFF jmp int_with_check CFI_ENDPROC END(int_ret_from_sys_call) @@ -484,6 +513,10 @@ END(stub_rt_sigreturn) swapgs 1: incl %gs:pda_irqcount # RED-PEN should check preempt count cmoveq %gs:pda_irqstackptr,%rsp + /* + * We entered an interrupt context - irqs are off: + */ + TRACE_IRQS_OFF call \func .endm @@ -493,6 +526,7 @@ ENTRY(common_interrupt) /* 0(%rsp): oldrsp-ARGOFFSET */ ret_from_intr: cli + TRACE_IRQS_OFF decl %gs:pda_irqcount leaveq CFI_DEF_CFA_REGISTER rsp @@ -515,9 +549,21 @@ retint_check: CFI_REMEMBER_STATE jnz retint_careful retint_swapgs: + /* + * The iretq could re-enable interrupts: + */ + cli + TRACE_IRQS_IRETQ swapgs + jmp restore_args + retint_restore_args: cli + /* + * The iretq could re-enable interrupts: + */ + TRACE_IRQS_IRETQ +restore_args: RESTORE_ARGS 0,8,0 iret_label: iretq @@ -530,6 +576,7 @@ iret_label: /* running with kernel gs */ bad_iret: movq $11,%rdi /* SIGSEGV */ + TRACE_IRQS_ON sti jmp do_exit .previous @@ -539,6 +586,7 @@ retint_careful: CFI_RESTORE_STATE bt $TIF_NEED_RESCHED,%edx jnc retint_signal + TRACE_IRQS_ON sti pushq %rdi CFI_ADJUST_CFA_OFFSET 8 @@ -547,11 +595,13 @@ retint_careful: CFI_ADJUST_CFA_OFFSET -8 GET_THREAD_INFO(%rcx) cli + TRACE_IRQS_OFF jmp retint_check retint_signal: testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx jz retint_swapgs + TRACE_IRQS_ON sti SAVE_REST movq $-1,ORIG_RAX(%rsp) @@ -560,6 +610,7 @@ retint_signal: call do_notify_resume RESTORE_REST cli + TRACE_IRQS_OFF movl $_TIF_NEED_RESCHED,%edi GET_THREAD_INFO(%rcx) jmp retint_check @@ -666,7 +717,7 @@ END(spurious_interrupt) /* error code is on the stack already */ /* handle NMI like exceptions that can happen everywhere */ - .macro paranoidentry sym, ist=0 + .macro paranoidentry sym, ist=0, irqtrace=1 SAVE_ALL cld movl $1,%ebx @@ -691,8 +742,73 @@ END(spurious_interrupt) addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) .endif cli + .if \irqtrace + TRACE_IRQS_OFF + .endif .endm - + + /* + * "Paranoid" exit path from exception stack. + * Paranoid because this is used by NMIs and cannot take + * any kernel state for granted. + * We don't do kernel preemption checks here, because only + * NMI should be common and it does not enable IRQs and + * cannot get reschedule ticks. + * + * "trace" is 0 for the NMI handler only, because irq-tracing + * is fundamentally NMI-unsafe. (we cannot change the soft and + * hard flags at once, atomically) + */ + .macro paranoidexit trace=1 + /* ebx: no swapgs flag */ +paranoid_exit\trace: + testl %ebx,%ebx /* swapgs needed? */ + jnz paranoid_restore\trace + testl $3,CS(%rsp) + jnz paranoid_userspace\trace +paranoid_swapgs\trace: + TRACE_IRQS_IRETQ 0 + swapgs +paranoid_restore\trace: + RESTORE_ALL 8 + iretq +paranoid_userspace\trace: + GET_THREAD_INFO(%rcx) + movl threadinfo_flags(%rcx),%ebx + andl $_TIF_WORK_MASK,%ebx + jz paranoid_swapgs\trace + movq %rsp,%rdi /* &pt_regs */ + call sync_regs + movq %rax,%rsp /* switch stack for scheduling */ + testl $_TIF_NEED_RESCHED,%ebx + jnz paranoid_schedule\trace + movl %ebx,%edx /* arg3: thread flags */ + .if \trace + TRACE_IRQS_ON + .endif + sti + xorl %esi,%esi /* arg2: oldset */ + movq %rsp,%rdi /* arg1: &pt_regs */ + call do_notify_resume + cli + .if \trace + TRACE_IRQS_OFF + .endif + jmp paranoid_userspace\trace +paranoid_schedule\trace: + .if \trace + TRACE_IRQS_ON + .endif + sti + call schedule + cli + .if \trace + TRACE_IRQS_OFF + .endif + jmp paranoid_userspace\trace + CFI_ENDPROC + .endm + /* * Exception entry point. This expects an error code/orig_rax on the stack * and the exception handler in %rax. @@ -748,6 +864,7 @@ error_exit: movl %ebx,%eax RESTORE_REST cli + TRACE_IRQS_OFF GET_THREAD_INFO(%rcx) testl %eax,%eax jne retint_kernel @@ -755,6 +872,10 @@ error_exit: movl $_TIF_WORK_MASK,%edi andl %edi,%edx jnz retint_careful + /* + * The iret might restore flags: + */ + TRACE_IRQS_IRETQ swapgs RESTORE_ARGS 0,8,0 jmp iret_label @@ -916,8 +1037,7 @@ KPROBE_ENTRY(debug) pushq $0 CFI_ADJUST_CFA_OFFSET 8 paranoidentry do_debug, DEBUG_STACK - jmp paranoid_exit - CFI_ENDPROC + paranoidexit END(debug) .previous .text @@ -926,49 +1046,13 @@ KPROBE_ENTRY(nmi) INTR_FRAME pushq $-1 CFI_ADJUST_CFA_OFFSET 8 - paranoidentry do_nmi - /* - * "Paranoid" exit path from exception stack. - * Paranoid because this is used by NMIs and cannot take - * any kernel state for granted. - * We don't do kernel preemption checks here, because only - * NMI should be common and it does not enable IRQs and - * cannot get reschedule ticks. - */ - /* ebx: no swapgs flag */ -paranoid_exit: - testl %ebx,%ebx /* swapgs needed? */ - jnz paranoid_restore - testl $3,CS(%rsp) - jnz paranoid_userspace -paranoid_swapgs: - swapgs -paranoid_restore: - RESTORE_ALL 8 - iretq -paranoid_userspace: - GET_THREAD_INFO(%rcx) - movl threadinfo_flags(%rcx),%ebx - andl $_TIF_WORK_MASK,%ebx - jz paranoid_swapgs - movq %rsp,%rdi /* &pt_regs */ - call sync_regs - movq %rax,%rsp /* switch stack for scheduling */ - testl $_TIF_NEED_RESCHED,%ebx - jnz paranoid_schedule - movl %ebx,%edx /* arg3: thread flags */ - sti - xorl %esi,%esi /* arg2: oldset */ - movq %rsp,%rdi /* arg1: &pt_regs */ - call do_notify_resume - cli - jmp paranoid_userspace -paranoid_schedule: - sti - call schedule - cli - jmp paranoid_userspace - CFI_ENDPROC + paranoidentry do_nmi, 0, 0 +#ifdef CONFIG_TRACE_IRQFLAGS + paranoidexit 0 +#else + jmp paranoid_exit1 + CFI_ENDPROC +#endif END(nmi) .previous .text @@ -977,7 +1061,7 @@ KPROBE_ENTRY(int3) pushq $0 CFI_ADJUST_CFA_OFFSET 8 paranoidentry do_int3, DEBUG_STACK - jmp paranoid_exit + jmp paranoid_exit1 CFI_ENDPROC END(int3) .previous .text @@ -1006,7 +1090,7 @@ END(reserved) ENTRY(double_fault) XCPT_FRAME paranoidentry do_double_fault - jmp paranoid_exit + jmp paranoid_exit1 CFI_ENDPROC END(double_fault) @@ -1022,7 +1106,7 @@ END(segment_not_present) ENTRY(stack_segment) XCPT_FRAME paranoidentry do_stack_segment - jmp paranoid_exit + jmp paranoid_exit1 CFI_ENDPROC END(stack_segment) @@ -1050,7 +1134,7 @@ ENTRY(machine_check) pushq $0 CFI_ADJUST_CFA_OFFSET 8 paranoidentry do_machine_check - jmp paranoid_exit + jmp paranoid_exit1 CFI_ENDPROC END(machine_check) #endif diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c index e6a71c9556d..36647ce6aec 100644 --- a/arch/x86_64/kernel/head64.c +++ b/arch/x86_64/kernel/head64.c @@ -85,6 +85,11 @@ void __init x86_64_start_kernel(char * real_mode_data) clear_bss(); /* + * This must be called really, really early: + */ + lockdep_init(); + + /* * switch to init_level4_pgt from boot_level4_pgt */ memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t)); diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c index a1f1df5f7bf..5221a53e90c 100644 --- a/arch/x86_64/kernel/irq.c +++ b/arch/x86_64/kernel/irq.c @@ -177,8 +177,10 @@ asmlinkage void do_softirq(void) local_irq_save(flags); pending = local_softirq_pending(); /* Switch to interrupt stack */ - if (pending) + if (pending) { call_softirq(); + WARN_ON_ONCE(softirq_count()); + } local_irq_restore(flags); } EXPORT_SYMBOL(do_softirq); diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 476c1472fc0..5baa0c726e9 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -127,7 +127,7 @@ void __cpuinit nmi_watchdog_default(void) static __init void nmi_cpu_busy(void *data) { volatile int *endflag = data; - local_irq_enable(); + local_irq_enable_in_hardirq(); /* Intentionally don't use cpu_relax here. This is to make sure that the performance counter really ticks, even if there is a simulator or similar that catches the diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index ca56e19b8b6..bb6745d13b8 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -296,7 +296,7 @@ void __show_regs(struct pt_regs * regs) system_utsname.version); printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip); printk_address(regs->rip); - printk("\nRSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, + printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags); printk("RAX: %016lx RBX: %016lx RCX: %016lx\n", regs->rax, regs->rbx, regs->rcx); diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 9705a6a384f..b7c70596979 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -775,6 +775,8 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) }; DECLARE_WORK(work, do_fork_idle, &c_idle); + lockdep_set_class(&c_idle.done.wait.lock, &waitqueue_lock_key); + /* allocate memory for gdts of secondary cpus. Hotplug is considered */ if (!cpu_gdt_descr[cpu].address && !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) { diff --git a/arch/x86_64/kernel/stacktrace.c b/arch/x86_64/kernel/stacktrace.c new file mode 100644 index 00000000000..32cf55eb9af --- /dev/null +++ b/arch/x86_64/kernel/stacktrace.c @@ -0,0 +1,221 @@ +/* + * arch/x86_64/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> + +#include <asm/smp.h> + +static inline int +in_range(unsigned long start, unsigned long addr, unsigned long end) +{ + return addr >= start && addr <= end; +} + +static unsigned long +get_stack_end(struct task_struct *task, unsigned long stack) +{ + unsigned long stack_start, stack_end, flags; + int i, cpu; + + /* + * The most common case is that we are in the task stack: + */ + stack_start = (unsigned long)task->thread_info; + stack_end = stack_start + THREAD_SIZE; + + if (in_range(stack_start, stack, stack_end)) + return stack_end; + + /* + * We are in an interrupt if irqstackptr is set: + */ + raw_local_irq_save(flags); + cpu = safe_smp_processor_id(); + stack_end = (unsigned long)cpu_pda(cpu)->irqstackptr; + + if (stack_end) { + stack_start = stack_end & ~(IRQSTACKSIZE-1); + if (in_range(stack_start, stack, stack_end)) + goto out_restore; + /* + * We get here if we are in an IRQ context but we + * are also in an exception stack. + */ + } + + /* + * Iterate over all exception stacks, and figure out whether + * 'stack' is in one of them: + */ + for (i = 0; i < N_EXCEPTION_STACKS; i++) { + /* + * set 'end' to the end of the exception stack. + */ + stack_end = per_cpu(init_tss, cpu).ist[i]; + stack_start = stack_end - EXCEPTION_STKSZ; + + /* + * Is 'stack' above this exception frame's end? + * If yes then skip to the next frame. + */ + if (stack >= stack_end) + continue; + /* + * Is 'stack' above this exception frame's start address? + * If yes then we found the right frame. + */ + if (stack >= stack_start) + goto out_restore; + + /* + * If this is a debug stack, and if it has a larger size than + * the usual exception stacks, then 'stack' might still + * be within the lower portion of the debug stack: + */ +#if DEBUG_STKSZ > EXCEPTION_STKSZ + if (i == DEBUG_STACK - 1 && stack >= stack_end - DEBUG_STKSZ) { + /* + * Black magic. A large debug stack is composed of + * multiple exception stack entries, which we + * iterate through now. Dont look: + */ + do { + stack_end -= EXCEPTION_STKSZ; + stack_start -= EXCEPTION_STKSZ; + } while (stack < stack_start); + + goto out_restore; + } +#endif + } + /* + * Ok, 'stack' is not pointing to any of the system stacks. + */ + stack_end = 0; + +out_restore: + raw_local_irq_restore(flags); + + return stack_end; +} + + +/* + * Save stack-backtrace addresses into a stack_trace buffer: + */ +static inline unsigned long +save_context_stack(struct stack_trace *trace, unsigned int skip, + unsigned long stack, unsigned long stack_end) +{ + unsigned long addr; + +#ifdef CONFIG_FRAME_POINTER + unsigned long prev_stack = 0; + + while (in_range(prev_stack, stack, stack_end)) { + pr_debug("stack: %p\n", (void *)stack); + addr = (unsigned long)(((unsigned long *)stack)[1]); + pr_debug("addr: %p\n", (void *)addr); + if (!skip) + trace->entries[trace->nr_entries++] = addr-1; + else + skip--; + if (trace->nr_entries >= trace->max_entries) + break; + if (!addr) + return 0; + /* + * Stack frames must go forwards (otherwise a loop could + * happen if the stackframe is corrupted), so we move + * prev_stack forwards: + */ + prev_stack = stack; + stack = (unsigned long)(((unsigned long *)stack)[0]); + } + pr_debug("invalid: %p\n", (void *)stack); +#else + while (stack < stack_end) { + addr = ((unsigned long *)stack)[0]; + stack += sizeof(long); + if (__kernel_text_address(addr)) { + if (!skip) + trace->entries[trace->nr_entries++] = addr-1; + else + skip--; + if (trace->nr_entries >= trace->max_entries) + break; + } + } +#endif + return stack; +} + +#define MAX_STACKS 10 + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + * If all_contexts is set, all contexts (hardirq, softirq and process) + * are saved. If not set then only the current context is saved. + */ +void save_stack_trace(struct stack_trace *trace, + struct task_struct *task, int all_contexts, + unsigned int skip) +{ + unsigned long stack = (unsigned long)&stack; + int i, nr_stacks = 0, stacks_done[MAX_STACKS]; + + WARN_ON(trace->nr_entries || !trace->max_entries); + + if (!task) + task = current; + + pr_debug("task: %p, ti: %p\n", task, task->thread_info); + + if (!task || task == current) { + /* Grab rbp right from our regs: */ + asm ("mov %%rbp, %0" : "=r" (stack)); + pr_debug("rbp: %p\n", (void *)stack); + } else { + /* rbp is the last reg pushed by switch_to(): */ + stack = task->thread.rsp; + pr_debug("other task rsp: %p\n", (void *)stack); + stack = (unsigned long)(((unsigned long *)stack)[0]); + pr_debug("other task rbp: %p\n", (void *)stack); + } + + while (1) { + unsigned long stack_end = get_stack_end(task, stack); + + pr_debug("stack: %p\n", (void *)stack); + pr_debug("stack end: %p\n", (void *)stack_end); + + /* + * Invalid stack addres? + */ + if (!stack_end) + return; + /* + * Were we in this stack already? (recursion) + */ + for (i = 0; i < nr_stacks; i++) + if (stacks_done[i] == stack_end) + return; + stacks_done[nr_stacks] = stack_end; + + stack = save_context_stack(trace, skip, stack, stack_end); + if (!all_contexts || !stack || + trace->nr_entries >= trace->max_entries) + return; + trace->entries[trace->nr_entries++] = ULONG_MAX; + if (trace->nr_entries >= trace->max_entries) + return; + if (++nr_stacks >= MAX_STACKS) + return; + } +} + diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index ebbee6f59ff..b9ff75992c1 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -889,7 +889,7 @@ int __init time_setup(char *str) } static struct irqaction irq0 = { - timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL + timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL }; void __init time_init(void) diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 5a5311d3de0..79d05c48207 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -110,28 +110,31 @@ static int kstack_depth_to_print = 12; static int call_trace = 1; #ifdef CONFIG_KALLSYMS -#include <linux/kallsyms.h> -int printk_address(unsigned long address) -{ +# include <linux/kallsyms.h> +void printk_address(unsigned long address) +{ unsigned long offset = 0, symsize; const char *symname; char *modname; - char *delim = ":"; + char *delim = ":"; char namebuf[128]; - symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf); - if (!symname) - return printk("[<%016lx>]", address); - if (!modname) + symname = kallsyms_lookup(address, &symsize, &offset, + &modname, namebuf); + if (!symname) { + printk(" [<%016lx>]\n", address); + return; + } + if (!modname) modname = delim = ""; - return printk("<%016lx>{%s%s%s%s%+ld}", - address, delim, modname, delim, symname, offset); -} + printk(" [<%016lx>] %s%s%s%s+0x%lx/0x%lx\n", + address, delim, modname, delim, symname, offset, symsize); +} #else -int printk_address(unsigned long address) -{ - return printk("[<%016lx>]", address); -} +void printk_address(unsigned long address) +{ + printk(" [<%016lx>]\n", address); +} #endif static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, @@ -149,10 +152,22 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, }; unsigned k; + /* + * Iterate over all exception stacks, and figure out whether + * 'stack' is in one of them: + */ for (k = 0; k < N_EXCEPTION_STACKS; k++) { unsigned long end; + /* + * set 'end' to the end of the exception stack. + */ switch (k + 1) { + /* + * TODO: this block is not needed i think, because + * setup64.c:cpu_init() sets up t->ist[DEBUG_STACK] + * properly too. + */ #if DEBUG_STKSZ > EXCEPTION_STKSZ case DEBUG_STACK: end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ; @@ -162,19 +177,43 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, end = per_cpu(init_tss, cpu).ist[k]; break; } + /* + * Is 'stack' above this exception frame's end? + * If yes then skip to the next frame. + */ if (stack >= end) continue; + /* + * Is 'stack' above this exception frame's start address? + * If yes then we found the right frame. + */ if (stack >= end - EXCEPTION_STKSZ) { + /* + * Make sure we only iterate through an exception + * stack once. If it comes up for the second time + * then there's something wrong going on - just + * break out and return NULL: + */ if (*usedp & (1U << k)) break; *usedp |= 1U << k; *idp = ids[k]; return (unsigned long *)end; } + /* + * If this is a debug stack, and if it has a larger size than + * the usual exception stacks, then 'stack' might still + * be within the lower portion of the debug stack: + */ #if DEBUG_STKSZ > EXCEPTION_STKSZ if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) { unsigned j = N_EXCEPTION_STACKS - 1; + /* + * Black magic. A large debug stack is composed of + * multiple exception stack entries, which we + * iterate through now. Dont look: + */ do { ++j; end -= EXCEPTION_STKSZ; @@ -193,20 +232,14 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, static int show_trace_unwind(struct unwind_frame_info *info, void *context) { - int i = 11, n = 0; + int n = 0; while (unwind(info) == 0 && UNW_PC(info)) { - ++n; - if (i > 50) { - printk("\n "); - i = 7; - } else - i += printk(" "); - i += printk_address(UNW_PC(info)); + n++; + printk_address(UNW_PC(info)); if (arch_unw_user_mode(info)) break; } - printk("\n"); return n; } @@ -224,7 +257,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s int i = 11; unsigned used = 0; - printk("\nCall Trace:"); + printk("\nCall Trace:\n"); if (!tsk) tsk = current; @@ -250,16 +283,15 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s } } + /* + * Print function call entries within a stack. 'cond' is the + * "end of stackframe" condition, that the 'stack++' + * iteration will eventually trigger. + */ #define HANDLE_STACK(cond) \ do while (cond) { \ unsigned long addr = *stack++; \ if (kernel_text_address(addr)) { \ - if (i > 50) { \ - printk("\n "); \ - i = 0; \ - } \ - else \ - i += printk(" "); \ /* \ * If the address is either in the text segment of the \ * kernel, or in the region which contains vmalloc'ed \ @@ -268,20 +300,30 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s * down the cause of the crash will be able to figure \ * out the call path that was taken. \ */ \ - i += printk_address(addr); \ + printk_address(addr); \ } \ } while (0) - for(; ; ) { + /* + * Print function call entries in all stacks, starting at the + * current stack address. If the stacks consist of nested + * exceptions + */ + for ( ; ; ) { const char *id; unsigned long *estack_end; estack_end = in_exception_stack(cpu, (unsigned long)stack, &used, &id); if (estack_end) { - i += printk(" <%s>", id); + printk(" <%s>", id); HANDLE_STACK (stack < estack_end); - i += printk(" <EOE>"); + printk(" <EOE>"); + /* + * We link to the next stack via the + * second-to-last pointer (index -2 to end) in the + * exception stack: + */ stack = (unsigned long *) estack_end[-2]; continue; } @@ -291,19 +333,28 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s (IRQSTACKSIZE - 64) / sizeof(*irqstack); if (stack >= irqstack && stack < irqstack_end) { - i += printk(" <IRQ>"); + printk(" <IRQ>"); HANDLE_STACK (stack < irqstack_end); + /* + * We link to the next stack (which would be + * the process stack normally) the last + * pointer (index -1 to end) in the IRQ stack: + */ stack = (unsigned long *) (irqstack_end[-1]); irqstack_end = NULL; - i += printk(" <EOI>"); + printk(" <EOI>"); continue; } } break; } + /* + * This prints the process stack: + */ HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0); #undef HANDLE_STACK + printk("\n"); } @@ -337,8 +388,8 @@ static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned break; } if (i && ((i % 4) == 0)) - printk("\n "); - printk("%016lx ", *stack++); + printk("\n"); + printk(" %016lx", *stack++); touch_nmi_watchdog(); } show_trace(tsk, regs, rsp); diff --git a/arch/x86_64/lib/thunk.S b/arch/x86_64/lib/thunk.S index e49af0032e9..332ea5dff91 100644 --- a/arch/x86_64/lib/thunk.S +++ b/arch/x86_64/lib/thunk.S @@ -47,6 +47,11 @@ thunk_retrax __down_failed_interruptible,__down_interruptible thunk_retrax __down_failed_trylock,__down_trylock thunk __up_wakeup,__up + +#ifdef CONFIG_TRACE_IRQFLAGS + thunk trace_hardirqs_on_thunk,trace_hardirqs_on + thunk trace_hardirqs_off_thunk,trace_hardirqs_off +#endif /* SAVE_ARGS below is used only for the .cfi directives it contains. */ CFI_STARTPROC diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 5afcf6eb00f..ac8ea66ccb9 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -570,7 +570,6 @@ no_context: printk(KERN_ALERT "Unable to handle kernel paging request"); printk(" at %016lx RIP: \n" KERN_ALERT,address); printk_address(regs->rip); - printk("\n"); dump_pagetable(address); tsk->thread.cr2 = address; tsk->thread.trap_no = 14; diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 4a2c365ba68..412ab32de39 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -52,7 +52,7 @@ unsigned long long sched_clock(void) static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "timer", }; |