summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig22
-rw-r--r--arch/arm/boot/compressed/Makefile4
-rw-r--r--arch/arm/boot/compressed/head-shmobile.S53
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/common/gic.c69
-rw-r--r--arch/arm/common/timer-sp.c (renamed from arch/arm/plat-versatile/timer-sp.c)4
-rw-r--r--arch/arm/include/asm/elf.h2
-rw-r--r--arch/arm/include/asm/hardware/entry-macro-gic.S75
-rw-r--r--arch/arm/include/asm/hardware/gic.h7
-rw-r--r--arch/arm/include/asm/hardware/timer-sp.h (renamed from arch/arm/plat-versatile/include/plat/timer-sp.h)0
-rw-r--r--arch/arm/include/asm/io.h13
-rw-r--r--arch/arm/include/asm/kexec.h18
-rw-r--r--arch/arm/include/asm/module.h15
-rw-r--r--arch/arm/kernel/machine_kexec.c30
-rw-r--r--arch/arm/kernel/module.c109
-rw-r--r--arch/arm/kernel/smp_twd.c7
-rw-r--r--arch/arm/mach-cns3xxx/core.c7
-rw-r--r--arch/arm/mach-cns3xxx/core.h1
-rw-r--r--arch/arm/mach-cns3xxx/include/mach/entry-macro.S66
-rw-r--r--arch/arm/mach-davinci/include/mach/io.h4
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c2
-rw-r--r--arch/arm/mach-iop13xx/include/mach/io.h4
-rw-r--r--arch/arm/mach-iop32x/include/mach/io.h4
-rw-r--r--arch/arm/mach-iop33x/include/mach/io.h4
-rw-r--r--arch/arm/mach-ixp23xx/include/mach/io.h4
-rw-r--r--arch/arm/mach-ixp4xx/include/mach/io.h4
-rw-r--r--arch/arm/mach-kirkwood/include/mach/io.h4
-rw-r--r--arch/arm/mach-msm/board-msm8x60.c7
-rw-r--r--arch/arm/mach-omap2/include/mach/entry-macro.S93
-rw-r--r--arch/arm/mach-omap2/include/mach/omap4-common.h1
-rw-r--r--arch/arm/mach-omap2/omap-smp.c2
-rw-r--r--arch/arm/mach-omap2/omap4-common.c11
-rw-r--r--arch/arm/mach-orion5x/include/mach/io.h4
-rw-r--r--arch/arm/mach-realview/core.c5
-rw-r--r--arch/arm/mach-realview/core.h1
-rw-r--r--arch/arm/mach-realview/include/mach/entry-macro.S65
-rw-r--r--arch/arm/mach-realview/platsmp.c2
-rw-r--r--arch/arm/mach-realview/realview_eb.c14
-rw-r--r--arch/arm/mach-realview/realview_pb1176.c11
-rw-r--r--arch/arm/mach-realview/realview_pb11mp.c10
-rw-r--r--arch/arm/mach-realview/realview_pba8.c6
-rw-r--r--arch/arm/mach-realview/realview_pbx.c13
-rw-r--r--arch/arm/mach-s5pv310/cpu.c6
-rw-r--r--arch/arm/mach-s5pv310/include/mach/smp.h2
-rw-r--r--arch/arm/mach-s5pv310/platsmp.c2
-rw-r--r--arch/arm/mach-sa1100/Kconfig10
-rw-r--r--arch/arm/mach-sa1100/Makefile3
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c51
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1110.c57
-rw-r--r--arch/arm/mach-sa1100/generic.c41
-rw-r--r--arch/arm/mach-sa1100/include/mach/hardware.h8
-rw-r--r--arch/arm/mach-sa1100/include/mach/nanoengine.h52
-rw-r--r--arch/arm/mach-sa1100/nanoengine.c119
-rw-r--r--arch/arm/mach-sa1100/pci-nanoengine.c284
-rw-r--r--arch/arm/mach-sa1100/simpad.c7
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c1
-rw-r--r--arch/arm/mach-shmobile/include/mach/head-ap4evb.txt87
-rw-r--r--arch/arm/mach-shmobile/include/mach/zboot.h20
-rw-r--r--arch/arm/mach-shmobile/include/mach/zboot_macros.h65
-rw-r--r--arch/arm/mach-tegra/include/mach/entry-macro.S66
-rw-r--r--arch/arm/mach-tegra/include/mach/io.h4
-rw-r--r--arch/arm/mach-tegra/irq.c4
-rw-r--r--arch/arm/mach-tegra/platsmp.c2
-rw-r--r--arch/arm/mach-ux500/cpu.c4
-rw-r--r--arch/arm/mach-ux500/include/mach/entry-macro.S68
-rw-r--r--arch/arm/mach-ux500/platsmp.c2
-rw-r--r--arch/arm/mach-versatile/core.c2
-rw-r--r--arch/arm/mach-vexpress/core.h2
-rw-r--r--arch/arm/mach-vexpress/ct-ca9x4.c9
-rw-r--r--arch/arm/mach-vexpress/include/mach/entry-macro.S62
-rw-r--r--arch/arm/mach-vexpress/platsmp.c2
-rw-r--r--arch/arm/mach-vexpress/v2m.c2
-rw-r--r--arch/arm/plat-omap/include/plat/io.h4
-rw-r--r--arch/arm/plat-versatile/Makefile1
-rw-r--r--drivers/pcmcia/Makefile3
-rw-r--r--drivers/pcmcia/sa1100_generic.c3
-rw-r--r--drivers/pcmcia/sa1100_generic.h1
-rw-r--r--drivers/pcmcia/sa1100_nanoengine.c219
-rw-r--r--drivers/pcmcia/soc_common.c128
-rw-r--r--drivers/rtc/rtc-sa1100.c161
-rw-r--r--fs/proc/vmcore.c2
-rw-r--r--include/linux/crash_dump.h9
-rw-r--r--scripts/recordmcount.c7
-rw-r--r--scripts/recordmcount.h5
84 files changed, 1612 insertions, 753 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c0573b..9d2608363390 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -23,6 +23,7 @@ config ARM
select PERF_USE_VMALLOC
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
+ select HAVE_C_RECORDMCOUNT
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
@@ -1164,7 +1165,7 @@ config ISA_DMA_API
bool
config PCI
- bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+ bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || SA1100_NANOENGINE
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1175,6 +1176,12 @@ config PCI_DOMAINS
bool
depends on PCI
+config PCI_NANOENGINE
+ bool "BSE nanoEngine PCI support"
+ depends on SA1100_NANOENGINE
+ help
+ Enable PCI on the BSE nanoEngine board.
+
config PCI_SYSCALL
def_bool PCI
@@ -1650,6 +1657,19 @@ config ATAGS_PROC
Should the atags used to boot the kernel be exported in an "atags"
file in procfs. Useful with kexec.
+config CRASH_DUMP
+ bool "Build kdump crash kernel (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ Generate crash dump after being started by kexec. This should
+ be normally only set in special crash dump kernels which are
+ loaded in the main kernel with kexec-tools into a specially
+ reserved region and then later executed after a crash by
+ kdump/kexec. The crash dump kernel must be compiled to a
+ memory address not used by the main kernel
+
+ For more details see Documentation/kdump/kdump.txt
+
config AUTO_ZRELADDR
bool "Auto calculation of the decompressed kernel image address"
depends on !ZBOOT_ROM && !ARCH_U300
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 65a7c1c588a9..0a8f748e506a 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -45,6 +45,10 @@ else
endif
endif
+ifeq ($(CONFIG_ARCH_SHMOBILE),y)
+OBJS += head-shmobile.o
+endif
+
#
# We now have a PIC decompressor implementation. Decompressors running
# from RAM should not define ZTEXTADDR. Decompressors running directly
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
new file mode 100644
index 000000000000..30973b76e6ae
--- /dev/null
+++ b/arch/arm/boot/compressed/head-shmobile.S
@@ -0,0 +1,53 @@
+/*
+ * The head-file for SH-Mobile ARM platforms
+ *
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Simon Horman <horms@verge.net.au>
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef CONFIG_ZBOOT_ROM
+
+ .section ".start", "ax"
+
+ /* load board-specific initialization code */
+#include <mach/zboot.h>
+
+ b 1f
+__atags:@ tag #1
+ .long 12 @ tag->hdr.size = tag_size(tag_core);
+ .long 0x54410001 @ tag->hdr.tag = ATAG_CORE;
+ .long 0 @ tag->u.core.flags = 0;
+ .long 0 @ tag->u.core.pagesize = 0;
+ .long 0 @ tag->u.core.rootdev = 0;
+ @ tag #2
+ .long 8 @ tag->hdr.size = tag_size(tag_mem32);
+ .long 0x54410002 @ tag->hdr.tag = ATAG_MEM;
+ .long CONFIG_MEMORY_SIZE @ tag->u.mem.size = CONFIG_MEMORY_SIZE;
+ .long CONFIG_MEMORY_START @ @ tag->u.mem.start = CONFIG_MEMORY_START;
+ @ tag #3
+ .long 0 @ tag->hdr.size = 0
+ .long 0 @ tag->hdr.tag = ATAG_NONE;
+1:
+
+ /* Set board ID necessary for boot */
+ ldr r7, 1f @ Set machine type register
+ adr r8, __atags @ Set atag register
+ b 2f
+
+1 : .long MACH_TYPE
+2 :
+
+#endif /* CONFIG_ZBOOT_ROM */
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index e6e8664a9413..e7521bca2c35 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_ARCH_IXP2000) += uengine.o
obj-$(CONFIG_ARCH_IXP23XX) += uengine.o
obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
obj-$(CONFIG_COMMON_CLKDEV) += clkdev.o
+obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index e6388dcd8cfa..0b89ef001330 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -35,6 +35,9 @@
static DEFINE_SPINLOCK(irq_controller_lock);
+/* Address of GIC 0 CPU interface */
+void __iomem *gic_cpu_base_addr __read_mostly;
+
struct gic_chip_data {
unsigned int irq_offset;
void __iomem *dist_base;
@@ -45,7 +48,7 @@ struct gic_chip_data {
#define MAX_GIC_NR 1
#endif
-static struct gic_chip_data gic_data[MAX_GIC_NR];
+static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
static inline void __iomem *gic_dist_base(unsigned int irq)
{
@@ -213,21 +216,16 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
set_irq_chained_handler(irq, gic_handle_cascade_irq);
}
-void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
- unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic,
+ unsigned int irq_start)
{
unsigned int gic_irqs, irq_limit, i;
+ void __iomem *base = gic->dist_base;
u32 cpumask = 1 << smp_processor_id();
- if (gic_nr >= MAX_GIC_NR)
- BUG();
-
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
- gic_data[gic_nr].dist_base = base;
- gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
-
writel(0, base + GIC_DIST_CTRL);
/*
@@ -267,7 +265,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
/*
* Limit number of interrupts registered to the platform maximum
*/
- irq_limit = gic_data[gic_nr].irq_offset + gic_irqs;
+ irq_limit = gic->irq_offset + gic_irqs;
if (WARN_ON(irq_limit > NR_IRQS))
irq_limit = NR_IRQS;
@@ -276,7 +274,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
*/
for (i = irq_start; i < irq_limit; i++) {
set_irq_chip(i, &gic_chip);
- set_irq_chip_data(i, &gic_data[gic_nr]);
+ set_irq_chip_data(i, gic);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
@@ -284,19 +282,12 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
writel(1, base + GIC_DIST_CTRL);
}
-void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
+static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
{
- void __iomem *dist_base;
+ void __iomem *dist_base = gic->dist_base;
+ void __iomem *base = gic->cpu_base;
int i;
- if (gic_nr >= MAX_GIC_NR)
- BUG();
-
- dist_base = gic_data[gic_nr].dist_base;
- BUG_ON(!dist_base);
-
- gic_data[gic_nr].cpu_base = base;
-
/*
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
@@ -314,6 +305,42 @@ void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
writel(1, base + GIC_CPU_CTRL);
}
+void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+ void __iomem *dist_base, void __iomem *cpu_base)
+{
+ struct gic_chip_data *gic;
+
+ BUG_ON(gic_nr >= MAX_GIC_NR);
+
+ gic = &gic_data[gic_nr];
+ gic->dist_base = dist_base;
+ gic->cpu_base = cpu_base;
+ gic->irq_offset = (irq_start - 1) & ~31;
+
+ if (gic_nr == 0)
+ gic_cpu_base_addr = cpu_base;
+
+ gic_dist_init(gic, irq_start);
+ gic_cpu_init(gic);
+}
+
+void __cpuinit gic_secondary_init(unsigned int gic_nr)
+{
+ BUG_ON(gic_nr >= MAX_GIC_NR);
+
+ gic_cpu_init(&gic_data[gic_nr]);
+}
+
+void __cpuinit gic_enable_ppi(unsigned int irq)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ irq_to_desc(irq)->status |= IRQ_NOPROBE;
+ gic_unmask_irq(irq);
+ local_irq_restore(flags);
+}
+
#ifdef CONFIG_SMP
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
diff --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/common/timer-sp.c
index fb0d1c299718..4740313daa5b 100644
--- a/arch/arm/plat-versatile/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/arm/plat-versatile/timer-sp.c
+ * linux/arch/arm/common/timer-sp.c
*
* Copyright (C) 1999 - 2003 ARM Limited
* Copyright (C) 2000 Deep Blue Solutions Ltd
@@ -26,8 +26,6 @@
#include <asm/hardware/arm_timer.h>
-#include <plat/timer-sp.h>
-
/*
* These timers are currently always setup to be clocked at 1MHz.
*/
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 8bb66bca2e3e..c3cd8755e648 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -99,6 +99,8 @@ struct elf32_hdr;
extern int elf_check_arch(const struct elf32_hdr *);
#define elf_check_arch elf_check_arch
+#define vmcore_elf64_check_arch(x) (0)
+
extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
new file mode 100644
index 000000000000..c115b82fe80a
--- /dev/null
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/include/asm/hardware/entry-macro-gic.S
+ *
+ * Low-level IRQ helper macros for GIC
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/hardware/gic.h>
+
+#ifndef HAVE_GET_IRQNR_PREAMBLE
+ .macro get_irqnr_preamble, base, tmp
+ ldr \base, =gic_cpu_base_addr
+ ldr \base, [\base]
+ .endm
+#endif
+
+/*
+ * The interrupt numbering scheme is defined in the
+ * interrupt controller spec. To wit:
+ *
+ * Interrupts 0-15 are IPI
+ * 16-28 are reserved
+ * 29-31 are local. We allow 30 to be used for the watchdog.
+ * 32-1020 are global
+ * 1021-1022 are reserved
+ * 1023 is "spurious" (no interrupt)
+ *
+ * For now, we ignore all local interrupts so only return an interrupt if it's
+ * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
+ *
+ * A simple read from the controller will tell us the number of the highest
+ * priority enabled interrupt. We then just need to check whether it is in the
+ * valid range for an IRQ (30-1020 inclusive).
+ */
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+ ldr \irqstat, [\base, #GIC_CPU_INTACK]
+ /* bits 12-10 = src CPU, 9-0 = int # */
+
+ ldr \tmp, =1021
+ bic \irqnr, \irqstat, #0x1c00
+ cmp \irqnr, #29
+ cmpcc \irqnr, \irqnr
+ cmpne \irqnr, \tmp
+ cmpcs \irqnr, \irqnr
+ .endm
+
+/* We assume that irqstat (the raw value of the IRQ acknowledge
+ * register) is preserved from the macro above.
+ * If there is an IPI, we immediately signal end of interrupt on the
+ * controller, since this requires the original irqstat value which
+ * we won't easily be able to recreate later.
+ */
+
+ .macro test_for_ipi, irqnr, irqstat, base, tmp
+ bic \irqnr, \irqstat, #0x1c00
+ cmp \irqnr, #16
+ strcc \irqstat, [\base, #GIC_CPU_EOI]
+ cmpcs \irqnr, \irqnr
+ .endm
+
+/* As above, this assumes that irqstat and base are preserved.. */
+
+ .macro test_for_ltirq, irqnr, irqstat, base, tmp
+ bic \irqnr, \irqstat, #0x1c00
+ mov \tmp, #0
+ cmp \irqnr, #29
+ moveq \tmp, #1
+ streq \irqstat, [\base, #GIC_CPU_EOI]
+ cmp \tmp, #0
+ .endm
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 7f34333bb545..84557d321001 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,10 +33,13 @@
#define GIC_DIST_SOFTINT 0xf00
#ifndef __ASSEMBLY__
-void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
-void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+extern void __iomem *gic_cpu_base_addr;
+
+void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_secondary_init(unsigned int);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
+void gic_enable_ppi(unsigned int);
#endif
#endif
diff --git a/arch/arm/plat-versatile/include/plat/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h
index 21e75e30d497..21e75e30d497 100644
--- a/arch/arm/plat-versatile/include/plat/timer-sp.h
+++ b/arch/arm/include/asm/hardware/timer-sp.h
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 815efa2d4e07..20e0f7c9e03e 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -241,18 +241,15 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
*
*/
#ifndef __arch_ioremap
-#define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
-#define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC)
-#define iounmap(cookie) __iounmap(cookie)
-#else
+#define __arch_ioremap __arm_ioremap
+#define __arch_iounmap __iounmap
+#endif
+
#define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
-#define iounmap(cookie) __arch_iounmap(cookie)
-#endif
+#define iounmap __arch_iounmap
/*
* io{read,write}{8,16,32} macros
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index 8ec9ef5c3c7b..c0094d8edae4 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -33,10 +33,20 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
if (oldregs) {
memcpy(newregs, oldregs, sizeof(*newregs));
} else {
- __asm__ __volatile__ ("stmia %0, {r0 - r15}"
- : : "r" (&newregs->ARM_r0));
- __asm__ __volatile__ ("mrs %0, cpsr"
- : "=r" (newregs->ARM_cpsr));
+ __asm__ __volatile__ (
+ "stmia %[regs_base], {r0-r12}\n\t"
+ "mov %[_ARM_sp], sp\n\t"
+ "str lr, %[_ARM_lr]\n\t"
+ "adr %[_ARM_pc], 1f\n\t"
+ "mrs %[_ARM_cpsr], cpsr\n\t"
+ "1:"
+ : [_ARM_pc] "=r" (newregs->ARM_pc),
+ [_ARM_cpsr] "=r" (newregs->ARM_cpsr),
+ [_ARM_sp] "=r" (newregs->ARM_sp),
+ [_ARM_lr] "=o" (newregs->ARM_lr)
+ : [regs_base] "r" (&newregs->ARM_r0)
+ : "memory"
+ );
}
}
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index cbb0bc295d2b..12c8e680cbff 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -8,11 +8,6 @@
struct unwind_table;
#ifdef CONFIG_ARM_UNWIND
-struct arm_unwind_mapping {
- Elf_Shdr *unw_sec;
- Elf_Shdr *sec_text;
- struct unwind_table *unwind;
-};
enum {
ARM_SEC_INIT,
ARM_SEC_DEVINIT,
@@ -21,13 +16,13 @@ enum {
ARM_SEC_DEVEXIT,
ARM_SEC_MAX,
};
+#endif
+
struct mod_arch_specific {
- struct arm_unwind_mapping map[ARM_SEC_MAX];
-};
-#else
-struct mod_arch_specific {
-};
+#ifdef CONFIG_ARM_UNWIND
+ struct unwind_table *unwind[ARM_SEC_MAX];
#endif
+};
/*
* Include the ARM architecture version.
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 3a8fd5140d7a..30ead135ff5f 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -23,6 +23,8 @@ extern unsigned long kexec_indirection_page;
extern unsigned long kexec_mach_type;
extern unsigned long kexec_boot_atags;
+static atomic_t waiting_for_crash_ipi;
+
/*
* Provide a dummy crash_notes definition while crash dump arrives to arm.
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -37,9 +39,37 @@ void machine_kexec_cleanup(struct kimage *image)
{
}
+void machine_crash_nonpanic_core(void *unused)
+{
+ struct pt_regs regs;
+
+ crash_setup_regs(&regs, NULL);
+ printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
+ smp_processor_id());
+ crash_save_cpu(&regs, smp_processor_id());
+ flush_cache_all();
+
+ atomic_dec(&waiting_for_crash_ipi);
+ while (1)
+ cpu_relax();
+}
+
void machine_crash_shutdown(struct pt_regs *regs)
{
+ unsigned long msecs;
+
local_irq_disable();
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+ smp_call_function(machine_crash_nonpanic_core, NULL, false);
+ msecs = 1000; /* Wait at most a second for the other cpus to stop */
+ while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+ mdelay(1);
+ msecs--;
+ }
+ if (atomic_read(&waiting_for_crash_ipi) > 0)
+ printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
+
crash_save_cpu(regs, smp_processor_id());
printk(KERN_INFO "Loading crashdump kernel...\n");
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index d9bd786ce23d..0c1bb68ff4a8 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -67,35 +67,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
char *secstrings,
struct module *mod)
{
-#ifdef CONFIG_ARM_UNWIND
- Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
- struct arm_unwind_mapping *maps = mod->arch.map;
-
- for (s = sechdrs; s < sechdrs_end; s++) {
- char const *secname = secstrings + s->sh_name;
-
- if (strcmp(".ARM.exidx.init.text", secname) == 0)
- maps[ARM_SEC_INIT].unw_sec = s;
- else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
- maps[ARM_SEC_DEVINIT].unw_sec = s;
- else if (strcmp(".ARM.exidx", secname) == 0)
- maps[ARM_SEC_CORE].unw_sec = s;
- else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
- maps[ARM_SEC_EXIT].unw_sec = s;
- else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
- maps[ARM_SEC_DEVEXIT].unw_sec = s;
- else if (strcmp(".init.text", secname) == 0)
- maps[ARM_SEC_INIT].sec_text = s;
- else if (strcmp(".devinit.text", secname) == 0)
- maps[ARM_SEC_DEVINIT].sec_text = s;
- else if (strcmp(".text", secname) == 0)
- maps[ARM_SEC_CORE].sec_text = s;
- else if (strcmp(".exit.text", secname) == 0)
- maps[ARM_SEC_EXIT].sec_text = s;
- else if (strcmp(".devexit.text", secname) == 0)
- maps[ARM_SEC_DEVEXIT].sec_text = s;
- }
-#endif
return 0;
}
@@ -300,41 +271,69 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
return -ENOEXEC;
}
-#ifdef CONFIG_ARM_UNWIND
-static void register_unwind_tables(struct module *mod)
+struct mod_unwind_map {
+ const Elf_Shdr *unw_sec;
+ const Elf_Shdr *txt_sec;
+};
+
+int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ struct module *mod)
{
+#ifdef CONFIG_ARM_UNWIND
+ const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+ const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+ struct mod_unwind_map maps[ARM_SEC_MAX];
int i;
- for (i = 0; i < ARM_SEC_MAX; ++i) {
- struct arm_unwind_mapping *map = &mod->arch.map[i];
- if (map->unw_sec && map->sec_text)
- map->unwind = unwind_table_add(map->unw_sec->sh_addr,
- map->unw_sec->sh_size,
- map->sec_text->sh_addr,
- map->sec_text->sh_size);
+
+ memset(maps, 0, sizeof(maps));
+
+ for (s = sechdrs; s < sechdrs_end; s++) {
+ const char *secname = secstrs + s->sh_name;
+
+ if (!(s->sh_flags & SHF_ALLOC))
+ continue;
+
+ if (strcmp(".ARM.exidx.init.text", secname) == 0)
+ maps[ARM_SEC_INIT].unw_sec = s;
+ else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+ maps[ARM_SEC_DEVINIT].unw_sec = s;
+ else if (strcmp(".ARM.exidx", secname) == 0)
+ maps[ARM_SEC_CORE].unw_sec = s;
+ else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+ maps[ARM_SEC_EXIT].unw_sec = s;
+ else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+ maps[ARM_SEC_DEVEXIT].unw_sec = s;
+ else if (strcmp(".init.text", secname) == 0)
+ maps[ARM_SEC_INIT].txt_sec = s;
+ else if (strcmp(".devinit.text", secname) == 0)
+ maps[ARM_SEC_DEVINIT].txt_sec = s;
+ else if (strcmp(".text", secname) == 0)
+ maps[ARM_SEC_CORE].txt_sec = s;
+ else if (strcmp(".exit.text", secname) == 0)
+ maps[ARM_SEC_EXIT].txt_sec = s;
+ else if (strcmp(".devexit.text", secname) == 0)
+ maps[ARM_SEC_DEVEXIT].txt_sec = s;
}
-}
-static void unregister_unwind_tables(struct module *mod)
-{
- int i = ARM_SEC_MAX;
- while (--i >= 0)
- unwind_table_del(mod->arch.map[i].unwind);
-}
-#else
-static inline void register_unwind_tables(struct module *mod) { }
-static inline void unregister_unwind_tables(struct module *mod) { }
+ for (i = 0; i < ARM_SEC_MAX; i++)
+ if (maps[i].unw_sec && maps[i].txt_sec)
+ mod->arch.unwind[i] =
+ unwind_table_add(maps[i].unw_sec->sh_addr,
+ maps[i].unw_sec->sh_size,
+ maps[i].txt_sec->sh_addr,
+ maps[i].txt_sec->sh_size);
#endif
-
-int
-module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
- struct module *module)
-{
- register_unwind_tables(module);
return 0;
}
void
module_arch_cleanup(struct module *mod)
{
- unregister_unwind_tables(mod);
+#ifdef CONFIG_ARM_UNWIND
+ int i;
+
+ for (i = 0; i < ARM_SEC_MAX; i++)
+ if (mod->arch.unwind[i])
+ unwind_table_del(mod->arch.unwind[i]);
+#endif
}
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 35882fbf37f9..67f933ec4177 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -127,8 +127,6 @@ static void __cpuinit twd_calibrate_rate(void)
*/
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
{
- unsigned long flags;
-
twd_calibrate_rate();
clk->name = "local_timer";
@@ -143,10 +141,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
/* Make sure our local interrupt controller has this enabled */
- local_irq_save(flags);
- irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
- get_irq_chip(clk->irq)->unmask(clk->irq);
- local_irq_restore(flags);
+ gic_enable_ppi(clk->irq);
clockevents_register_device(clk);
}
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 9ca4d581016f..da30078a80c1 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -69,13 +69,10 @@ void __init cns3xxx_map_io(void)
}
/* used by entry-macro.S */
-void __iomem *gic_cpu_base_addr;
-
void __init cns3xxx_init_irq(void)
{
- gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT);
- gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29);
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
+ __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
}
void cns3xxx_power_off(void)
diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h
index 6b33ec11346e..ef9e5116b1a9 100644
--- a/arch/arm/mach-cns3xxx/core.h
+++ b/arch/arm/mach-cns3xxx/core.h
@@ -11,7 +11,6 @@
#ifndef __CNS3XXX_CORE_H
#define __CNS3XXX_CORE_H
-extern void __iomem *gic_cpu_base_addr;
extern struct sys_timer cns3xxx_timer;
void __init cns3xxx_map_io(void);
diff --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
index 5e1c5545680f..6bd83ed90afe 100644
--- a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
+++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S
@@ -9,74 +9,10 @@
*/
#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =gic_cpu_base_addr
- ldr \base, [\base]
- .endm
-
.macro arch_ret_to_user, tmp1, tmp2
.endm
-
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * For now, we ignore all local interrupts so only return an interrupt if it's
- * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
- *
- * A simple read from the controller will tell us the number of the highest
- * priority enabled interrupt. We then just need to check whether it is in the
- * valid range for an IRQ (30-1020 inclusive).
- */
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
- ldr \tmp, =1021
-
- bic \irqnr, \irqstat, #0x1c00
-
- cmp \irqnr, #29
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
-
- .endm
-
- /* We assume that irqstat (the raw value of the IRQ acknowledge
- * register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of interrupt on the
- * controller, since this requires the original irqstat value which
- * we won't easily be able to recreate later.
- */
-
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h
index 62b0a90309ad..d1b954955c12 100644
--- a/arch/arm/mach-davinci/include/mach/io.h
+++ b/arch/arm/mach-davinci/include/mach/io.h
@@ -22,8 +22,8 @@
#define __mem_isa(a) (a)
#ifndef __ASSEMBLER__
-#define __arch_ioremap(p, s, t) davinci_ioremap(p, s, t)
-#define __arch_iounmap(v) davinci_iounmap(v)
+#define __arch_ioremap davinci_ioremap
+#define __arch_iounmap davinci_iounmap
void __iomem *davinci_ioremap(unsigned long phys, size_t size,
unsigned int type);
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 6258c90d020c..1713ecf0c95f 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -41,7 +41,7 @@
#include <asm/mach/map.h>
#include <asm/mach/time.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
#include "common.h"
diff --git a/arch/arm/mach-iop13xx/include/mach/io.h b/arch/arm/mach-iop13xx/include/mach/io.h
index a6e0f9e6ddcf..dffb234bb967 100644
--- a/arch/arm/mach-iop13xx/include/mach/io.h
+++ b/arch/arm/mach-iop13xx/include/mach/io.h
@@ -35,7 +35,7 @@ extern u32 iop13xx_atux_mem_base;
extern size_t iop13xx_atue_mem_size;
extern size_t iop13xx_atux_mem_size;
-#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f)
-#define __arch_iounmap(a) __iop13xx_iounmap(a)
+#define __arch_ioremap __iop13xx_ioremap
+#define __arch_iounmap __iop13xx_iounmap
#endif
diff --git a/arch/arm/mach-iop32x/include/mach/io.h b/arch/arm/mach-iop32x/include/mach/io.h
index 339e5854728b..059c783ce0b2 100644
--- a/arch/arm/mach-iop32x/include/mach/io.h
+++ b/arch/arm/mach-iop32x/include/mach/io.h
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr);
#define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
#define __mem_pci(a) (a)
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a) __iop3xx_iounmap(a)
+#define __arch_ioremap __iop3xx_ioremap
+#define __arch_iounmap __iop3xx_iounmap
#endif
diff --git a/arch/arm/mach-iop33x/include/mach/io.h b/arch/arm/mach-iop33x/include/mach/io.h
index e99a7ed6d050..39e893e97c21 100644
--- a/arch/arm/mach-iop33x/include/mach/io.h
+++ b/arch/arm/mach-iop33x/include/mach/io.h
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr);
#define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
#define __mem_pci(a) (a)
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a) __iop3xx_iounmap(a)
+#define __arch_ioremap __iop3xx_ioremap
+#define __arch_iounmap __iop3xx_iounmap
#endif
diff --git a/arch/arm/mach-ixp23xx/include/mach/io.h b/arch/arm/mach-ixp23xx/include/mach/io.h
index fd9ef8e519f7..a1749d0fd896 100644
--- a/arch/arm/mach-ixp23xx/include/mach/io.h
+++ b/arch/arm/mach-ixp23xx/include/mach/io.h
@@ -45,8 +45,8 @@ ixp23xx_iounmap(void __iomem *addr)
__iounmap(addr);
}
-#define __arch_ioremap(a,s,f) ixp23xx_ioremap(a,s,f)
-#define __arch_iounmap(a) ixp23xx_iounmap(a)
+#define __arch_ioremap ixp23xx_ioremap
+#define __arch_iounmap ixp23xx_iounmap
#endif
diff --git a/arch/arm/mach-ixp4xx/include/mach/io.h b/arch/arm/mach-ixp4xx/include/mach/io.h
index de274a1f19d7..57b5410c31f4 100644
--- a/arch/arm/mach-ixp4xx/include/mach/io.h
+++ b/arch/arm/mach-ixp4xx/include/mach/io.h
@@ -74,8 +74,8 @@ static inline void __indirect_iounmap(void __iomem *addr)
__iounmap(addr);
}
-#define __arch_ioremap(a, s, f) __indirect_ioremap(a, s, f)
-#define __arch_iounmap(a) __indirect_iounmap(a)
+#define __arch_ioremap __indirect_ioremap
+#define __arch_iounmap __indirect_iounmap
#define writeb(v, p) __indirect_writeb(v, p)
#define writew(v, p) __indirect_writew(v, p)
diff --git a/arch/arm/mach-kirkwood/include/mach/io.h b/arch/arm/mach-kirkwood/include/mach/io.h
index 44e8be04f259..1aaddc364f2e 100644
--- a/arch/arm/mach-kirkwood/include/mach/io.h
+++ b/arch/arm/mach-kirkwood/include/mach/io.h
@@ -42,8 +42,8 @@ __arch_iounmap(void __iomem *addr)
__iounmap(addr);
}
-#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m)
-#define __arch_iounmap(a) __arch_iounmap(a)
+#define __arch_ioremap __arch_ioremap
+#define __arch_iounmap __arch_iounmap
#define __io(a) __io(a)
#define __mem_pci(a) (a)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 7486a681cc71..9b5eb2b4ae1b 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -28,8 +28,6 @@
#include <mach/board.h>
#include <mach/msm_iomap.h>
-void __iomem *gic_cpu_base_addr;
-
unsigned long clk_get_max_axi_khz(void)
{
return 0;
@@ -44,9 +42,8 @@ static void __init msm8x60_init_irq(void)
{
unsigned int i;
- gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
- gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
- gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+ gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+ (void *)MSM_QGIC_CPU_BASE);
/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index 06e64e1fc28a..d54c4f89a8bd 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -105,6 +105,35 @@ omap_irq_base: .word 0
9999:
.endm
+#ifdef CONFIG_SMP
+ /* We assume that irqstat (the raw value of the IRQ acknowledge
+ * register) is preserved from the macro above.
+ * If there is an IPI, we immediately signal end of interrupt
+ * on the controller, since this requires the original irqstat
+ * value which we won't easily be able to recreate later.
+ */
+
+ .macro test_for_ipi, irqnr, irqstat, base, tmp
+ bic \irqnr, \irqstat, #0x1c00
+ cmp \irqnr, #16
+ it cc
+ strcc \irqstat, [\base, #GIC_CPU_EOI]
+ it cs
+ cmpcs \irqnr, \irqnr
+ .endm
+
+ /* As above, this assumes that irqstat and base are preserved */
+
+ .macro test_for_ltirq, irqnr, irqstat, base, tmp
+ bic \irqnr, \irqstat, #0x1c00
+ mov \tmp, #0
+ cmp \irqnr, #29
+ itt eq
+ moveq \tmp, #1
+ streq \irqstat, [\base, #GIC_CPU_EOI]
+ cmp \tmp, #0
+ .endm
+#endif /* CONFIG_SMP */
#else /* MULTI_OMAP2 */
@@ -141,74 +170,16 @@ omap_irq_base: .word 0
#ifdef CONFIG_ARCH_OMAP4
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
.macro get_irqnr_preamble, base, tmp
ldr \base, =OMAP4_IRQ_BASE
.endm
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * For now, we ignore all local interrupts so only return an
- * interrupt if it's between 30 and 1020. The test_for_ipi
- * routine below will pick up on IPIs.
- * A simple read from the controller will tell us the number
- * of the highest priority enabled interrupt.
- * We then just need to check whether it is in the
- * valid range for an IRQ (30-1020 inclusive).
- */
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqstat, [\base, #GIC_CPU_INTACK]
-
- ldr \tmp, =1021
-
- bic \irqnr, \irqstat, #0x1c00
-
- cmp \irqnr, #29
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
- .endm
#endif
-#endif /* MULTI_OMAP2 */
-
-#ifdef CONFIG_SMP
- /* We assume that irqstat (the raw value of the IRQ acknowledge
- * register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of interrupt
- * on the controller, since this requires the original irqstat
- * value which we won't easily be able to recreate later.
- */
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- it cc
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- it cs
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base are preserved */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- itt eq
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
-#endif /* CONFIG_SMP */
+#endif /* MULTI_OMAP2 */
.macro irq_prio_table
.endm
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 2744dfee1ff4..5b0270b28934 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -24,7 +24,6 @@
extern void __iomem *l2cache_base;
#endif
-extern void __iomem *gic_cpu_base_addr;
extern void __iomem *gic_dist_base_addr;
extern void __init gic_init_irq(void);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 9e9f70e18e3c..9fbac2c39104 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -50,7 +50,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_secondary_init(0);
/*
* Synchronise with the boot thread.
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 2f895553e6a8..666e852988d5 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -26,21 +26,22 @@
void __iomem *l2cache_base;
#endif
-void __iomem *gic_cpu_base_addr;
void __iomem *gic_dist_base_addr;
void __init gic_init_irq(void)
{
+ void __iomem *gic_cpu_base;
+
/* Static mapping, never released */
gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
BUG_ON(!gic_dist_base_addr);
- gic_dist_init(0, gic_dist_base_addr, 29);
/* Static mapping, never released */
- gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
- BUG_ON(!gic_cpu_base_addr);
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
+ BUG_ON(!gic_cpu_base);
+
+ gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
}
#ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h
index c47b033bd999..c5196101a237 100644
--- a/arch/arm/mach-orion5x/include/mach/io.h
+++ b/arch/arm/mach-orion5x/include/mach/io.h
@@ -38,8 +38,8 @@ __arch_iounmap(void __iomem *addr)
__iounmap(addr);
}
-#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m)
-#define __arch_iounmap(a) __arch_iounmap(a)
+#define __arch_ioremap __arch_ioremap
+#define __arch_iounmap __arch_iounmap
#define __io(a) __typesafe_io(a)
#define __mem_pci(a) (a)
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 07c08151dfe6..14fbe50376b6 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -50,13 +50,10 @@
#include <mach/clkdev.h>
#include <mach/platform.h>
#include <mach/irqs.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
#include "core.h"
-/* used by entry-macro.S and platsmp.c */
-void __iomem *gic_cpu_base_addr;
-
#ifdef CONFIG_ZONE_DMA
/*
* Adjust the zones if there are restrictions for DMA access.
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 781bca68a9fa..693239ddc39e 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -53,7 +53,6 @@ extern struct platform_device realview_i2c_device;
extern struct mmci_platform_data realview_mmc0_plat_data;
extern struct mmci_platform_data realview_mmc1_plat_data;
extern struct clcd_board clcd_plat_data;
-extern void __iomem *gic_cpu_base_addr;
extern void __iomem *timer0_va_base;
extern void __iomem *timer1_va_base;
extern void __iomem *timer2_va_base;
diff --git a/arch/arm/mach-realview/include/mach/entry-macro.S b/arch/arm/mach-realview/include/mach/entry-macro.S
index 340a5c276946..4071164aebaa 100644
--- a/arch/arm/mach-realview/include/mach/entry-macro.S
+++ b/arch/arm/mach-realview/include/mach/entry-macro.S
@@ -8,74 +8,11 @@
* warranty of any kind, whether express or implied.
*/
#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =gic_cpu_base_addr
- ldr \base, [\base]
- .endm
-
.macro arch_ret_to_user, tmp1, tmp2
.endm
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * For now, we ignore all local interrupts so only return an interrupt if it's
- * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
- *
- * A simple read from the controller will tell us the number of the highest
- * priority enabled interrupt. We then just need to check whether it is in the
- * valid range for an IRQ (30-1020 inclusive).
- */
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
- ldr \tmp, =1021
-
- bic \irqnr, \irqstat, #0x1c00
-
- cmp \irqnr, #29
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
-
- .endm
-
- /* We assume that irqstat (the raw value of the IRQ acknowledge
- * register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of interrupt on the
- * controller, since this requires the original irqstat value which
- * we won't easily be able to recreate later.
- */
-
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 009265818d55..6da8a2e53c44 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -69,7 +69,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_secondary_init(0);
/*
* let the primary processor know we're out of the
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index f2697106f809..6ef5c5e528b2 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -364,21 +364,19 @@ static void __init gic_init_irq(void)
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
/* core tile GIC, primary */
- gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
- gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE),
+ __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
#ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
/* board GIC, secondary */
- gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
- gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
+ gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+ __io_address(REALVIEW_EB_GIC_CPU_BASE));
gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
#endif
} else {
/* board GIC, primary */
- gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
- gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+ __io_address(REALVIEW_EB_GIC_CPU_BASE));
}
}
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index a4125619d71b..cbdc97a5685f 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -304,13 +304,14 @@ static struct platform_device char_lcd_device = {
static void __init gic_init_irq(void)
{
/* ARM1176 DevChip GIC, primary */
- gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
- gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_init(0, IRQ_DC1176_GIC_START,
+ __io_address(REALVIEW_DC1176_GIC_DIST_BASE),
+ __io_address(REALVIEW_DC1176_GIC_CPU_BASE));
/* board GIC, secondary */
- gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
- gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
+ gic_init(1, IRQ_PB1176_GIC_START,
+ __io_address(REALVIEW_PB1176_GIC_DIST_BASE),
+ __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
}
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 117b95b2ca15..8e8ab7d29a6a 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -309,13 +309,13 @@ static void __init gic_init_irq(void)
writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
/* ARM11MPCore test chip GIC, primary */
- gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
- gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE),
+ __io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
/* board GIC, secondary */
- gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
- gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
+ gic_init(1, IRQ_PB11MP_GIC_START,
+ __io_address(REALVIEW_PB11MP_GIC_DIST_BASE),
+ __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
}
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 929b8dc12e81..841118e3e118 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -273,9 +273,9 @@ static struct platform_device pmu_device = {
static void __init gic_init_irq(void)
{
/* ARM PB-A8 on-board GIC */
- gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE);
- gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START);
- gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
+ gic_init(0, IRQ_PBA8_GIC_START,
+ __io_address(REALVIEW_PBA8_GIC_DIST_BASE),
+ __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
}
static void __init realview_pba8_timer_init(void)
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index b9f9e20031a7..02b755b009db 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -313,15 +313,12 @@ static void __init gic_init_irq(void)
{
/* ARM PBX on-board GIC */
if (core_tile_pbx11mp() || core_tile_pbxa9mp()) {
- gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE);
- gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
- 29);
- gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
+ gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+ __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
} else {
- gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE);
- gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE),
- IRQ_PBX_GIC_START);
- gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE));
+ gic_init(0, IRQ_PBX_GIC_START,
+ __io_address(REALVIEW_PBX_GIC_DIST_BASE),
+ __io_address(REALVIEW_PBX_GIC_CPU_BASE));
}
}
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index 82ce4aa6d61a..72ab289e7816 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -24,8 +24,6 @@
#include <mach/regs-irq.h>
-void __iomem *gic_cpu_base_addr;
-
extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
unsigned int irq_start);
extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -122,9 +120,7 @@ void __init s5pv310_init_irq(void)
{
int irq;
- gic_cpu_base_addr = S5P_VA_GIC_CPU;
- gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
- gic_cpu_init(0, S5P_VA_GIC_CPU);
+ gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
index b7ec252384f4..e1cc6a251c6a 100644
--- a/arch/arm/mach-s5pv310/include/mach/smp.h
+++ b/arch/arm/mach-s5pv310/include/mach/smp.h
@@ -9,8 +9,6 @@
#include <asm/hardware/gic.h>
#include <asm/smp_mpidr.h>
-extern void __iomem *gic_cpu_base_addr;
-
/*
* We use IRQ1 as the IPI
*/
diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
index d357c198edee..15929c169f81 100644
--- a/arch/arm/mach-s5pv310/platsmp.c
+++ b/arch/arm/mach-s5pv310/platsmp.c
@@ -54,7 +54,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_secondary_init(0);
/*
* let the primary processor know we're out of the
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index 5da8c35aa0de..42625e4d949a 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -118,6 +118,16 @@ config SA1100_LART
(also known as the LART). See <http://www.lartmaker.nl/> for
information on the LART.
+config SA1100_NANOENGINE
+ bool "nanoEngine"
+ select CPU_FREQ_SA1110
+ select PCI
+ select PCI_NANOENGINE
+ help
+ Say Y here if you are using the Bright Star Engineering nanoEngine.
+ See <http://www.brightstareng.com/arm/nanoeng.htm> for information
+ on the BSE nanoEngine.
+
config SA1100_PLEB
bool "PLEB"
select CPU_FREQ_SA1100
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 89349c1dd7a6..e697691eed28 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -37,6 +37,9 @@ obj-$(CONFIG_SA1100_JORNADA720_SSP) += jornada720_ssp.o
obj-$(CONFIG_SA1100_LART) += lart.o
led-$(CONFIG_SA1100_LART) += leds-lart.o
+obj-$(CONFIG_SA1100_NANOENGINE) += nanoengine.o
+obj-$(CONFIG_PCI_NANOENGINE) += pci-nanoengine.o
+
obj-$(CONFIG_SA1100_PLEB) += pleb.o
obj-$(CONFIG_SA1100_SHANNON) += shannon.o
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index 96f7dc103b59..07d4e8ba3719 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -94,48 +94,47 @@
#include "generic.h"
-typedef struct {
+struct sa1100_dram_regs {
int speed;
u32 mdcnfg;
u32 mdcas0;
u32 mdcas1;
u32 mdcas2;
-} sa1100_dram_regs_t;
+};
static struct cpufreq_driver sa1100_driver;
-static sa1100_dram_regs_t sa1100_dram_settings[] =
-{
- /* speed, mdcnfg, mdcas0, mdcas1, mdcas2 clock frequency */
- { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 59.0 MHz */
- { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 73.7 MHz */
- { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 88.5 MHz */
- { 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 103.2 MHz */
- { 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 118.0 MHz */
- { 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 132.7 MHz */
- { 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff }, /* 147.5 MHz */
- { 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff }, /* 162.2 MHz */
- { 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff }, /* 176.9 MHz */
- { 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff }, /* 191.7 MHz */
- { 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 206.4 MHz */
- { 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 221.2 MHz */
- { 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 }, /* 235.9 MHz */
- { 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 250.7 MHz */
- { 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 265.4 MHz */
- { 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 }, /* 280.2 MHz */
+static struct sa1100_dram_regs sa1100_dram_settings[] = {
+ /*speed, mdcnfg, mdcas0, mdcas1, mdcas2, clock freq */
+ { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 59.0 MHz */
+ { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 73.7 MHz */
+ { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 88.5 MHz */
+ {103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
+ {118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
+ {132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
+ {147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
+ {162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
+ {176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
+ {191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
+ {206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
+ {221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
+ {235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
+ {250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
+ {265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
+ {280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
{ 0, 0, 0, 0, 0 } /* last entry */
};
static void sa1100_update_dram_timings(int current_speed, int new_speed)
{
- sa1100_dram_regs_t *settings = sa1100_dram_settings;
+ struct sa1100_dram_regs *settings = sa1100_dram_settings;
/* find speed */
while (settings->speed != 0) {
- if(new_speed == settings->speed)
+ if (new_speed == settings->speed)
break;
-
+
settings++;
}
@@ -149,7 +148,7 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
/* We're going FASTER, so first relax the memory
* timings before changing the core frequency
*/
-
+
/* Half the memory access clock */
MDCNFG |= MDCNFG_CDB2;
@@ -187,7 +186,7 @@ static int sa1100_target(struct cpufreq_policy *policy,
struct cpufreq_freqs freqs;
new_ppcr = sa11x0_freq_to_ppcr(target_freq);
- switch(relation){
+ switch (relation) {
case CPUFREQ_RELATION_L:
if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
new_ppcr--;
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 7252874d328b..675bf8ef97e8 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -16,28 +16,24 @@
*
* 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>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
-#include <mach/hardware.h>
#include <asm/cputype.h>
#include <asm/mach-types.h>
-#include <asm/system.h>
+
+#include <mach/hardware.h>
#include "generic.h"
#undef DEBUG
-static struct cpufreq_driver sa1110_driver;
-
struct sdram_params {
- const char name[16];
+ const char name[20];
u_char rows; /* bits */
u_char cas_latency; /* cycles */
u_char tck; /* clock cycle time (ns) */
@@ -107,6 +103,15 @@ static struct sdram_params sdram_tbl[] __initdata = {
.twr = 8,
.refresh = 64000,
.cas_latency = 3,
+ }, { /* Micron MT48LC8M16A2TG-75 */
+ .name = "MT48LC8M16A2TG-75",
+ .rows = 12,
+ .tck = 8,
+ .trcd = 20,
+ .trp = 20,
+ .twr = 8,
+ .refresh = 64000,
+ .cas_latency = 3,
},
};
@@ -180,11 +185,13 @@ sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz,
sd->mdrefr |= MDREFR_K1DB2;
/* initial number of '1's in MDCAS + 1 */
- set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
+ set_mdcas(sd->mdcas, sd_khz >= 62000,
+ ns_to_cycles(sdram->trcd, mem_khz));
#ifdef DEBUG
- printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
- sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
+ printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
+ sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
+ sd->mdcas[2]);
#endif
}
@@ -213,7 +220,7 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
#ifdef DEBUG
mdelay(250);
- printk("new dri value = %d\n", dri);
+ printk(KERN_DEBUG "new dri value = %d\n", dri);
#endif
sdram_set_refresh(dri);
@@ -232,7 +239,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
unsigned long flags;
unsigned int ppcr, unused;
- switch(relation){
+ switch (relation) {
case CPUFREQ_RELATION_L:
ppcr = sa11x0_freq_to_ppcr(target_freq);
if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
@@ -280,11 +287,10 @@ static int sa1110_target(struct cpufreq_policy *policy,
* We wait 20ms to be safe.
*/
sdram_set_refresh(2);
- if (!irqs_disabled()) {
+ if (!irqs_disabled())
msleep(20);
- } else {
+ else
mdelay(20);
- }
/*
* Reprogram the DRAM timings with interrupts disabled, and
@@ -295,7 +301,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
local_irq_save(flags);
asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
udelay(10);
- __asm__ __volatile__(" \n\
+ __asm__ __volatile__("\n\
b 2f \n\
.align 5 \n\
1: str %3, [%1, #0] @ MDCNFG \n\
@@ -336,7 +342,9 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
return 0;
}
-static struct cpufreq_driver sa1110_driver = {
+/* sa1110_driver needs __refdata because it must remain after init registers
+ * it with cpufreq_register_driver() */
+static struct cpufreq_driver sa1110_driver __refdata = {
.flags = CPUFREQ_STICKY,
.verify = sa11x0_verify_speed,
.target = sa1110_target,
@@ -349,7 +357,8 @@ 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++)
+ for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
+ sdram++)
if (strcmp(name, sdram->name) == 0)
return sdram;
@@ -369,14 +378,14 @@ static int __init sa1110_clk_init(void)
if (!name[0]) {
if (machine_is_assabet())
name = "TC59SM716-CL3";
-
if (machine_is_pt_system3())
name = "K4S641632D";
-
if (machine_is_h3100())
name = "KM416S4030CT";
if (machine_is_jornada720())
- name = "K4S281632B-1H";
+ name = "K4S281632B-1H";
+ if (machine_is_nanoengine())
+ name = "MT48LC8M16A2TG-75";
}
sdram = sa1110_find_sdram(name);
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 3c1fcd696714..3555d616774c 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -163,10 +163,15 @@ static void sa11x0_register_device(struct platform_device *dev, void *data)
static struct resource sa11x0udc_resources[] = {
[0] = {
- .start = 0x80000000,
- .end = 0x8000ffff,
+ .start = __PREG(Ser0UDCCR),
+ .end = __PREG(Ser0UDCCR) + 0xffff,
.flags = IORESOURCE_MEM,
},
+ [1] = {
+ .start = IRQ_Ser0UDC,
+ .end = IRQ_Ser0UDC,
+ .flags = IORESOURCE_IRQ,
+ },
};
static u64 sa11x0udc_dma_mask = 0xffffffffUL;
@@ -184,10 +189,15 @@ static struct platform_device sa11x0udc_device = {
static struct resource sa11x0uart1_resources[] = {
[0] = {
- .start = 0x80010000,
- .end = 0x8001ffff,
+ .start = __PREG(Ser1UTCR0),
+ .end = __PREG(Ser1UTCR0) + 0xffff,
.flags = IORESOURCE_MEM,
},
+ [1] = {
+ .start = IRQ_Ser1UART,
+ .end = IRQ_Ser1UART,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct platform_device sa11x0uart1_device = {
@@ -199,10 +209,15 @@ static struct platform_device sa11x0uart1_device = {
static struct resource sa11x0uart3_resources[] = {
[0] = {
- .start = 0x80050000,
- .end = 0x8005ffff,
+ .start = __PREG(Ser3UTCR0),
+ .end = __PREG(Ser3UTCR0) + 0xffff,
.flags = IORESOURCE_MEM,
},
+ [1] = {
+ .start = IRQ_Ser3UART,
+ .end = IRQ_Ser3UART,
+ .flags = IORESOURCE_IRQ,
+ },
};
static struct platform_device sa11x0uart3_device = {
@@ -214,10 +229,15 @@ static struct platform_device sa11x0uart3_device = {
static struct resource sa11x0mcp_resources[] = {
[0] = {
- .start = 0x80060000,
- .end = 0x8006ffff,
+ .start = __PREG(Ser4MCCR0),
+ .end = __PREG(Ser4MCCR0) + 0xffff,
.flags = IORESOURCE_MEM,
},
+ [1] = {
+ .start = IRQ_Ser4MCP,
+ .end = IRQ_Ser4MCP,
+ .flags = IORESOURCE_IRQ,
+ },
};
static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
@@ -244,6 +264,11 @@ static struct resource sa11x0ssp_resources[] = {
.end = 0x8007ffff,
.flags = IORESOURCE_MEM,
},
+ [1] = {
+ .start = IRQ_Ser4SSP,
+ .end = IRQ_Ser4SSP,
+ .flags = IORESOURCE_IRQ,
+ },
};
static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
diff --git a/arch/arm/mach-sa1100/include/mach/hardware.h b/arch/arm/mach-sa1100/include/mach/hardware.h
index 99f5856d8de4..967ae7684390 100644
--- a/arch/arm/mach-sa1100/include/mach/hardware.h
+++ b/arch/arm/mach-sa1100/include/mach/hardware.h
@@ -76,4 +76,12 @@ static inline unsigned long get_clock_tick_rate(void)
#include "SA-1101.h"
#endif
+#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
+#define PCIBIOS_MIN_IO 0
+#define PCIBIOS_MIN_MEM 0
+#define pcibios_assign_all_busses() 1
+#define HAVE_ARCH_PCI_SET_DMA_MASK 1
+#endif
+
+
#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-sa1100/include/mach/nanoengine.h b/arch/arm/mach-sa1100/include/mach/nanoengine.h
new file mode 100644
index 000000000000..14f8382d0665
--- /dev/null
+++ b/arch/arm/mach-sa1100/include/mach/nanoengine.h
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-sa1100/include/mach/nanoengine.h
+ *
+ * This file contains the hardware specific definitions for nanoEngine.
+ * Only include this file from SA1100-specific files.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * 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.
+ *
+ */
+#ifndef __ASM_ARCH_NANOENGINE_H
+#define __ASM_ARCH_NANOENGINE_H
+
+#include <mach/irqs.h>
+
+#define GPIO_PC_READY0 GPIO_GPIO(11) /* ready for socket 0 (active high)*/
+#define GPIO_PC_READY1 GPIO_GPIO(12) /* ready for socket 1 (active high) */
+#define GPIO_PC_CD0 GPIO_GPIO(13) /* detect for socket 0 (active low) */
+#define GPIO_PC_CD1 GPIO_GPIO(14) /* detect for socket 1 (active low) */
+#define GPIO_PC_RESET0 GPIO_GPIO(15) /* reset socket 0 */
+#define GPIO_PC_RESET1 GPIO_GPIO(16) /* reset socket 1 */
+
+#define NANOENGINE_IRQ_GPIO_PCI IRQ_GPIO0
+#define NANOENGINE_IRQ_GPIO_PC_READY0 IRQ_GPIO11
+#define NANOENGINE_IRQ_GPIO_PC_READY1 IRQ_GPIO12
+#define NANOENGINE_IRQ_GPIO_PC_CD0 IRQ_GPIO13
+#define NANOENGINE_IRQ_GPIO_PC_CD1 IRQ_GPIO14
+
+/*
+ * nanoEngine Memory Map:
+ *
+ * 0000.0000 - 003F.0000 - 4 MB Flash
+ * C000.0000 - C1FF.FFFF - 32 MB SDRAM
+ * 1860.0000 - 186F.FFFF - 1 MB Internal PCI Memory Read/Write
+ * 18A1.0000 - 18A1.FFFF - 64 KB Internal PCI Config Space
+ * 4000.0000 - 47FF.FFFF - 128 MB External Bus I/O - Multiplexed Mode
+ * 4800.0000 - 4FFF.FFFF - 128 MB External Bus I/O - Non-Multiplexed Mode
+ *
+ */
+
+#define NANO_PCI_MEM_RW_PHYS 0x18600000
+#define NANO_PCI_MEM_RW_VIRT 0xf1000000
+#define NANO_PCI_MEM_RW_SIZE SZ_1M
+#define NANO_PCI_CONFIG_SPACE_PHYS 0x18A10000
+#define NANO_PCI_CONFIG_SPACE_VIRT 0xf2000000
+#define NANO_PCI_CONFIG_SPACE_SIZE SZ_64K
+
+#endif
+
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
new file mode 100644
index 000000000000..72087f0658b7
--- /dev/null
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -0,0 +1,119 @@
+/*
+ * linux/arch/arm/mach-sa1100/nanoengine.c
+ *
+ * Bright Star Engineering's nanoEngine board init code.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * 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/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/root_dev.h>
+
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "generic.h"
+
+/* Flash bank 0 */
+static struct mtd_partition nanoengine_partitions[] = {
+ {
+ .name = "nanoEngine boot firmware and parameter table",
+ .size = 0x00010000, /* 32K */
+ .offset = 0,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel/initrd reserved",
+ .size = 0x002f0000,
+ .offset = 0x00010000,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "experimental filesystem allocation",
+ .size = 0x00100000,
+ .offset = 0x00300000,
+ .mask_flags = MTD_WRITEABLE,
+ }
+};
+
+static struct flash_platform_data nanoengine_flash_data = {
+ .map_name = "jedec_probe",
+ .parts = nanoengine_partitions,
+ .nr_parts = ARRAY_SIZE(nanoengine_partitions),
+};
+
+static struct resource nanoengine_flash_resources[] = {
+ {
+ .start = SA1100_CS0_PHYS,
+ .end = SA1100_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = SA1100_CS1_PHYS,
+ .end = SA1100_CS1_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct map_desc nanoengine_io_desc[] __initdata = {
+ {
+ /* System Registers */
+ .virtual = 0xf0000000,
+ .pfn = __phys_to_pfn(0x10000000),
+ .length = 0x00100000,
+ .type = MT_DEVICE
+ }, {
+ /* Internal PCI Memory Read/Write */
+ .virtual = NANO_PCI_MEM_RW_VIRT,
+ .pfn = __phys_to_pfn(NANO_PCI_MEM_RW_PHYS),
+ .length = NANO_PCI_MEM_RW_SIZE,
+ .type = MT_DEVICE
+ }, {
+ /* Internal PCI Config Space */
+ .virtual = NANO_PCI_CONFIG_SPACE_VIRT,
+ .pfn = __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS),
+ .length = NANO_PCI_CONFIG_SPACE_SIZE,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init nanoengine_map_io(void)
+{
+ sa1100_map_io();
+ iotable_init(nanoengine_io_desc, ARRAY_SIZE(nanoengine_io_desc));
+
+ sa1100_register_uart(0, 1);
+ sa1100_register_uart(1, 2);
+ sa1100_register_uart(2, 3);
+ Ser1SDCR0 |= SDCR0_UART;
+ /* disable IRDA -- UART2 is used as a normal serial port */
+ Ser2UTCR4 = 0;
+ Ser2HSCR0 = 0;
+}
+
+static void __init nanoengine_init(void)
+{
+ sa11x0_register_mtd(&nanoengine_flash_data, nanoengine_flash_resources,
+ ARRAY_SIZE(nanoengine_flash_resources));
+}
+
+MACHINE_START(NANOENGINE, "BSE nanoEngine")
+ .boot_params = 0xc0000000,
+ .map_io = nanoengine_map_io,
+ .init_irq = sa1100_init_irq,
+ .timer = &sa1100_timer,
+ .init_machine = nanoengine_init,
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c
new file mode 100644
index 000000000000..fba7a913f12b
--- /dev/null
+++ b/arch/arm/mach-sa1100/pci-nanoengine.c
@@ -0,0 +1,284 @@
+/*
+ * linux/arch/arm/mach-sa1100/pci-nanoengine.c
+ *
+ * PCI functions for BSE nanoEngine PCI
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#include <mach/nanoengine.h>
+
+static DEFINE_SPINLOCK(nano_lock);
+
+static int nanoengine_get_pci_address(struct pci_bus *bus,
+ unsigned int devfn, int where, unsigned long *address)
+{
+ int ret = PCIBIOS_DEVICE_NOT_FOUND;
+ unsigned int busnr = bus->number;
+
+ *address = NANO_PCI_CONFIG_SPACE_VIRT +
+ ((bus->number << 16) | (devfn << 8) | (where & ~3));
+
+ ret = (busnr > 255 || devfn > 255 || where > 255) ?
+ PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+ return ret;
+}
+
+static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 *val)
+{
+ int ret;
+ unsigned long address;
+ unsigned long flags;
+ u32 v;
+
+ /* nanoEngine PCI bridge does not return -1 for a non-existing
+ * device. We must fake the answer. We know that the only valid
+ * device is device zero at bus 0, which is the network chip. */
+ if (bus->number != 0 || (devfn >> 3) != 0) {
+ v = -1;
+ nanoengine_get_pci_address(bus, devfn, where, &address);
+ goto exit_function;
+ }
+
+ spin_lock_irqsave(&nano_lock, flags);
+
+ ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+ v = __raw_readl(address);
+
+ spin_unlock_irqrestore(&nano_lock, flags);
+
+ v >>= ((where & 3) * 8);
+ v &= (unsigned long)(-1) >> ((4 - size) * 8);
+
+exit_function:
+ *val = v;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ int ret;
+ unsigned long address;
+ unsigned long flags;
+ unsigned shift;
+ u32 v;
+
+ shift = (where & 3) * 8;
+
+ spin_lock_irqsave(&nano_lock, flags);
+
+ ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+ v = __raw_readl(address);
+ switch (size) {
+ case 1:
+ v &= ~(0xFF << shift);
+ v |= val << shift;
+ break;
+ case 2:
+ v &= ~(0xFFFF << shift);
+ v |= val << shift;
+ break;
+ case 4:
+ v = val;
+ break;
+ }
+ __raw_writel(v, address);
+
+ spin_unlock_irqrestore(&nano_lock, flags);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_nano_ops = {
+ .read = nanoengine_read_config,
+ .write = nanoengine_write_config,
+};
+
+static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return NANOENGINE_IRQ_GPIO_PCI;
+}
+
+struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ return pci_scan_bus(sys->busnr, &pci_nano_ops, sys);
+}
+
+static struct resource pci_io_ports = {
+ .name = "PCI IO",
+ .start = 0x400,
+ .end = 0x7FF,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource pci_non_prefetchable_memory = {
+ .name = "PCI non-prefetchable",
+ .start = NANO_PCI_MEM_RW_PHYS,
+ /* nanoEngine documentation says there is a 1 Megabyte window here,
+ * but PCI reports just 128 + 8 kbytes. */
+ .end = NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1,
+/* .end = NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/
+ .flags = IORESOURCE_MEM,
+};
+
+/*
+ * nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it
+ * overlaps with previously defined memory.
+ *
+ * Here is what happens:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io 0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000)
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io 0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io 0x0400-0x043f] (PCI address [0x0-0x3f])
+ *
+ * On the other hand, if we do not request the prefetchable memory resource,
+ * linux will alloc it first and the two non-prefetchable memory areas that
+ * are our real interest will not be mapped. So we choose to map it to an
+ * unused area. It gets recognized as expansion ROM, but becomes disabled.
+ *
+ * Here is what happens then:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io 0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref]
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io 0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io 0x0400-0x043f] (PCI address [0x0-0x3f])
+
+# lspci -vv -s 0000:00:00.0
+00:00.0 Class 0200: Device 8086:1209 (rev 09)
+ Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
+ Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx-
+ Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes
+ Interrupt: pin A routed to IRQ 0
+ Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K]
+ Region 1: I/O ports at 0400 [size=64]
+ Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K]
+ [virtual] Expansion ROM at 78000000 [disabled] [size=1M]
+ Capabilities: [dc] Power Management version 2
+ Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
+ Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
+ Kernel driver in use: e100
+ Kernel modules: e100
+ *
+ */
+static struct resource pci_prefetchable_memory = {
+ .name = "PCI prefetchable",
+ .start = 0x78000000,
+ .end = 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1,
+ .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_nanoengine_setup_resources(struct resource **resource)
+{
+ if (request_resource(&ioport_resource, &pci_io_ports)) {
+ printk(KERN_ERR "PCI: unable to allocate io port region\n");
+ return -EBUSY;
+ }
+ if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) {
+ release_resource(&pci_io_ports);
+ printk(KERN_ERR "PCI: unable to allocate non prefetchable\n");
+ return -EBUSY;
+ }
+ if (request_resource(&iomem_resource, &pci_prefetchable_memory)) {
+ release_resource(&pci_io_ports);
+ release_resource(&pci_non_prefetchable_memory);
+ printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
+ return -EBUSY;
+ }
+ resource[0] = &pci_io_ports;
+ resource[1] = &pci_non_prefetchable_memory;
+ resource[2] = &pci_prefetchable_memory;
+
+ return 1;
+}
+
+int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
+{
+ int ret = 0;
+
+ if (nr == 0) {
+ sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
+ sys->io_offset = 0x400;
+ ret = pci_nanoengine_setup_resources(sys->resource);
+ /* Enable alternate memory bus master mode, see
+ * "Intel StrongARM SA1110 Developer's Manual",
+ * section 10.8, "Alternate Memory Bus Master Mode". */
+ GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+ GAFR |= GPIO_MBGNT | GPIO_MBREQ;
+ TUCR |= TUCR_MBGPIO;
+ }
+
+ return ret;
+}
+
+static struct hw_pci nanoengine_pci __initdata = {
+ .map_irq = pci_nanoengine_map_irq,
+ .nr_controllers = 1,
+ .scan = pci_nanoengine_scan_bus,
+ .setup = pci_nanoengine_setup,
+};
+
+static int __init nanoengine_pci_init(void)
+{
+ if (machine_is_nanoengine())
+ pci_common_init(&nanoengine_pci);
+ return 0;
+}
+
+subsys_initcall(nanoengine_pci_init);
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 27692d0ffbe8..cfb76077bd25 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -166,9 +166,6 @@ static void __init simpad_map_io(void)
PCFR = 0;
PSDR = 0;
- sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
- ARRAY_SIZE(simpad_flash_resources));
- sa11x0_register_mcp(&simpad_mcp_data);
}
static void simpad_power_off(void)
@@ -216,6 +213,10 @@ static int __init simpad_init(void)
pm_power_off = simpad_power_off;
+ sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
+ ARRAY_SIZE(simpad_flash_resources));
+ sa11x0_register_mcp(&simpad_mcp_data);
+
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
if(ret)
printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index d440e5f456ad..ac429ff2c20d 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -61,6 +61,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
+#include <asm/setup.h>
/*
* Address Interface BusWidth note
diff --git a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
new file mode 100644
index 000000000000..e3ebfa73956e
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
@@ -0,0 +1,87 @@
+LIST "partner-jet-setup.txt"
+LIST "(C) Copyright 2010 Renesas Solutions Corp"
+LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
+
+LIST "RWT Setting"
+EW 0xE6020004, 0xA500
+EW 0xE6030004, 0xA500
+
+DD 0x01001000, 0x01001000
+
+LIST "GPIO Setting"
+EB 0xE6051013, 0xA2
+
+LIST "CPG"
+ED 0xE6150080, 0x00000180
+ED 0xE61500C0, 0x00000002
+
+WAIT 1, 0xFE40009C
+
+LIST "FRQCR"
+ED 0xE6150000, 0x2D1305C3
+ED 0xE61500E0, 0x9E40358E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE61500E4, 0x00002000
+
+WAIT 1, 0xFE40009C
+
+LIST "PLL"
+ED 0xE6150028, 0x00004000
+
+WAIT 1, 0xFE40009C
+
+ED 0xE615002C, 0x93000040
+
+WAIT 1, 0xFE40009C
+
+LIST "BSC"
+ED 0xFEC10000, 0x00E0001B
+
+LIST "SBSC1"
+ED 0xFE400354, 0x01AD8000
+ED 0xFE400354, 0x01AD8001
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400008, 0xBCC90151
+ED 0xFE400040, 0x41774113
+ED 0xFE400044, 0x2712E229
+ED 0xFE400048, 0x20C18505
+ED 0xFE40004C, 0x00110209
+ED 0xFE400010, 0x00000087
+
+WAIT 10, 0xFE40009C
+
+ED 0xFE400084, 0x0000003F
+EB 0xFE500000, 0x00
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400084, 0x0000FF0A
+EB 0xFE500000, 0x00
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400084, 0x00002201
+EB 0xFE500000, 0x00
+ED 0xFE400084, 0x00000302
+EB 0xFE500000, 0x00
+EB 0xFE5C0000, 0x00
+ED 0xFE400008, 0xBCC90159
+ED 0xFE40008C, 0x88800004
+ED 0xFE400094, 0x00000004
+ED 0xFE400028, 0xA55A0032
+ED 0xFE40002C, 0xA55A000C
+ED 0xFE400020, 0xA55A2048
+ED 0xFE400008, 0xBCC90959
+
+LIST "Change CPGA setting"
+ED 0xE61500E0, 0x9E40352E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE6150354, 0x00000002
diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h
new file mode 100644
index 000000000000..3ad86b7708e9
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot.h
@@ -0,0 +1,20 @@
+#ifndef ZBOOT_H
+#define ZBOOT_H
+
+#include <asm/mach-types.h>
+#include <mach/zboot_macros.h>
+
+/**************************************************
+ *
+ * board specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_MACH_AP4EVB
+#define MACH_TYPE MACH_TYPE_AP4EVB
+#include "mach/head-ap4evb.txt"
+#else
+#error "unsupported board."
+#endif
+
+#endif /* ZBOOT_H */
diff --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
new file mode 100644
index 000000000000..aa6111fbc989
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
@@ -0,0 +1,65 @@
+#ifndef __ZBOOT_MACRO_H
+#define __ZBOOT_MACRO_H
+
+/* The LIST command is used to include comments in the script */
+.macro LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro ED, addr, data
+ LDR r0, 1f
+ LDR r1, 2f
+ STR r1, [r0]
+ B 3f
+1 : .long \addr
+2 : .long \data
+3 :
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro EW, addr, data
+ LDR r0, 1f
+ LDR r1, 2f
+ STRH r1, [r0]
+ B 3f
+1 : .long \addr
+2 : .long \data
+3 :
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro EB, addr, data
+ LDR r0, 1f
+ LDR r1, 2f
+ STRB r1, [r0]
+ B 3f
+1 : .long \addr
+2 : .long \data
+3 :
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro WAIT, time, reg
+ LDR r1, 1f
+ LDR r0, 2f
+ STR r0, [r1]
+10 :
+ LDR r0, [r1]
+ CMP r0, #0x00000000
+ BNE 10b
+ NOP
+ B 3f
+1 : .long \reg
+2 : .long \time * 100
+3 :
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro DD, start, end
+ LDR r1, 1f
+ B 2f
+1 : .long \start
+2 :
+.endm
+
+#endif /* __ZBOOT_MACRO_H */
diff --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S
index 2ba9e5c9d2f6..dd165c53889d 100644
--- a/arch/arm/mach-tegra/include/mach/entry-macro.S
+++ b/arch/arm/mach-tegra/include/mach/entry-macro.S
@@ -16,8 +16,8 @@
#include <mach/io.h>
#if defined(CONFIG_ARM_GIC)
-
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
/* Uses the GIC interrupt controller built into the cpu */
#define ICTRL_BASE (IO_CPU_VIRT + 0x100)
@@ -32,68 +32,6 @@
.macro arch_ret_to_user, tmp1, tmp2
.endm
-
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * For now, we ignore all local interrupts so only return an interrupt
- * if it's between 30 and 1020. The test_for_ipi routine below will
- * pick up on IPIs.
- *
- * A simple read from the controller will tell us the number of the
- * highest priority enabled interrupt. We then just need to check
- * whether it is in the valid range for an IRQ (30-1020 inclusive).
- */
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- /* bits 12-10 = src CPU, 9-0 = int # */
- ldr \irqstat, [\base, #GIC_CPU_INTACK]
-
- ldr \tmp, =1021
-
- bic \irqnr, \irqstat, #0x1c00
-
- cmp \irqnr, #29
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
-
- .endm
-
- /* We assume that irqstat (the raw value of the IRQ acknowledge
- * register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of interrupt on the
- * controller, since this requires the original irqstat value which
- * we won't easily be able to recreate later.
- */
-
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
-
#else
/* legacy interrupt controller for AP16 */
.macro disable_fiq
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
index f0981b1ac59e..4cea2230c8dc 100644
--- a/arch/arm/mach-tegra/include/mach/io.h
+++ b/arch/arm/mach-tegra/include/mach/io.h
@@ -65,8 +65,8 @@
#ifndef __ASSEMBLER__
-#define __arch_ioremap(p, s, t) tegra_ioremap(p, s, t)
-#define __arch_iounmap(v) tegra_iounmap(v)
+#define __arch_ioremap tegra_ioremap
+#define __arch_iounmap tegra_iounmap
void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
void tegra_iounmap(volatile void __iomem *addr);
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 50a8dfb9a0cf..5407de01abf0 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -94,8 +94,8 @@ void __init tegra_init_irq(void)
writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
}
- gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
- gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+ gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
+ IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
gic = get_irq_chip(29);
gic_unmask_irq = gic->unmask;
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1c0fd92cab39..3b7376c4f356 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -48,7 +48,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100);
+ gic_secondary_init(0);
/*
* Synchronise with the boot thread.
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 608a1372b172..7328c0179769 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -61,8 +61,8 @@ void __init ux500_init_devices(void)
void __init ux500_init_irq(void)
{
- gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
- gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+ gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE),
+ __io_address(UX500_GIC_CPU_BASE));
/*
* Init clocks here so that they are available for system timer
diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S
index 60ea88db8283..a37f585a3ecb 100644
--- a/arch/arm/mach-ux500/include/mach/entry-macro.S
+++ b/arch/arm/mach-ux500/include/mach/entry-macro.S
@@ -11,7 +11,8 @@
* warranty of any kind, whether express or implied.
*/
#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
@@ -22,68 +23,3 @@
.macro arch_ret_to_user, tmp1, tmp2
.endm
-
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * For now, we ignore all local interrupts so only return an
- * interrupt if it's between 30 and 1020. The test_for_ipi
- * routine below will pick up on IPIs.
- *
- * A simple read from the controller will tell us the number
- * of the highest priority enabled interrupt. We then just
- * need to check whether it is in the valid range for an
- * IRQ (30-1020 inclusive).
- */
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- /* bits 12-10 = src CPU, 9-0 = int # */
- ldr \irqstat, [\base, #GIC_CPU_INTACK]
-
- ldr \tmp, =1021
-
- bic \irqnr, \irqstat, #0x1c00
-
- cmp \irqnr, #29
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
-
- .endm
-
- /* We assume that irqstat (the raw value of the IRQ
- * acknowledge register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of
- * interrupt on the controller, since this requires the
- * original irqstat value which we won't easily be able
- * to recreate later.
- */
-
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base
- * are preserved..
- */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 9e4c678de785..b5077b4c419f 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -44,7 +44,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+ gic_secondary_init(0);
/*
* let the primary processor know we're out of the
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index e38acb0f89c8..6b93bd600271 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -49,7 +49,7 @@
#include <mach/clkdev.h>
#include <mach/hardware.h>
#include <mach/platform.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
#include "core.h"
diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
index 57dd95ce41f9..362780d868de 100644
--- a/arch/arm/mach-vexpress/core.h
+++ b/arch/arm/mach-vexpress/core.h
@@ -22,5 +22,3 @@ struct map_desc;
void v2m_map_io(struct map_desc *tile, size_t num);
extern struct sys_timer v2m_timer;
-
-extern void __iomem *gic_cpu_base_addr;
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index fd25ccd7272f..cb5793ef3ee0 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -21,7 +21,7 @@
#include <mach/clkdev.h>
#include <mach/ct-ca9x4.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -60,13 +60,10 @@ static void __init ct_ca9x4_map_io(void)
v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
}
-void __iomem *gic_cpu_base_addr;
-
static void __init ct_ca9x4_init_irq(void)
{
- gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU);
- gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29);
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
+ MMIO_P2V(A9_MPCORE_GIC_CPU));
}
#if 0
diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S
index 20e9fb514f0a..73c11297509e 100644
--- a/arch/arm/mach-vexpress/include/mach/entry-macro.S
+++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S
@@ -1,67 +1,7 @@
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
.macro disable_fiq
.endm
- .macro get_irqnr_preamble, base, tmp
- ldr \base, =gic_cpu_base_addr
- ldr \base, [\base]
- .endm
-
.macro arch_ret_to_user, tmp1, tmp2
.endm
-
- /*
- * The interrupt numbering scheme is defined in the
- * interrupt controller spec. To wit:
- *
- * Interrupts 0-15 are IPI
- * 16-28 are reserved
- * 29-31 are local. We allow 30 to be used for the watchdog.
- * 32-1020 are global
- * 1021-1022 are reserved
- * 1023 is "spurious" (no interrupt)
- *
- * For now, we ignore all local interrupts so only return an interrupt if it's
- * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
- *
- * A simple read from the controller will tell us the number of the highest
- * priority enabled interrupt. We then just need to check whether it is in the
- * valid range for an IRQ (30-1020 inclusive).
- */
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
- ldr \tmp, =1021
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #29
- cmpcc \irqnr, \irqnr
- cmpne \irqnr, \tmp
- cmpcs \irqnr, \irqnr
- .endm
-
- /* We assume that irqstat (the raw value of the IRQ acknowledge
- * register) is preserved from the macro above.
- * If there is an IPI, we immediately signal end of interrupt on the
- * controller, since this requires the original irqstat value which
- * we won't easily be able to recreate later.
- */
-
- .macro test_for_ipi, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- cmp \irqnr, #16
- strcc \irqstat, [\base, #GIC_CPU_EOI]
- cmpcs \irqnr, \irqnr
- .endm
-
- /* As above, this assumes that irqstat and base are preserved.. */
-
- .macro test_for_ltirq, irqnr, irqstat, base, tmp
- bic \irqnr, \irqstat, #0x1c00
- mov \tmp, #0
- cmp \irqnr, #29
- moveq \tmp, #1
- streq \irqstat, [\base, #GIC_CPU_EOI]
- cmp \tmp, #0
- .endm
-
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 670970699ba9..dfb591031d17 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -51,7 +51,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, gic_cpu_base_addr);
+ gic_secondary_init(0);
/*
* let the primary processor know we're out of the
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 7eaa232180a5..91ff2e0df856 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -22,7 +22,7 @@
#include <mach/clkdev.h>
#include <mach/motherboard.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
#include "core.h"
diff --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h
index 128b549c2796..204865f91d93 100644
--- a/arch/arm/plat-omap/include/plat/io.h
+++ b/arch/arm/plat-omap/include/plat/io.h
@@ -294,8 +294,8 @@ static inline void omap44xx_map_common_io(void)
extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
struct omap_sdrc_params *sdrc_cs1);
-#define __arch_ioremap(p,s,t) omap_ioremap(p,s,t)
-#define __arch_iounmap(v) omap_iounmap(v)
+#define __arch_ioremap omap_ioremap
+#define __arch_iounmap omap_iounmap
void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
void omap_iounmap(volatile void __iomem *addr);
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 5cf88e8427b1..aaa571d17924 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -1,5 +1,4 @@
obj-y := clock.o
-obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o
obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o
ifeq ($(CONFIG_LEDS_CLASS),y)
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 8d9386a22eb3..a565300a19c8 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -50,8 +50,9 @@ sa1111_cs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
sa1100_cs-y += sa1100_generic.o
sa1100_cs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
sa1100_cs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
-sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE) += pxa2xx_sharpsl.o
sa1100_cs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
+sa1100_cs-$(CONFIG_SA1100_NANOENGINE) += sa1100_nanoengine.o
sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 6b228590b3fd..fb9740d3e9a7 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -53,6 +53,9 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
#if defined(CONFIG_SA1100_H3100) || defined(CONFIG_SA1100_H3600)
pcmcia_h3600_init,
#endif
+#ifdef CONFIG_SA1100_NANOENGINE
+ pcmcia_nanoengine_init,
+#endif
#ifdef CONFIG_SA1100_SHANNON
pcmcia_shannon_init,
#endif
diff --git a/drivers/pcmcia/sa1100_generic.h b/drivers/pcmcia/sa1100_generic.h
index 794f96a35bba..adb08dbc723f 100644
--- a/drivers/pcmcia/sa1100_generic.h
+++ b/drivers/pcmcia/sa1100_generic.h
@@ -13,6 +13,7 @@ extern int pcmcia_freebird_init(struct device *);
extern int pcmcia_gcplus_init(struct device *);
extern int pcmcia_graphicsmaster_init(struct device *);
extern int pcmcia_h3600_init(struct device *);
+extern int pcmcia_nanoengine_init(struct device *);
extern int pcmcia_pangolin_init(struct device *);
extern int pcmcia_pfs168_init(struct device *);
extern int pcmcia_shannon_init(struct device *);
diff --git a/drivers/pcmcia/sa1100_nanoengine.c b/drivers/pcmcia/sa1100_nanoengine.c
new file mode 100644
index 000000000000..3d2652e2f5ae
--- /dev/null
+++ b/drivers/pcmcia/sa1100_nanoengine.c
@@ -0,0 +1,219 @@
+/*
+ * drivers/pcmcia/sa1100_nanoengine.c
+ *
+ * PCMCIA implementation routines for BSI nanoEngine.
+ *
+ * In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
+ * board you should carefully read this:
+ * http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * Based on original work for kernel 2.4 by
+ * Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
+ *
+ * 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/device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "sa1100_generic.h"
+
+static struct pcmcia_irqs irqs_skt0[] = {
+ /* socket, IRQ, name */
+ { 0, NANOENGINE_IRQ_GPIO_PC_CD0, "PC CD0" },
+};
+
+static struct pcmcia_irqs irqs_skt1[] = {
+ /* socket, IRQ, name */
+ { 1, NANOENGINE_IRQ_GPIO_PC_CD1, "PC CD1" },
+};
+
+struct nanoengine_pins {
+ unsigned input_pins;
+ unsigned output_pins;
+ unsigned clear_outputs;
+ unsigned transition_pins;
+ unsigned pci_irq;
+ struct pcmcia_irqs *pcmcia_irqs;
+ unsigned pcmcia_irqs_size;
+};
+
+static struct nanoengine_pins nano_skts[] = {
+ {
+ .input_pins = GPIO_PC_READY0 | GPIO_PC_CD0,
+ .output_pins = GPIO_PC_RESET0,
+ .clear_outputs = GPIO_PC_RESET0,
+ .transition_pins = NANOENGINE_IRQ_GPIO_PC_CD0,
+ .pci_irq = NANOENGINE_IRQ_GPIO_PC_READY0,
+ .pcmcia_irqs = irqs_skt0,
+ .pcmcia_irqs_size = ARRAY_SIZE(irqs_skt0)
+ }, {
+ .input_pins = GPIO_PC_READY1 | GPIO_PC_CD1,
+ .output_pins = GPIO_PC_RESET1,
+ .clear_outputs = GPIO_PC_RESET1,
+ .transition_pins = NANOENGINE_IRQ_GPIO_PC_CD1,
+ .pci_irq = NANOENGINE_IRQ_GPIO_PC_READY1,
+ .pcmcia_irqs = irqs_skt1,
+ .pcmcia_irqs_size = ARRAY_SIZE(irqs_skt1)
+ }
+};
+
+unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts);
+
+static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+ unsigned i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return -ENXIO;
+
+ GPDR &= ~nano_skts[i].input_pins;
+ GPDR |= nano_skts[i].output_pins;
+ GPCR = nano_skts[i].clear_outputs;
+ set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
+ skt->socket.pci_irq = nano_skts[i].pci_irq;
+
+ return soc_pcmcia_request_irqs(skt,
+ nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Release all resources.
+ */
+static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+ unsigned i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return;
+
+ soc_pcmcia_free_irqs(skt,
+ nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static int nanoengine_pcmcia_configure_socket(
+ struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+ unsigned reset;
+ unsigned i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return -ENXIO;
+
+ switch (i) {
+ case 0:
+ reset = GPIO_PC_RESET0;
+ break;
+ case 1:
+ reset = GPIO_PC_RESET1;
+ break;
+ default:
+ return -ENXIO;
+ }
+
+ if (state->flags & SS_RESET)
+ GPSR = reset;
+ else
+ GPCR = reset;
+
+ return 0;
+}
+
+static void nanoengine_pcmcia_socket_state(
+ struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
+{
+ unsigned long levels = GPLR;
+ unsigned i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return;
+
+ memset(state, 0, sizeof(struct pcmcia_state));
+ switch (i) {
+ case 0:
+ state->ready = (levels & GPIO_PC_READY0) ? 1 : 0;
+ state->detect = !(levels & GPIO_PC_CD0) ? 1 : 0;
+ break;
+ case 1:
+ state->ready = (levels & GPIO_PC_READY1) ? 1 : 0;
+ state->detect = !(levels & GPIO_PC_CD1) ? 1 : 0;
+ break;
+ default:
+ return;
+ }
+ state->bvd1 = 1;
+ state->bvd2 = 1;
+ state->wrprot = 0; /* Not available */
+ state->vs_3v = 1; /* Can only apply 3.3V */
+ state->vs_Xv = 0;
+}
+
+/*
+ * Enable card status IRQs on (re-)initialisation. This can
+ * be called at initialisation, power management event, or
+ * pcmcia event.
+ */
+static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+ unsigned i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return;
+
+ soc_pcmcia_enable_irqs(skt,
+ nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Disable card status IRQs on suspend.
+ */
+static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+ unsigned i = skt->nr;
+
+ if (i >= num_nano_pcmcia_sockets)
+ return;
+
+ soc_pcmcia_disable_irqs(skt,
+ nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static struct pcmcia_low_level nanoengine_pcmcia_ops = {
+ .owner = THIS_MODULE,
+
+ .hw_init = nanoengine_pcmcia_hw_init,
+ .hw_shutdown = nanoengine_pcmcia_hw_shutdown,
+
+ .configure_socket = nanoengine_pcmcia_configure_socket,
+ .socket_state = nanoengine_pcmcia_socket_state,
+ .socket_init = nanoengine_pcmcia_socket_init,
+ .socket_suspend = nanoengine_pcmcia_socket_suspend,
+};
+
+int pcmcia_nanoengine_init(struct device *dev)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_nanoengine())
+ ret = sa11xx_drv_pcmcia_probe(
+ dev, &nanoengine_pcmcia_ops, 0, 2);
+
+ return ret;
+}
+
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 2fe8cb8e95cd..5a9a392eacdf 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -31,20 +31,20 @@
======================================================================*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
+#include <linux/cpufreq.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/spinlock.h>
-#include <linux/cpufreq.h>
+#include <linux/timer.h>
#include <mach/hardware.h>
-#include <asm/io.h>
#include <asm/system.h>
#include "soc_common.h"
@@ -74,7 +74,8 @@ EXPORT_SYMBOL(soc_pcmcia_debug);
#endif
-#define to_soc_pcmcia_socket(x) container_of(x, struct soc_pcmcia_socket, socket)
+#define to_soc_pcmcia_socket(x) \
+ container_of(x, struct soc_pcmcia_socket, socket)
static unsigned short
calc_speed(unsigned short *spds, int num, unsigned short dflt)
@@ -91,11 +92,15 @@ calc_speed(unsigned short *spds, int num, unsigned short dflt)
return speed;
}
-void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing)
+void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
+ struct soc_pcmcia_timing *timing)
{
- timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
- timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
- timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+ timing->io =
+ calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
+ timing->mem =
+ calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+ timing->attr =
+ calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
}
EXPORT_SYMBOL(soc_common_pcmcia_get_timing);
@@ -137,8 +142,8 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
*
* Convert PCMCIA socket state to our socket configure structure.
*/
-static int
-soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
+static int soc_common_pcmcia_config_skt(
+ struct soc_pcmcia_socket *skt, socket_state_t *state)
{
int ret;
@@ -150,7 +155,8 @@ soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *stat
*/
if (skt->irq_state != 1 && state->io_irq) {
skt->irq_state = 1;
- set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);
+ set_irq_type(skt->socket.pci_irq,
+ IRQ_TYPE_EDGE_FALLING);
} else if (skt->irq_state == 1 && state->io_irq == 0) {
skt->irq_state = 0;
set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
@@ -304,24 +310,24 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
* of power configuration, reset, &c. We also record the value of
* `state' in order to regurgitate it to the PCMCIA core later.
*/
-static int
-soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int soc_common_pcmcia_set_socket(
+ struct pcmcia_socket *sock, socket_state_t *state)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
- debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
- (state->csc_mask==0)?"<NONE> ":"",
- (state->csc_mask&SS_DETECT)?"DETECT ":"",
- (state->csc_mask&SS_READY)?"READY ":"",
- (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
- (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
- (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
- (state->flags==0)?"<NONE> ":"",
- (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
- (state->flags&SS_IOCARD)?"IOCARD ":"",
- (state->flags&SS_RESET)?"RESET ":"",
- (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
- (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+ debug(skt, 2, "mask: %s%s%s%s%s%s flags: %s%s%s%s%s%s Vcc %d Vpp %d irq %d\n",
+ (state->csc_mask == 0) ? "<NONE> " : "",
+ (state->csc_mask & SS_DETECT) ? "DETECT " : "",
+ (state->csc_mask & SS_READY) ? "READY " : "",
+ (state->csc_mask & SS_BATDEAD) ? "BATDEAD " : "",
+ (state->csc_mask & SS_BATWARN) ? "BATWARN " : "",
+ (state->csc_mask & SS_STSCHG) ? "STSCHG " : "",
+ (state->flags == 0) ? "<NONE> " : "",
+ (state->flags & SS_PWR_AUTO) ? "PWR_AUTO " : "",
+ (state->flags & SS_IOCARD) ? "IOCARD " : "",
+ (state->flags & SS_RESET) ? "RESET " : "",
+ (state->flags & SS_SPKR_ENA) ? "SPKR_ENA " : "",
+ (state->flags & SS_OUTPUT_ENA) ? "OUTPUT_ENA " : "",
state->Vcc, state->Vpp, state->io_irq);
return soc_common_pcmcia_config_skt(skt, state);
@@ -336,8 +342,8 @@ soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
*
* Returns: 0 on success, -1 on error
*/
-static int
-soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
+static int soc_common_pcmcia_set_io_map(
+ struct pcmcia_socket *sock, struct pccard_io_map *map)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
unsigned short speed = map->speed;
@@ -346,14 +352,14 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
map->map, map->speed, (unsigned long long)map->start,
(unsigned long long)map->stop);
debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
- (map->flags==0)?"<NONE>":"",
- (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
- (map->flags&MAP_16BIT)?"16BIT ":"",
- (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
- (map->flags&MAP_0WS)?"0WS ":"",
- (map->flags&MAP_WRPROT)?"WRPROT ":"",
- (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
- (map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+ (map->flags == 0) ? "<NONE>" : "",
+ (map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
+ (map->flags & MAP_16BIT) ? "16BIT " : "",
+ (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
+ (map->flags & MAP_0WS) ? "0WS " : "",
+ (map->flags & MAP_WRPROT) ? "WRPROT " : "",
+ (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "",
+ (map->flags & MAP_PREFETCH) ? "PREFETCH " : "");
if (map->map >= MAX_IO_WIN) {
printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
@@ -390,8 +396,8 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
*
* Returns: 0 on success, -ERRNO on error
*/
-static int
-soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
+static int soc_common_pcmcia_set_mem_map(
+ struct pcmcia_socket *sock, struct pccard_mem_map *map)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
struct resource *res;
@@ -400,14 +406,14 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
debug(skt, 2, "map %u speed %u card_start %08x\n",
map->map, map->speed, map->card_start);
debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
- (map->flags==0)?"<NONE>":"",
- (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
- (map->flags&MAP_16BIT)?"16BIT ":"",
- (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
- (map->flags&MAP_0WS)?"0WS ":"",
- (map->flags&MAP_WRPROT)?"WRPROT ":"",
- (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
- (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+ (map->flags == 0) ? "<NONE>" : "",
+ (map->flags & MAP_ACTIVE) ? "ACTIVE " : "",
+ (map->flags & MAP_16BIT) ? "16BIT " : "",
+ (map->flags & MAP_AUTOSZ) ? "AUTOSZ " : "",
+ (map->flags & MAP_0WS) ? "0WS " : "",
+ (map->flags & MAP_WRPROT) ? "WRPROT " : "",
+ (map->flags & MAP_ATTRIB) ? "ATTRIB " : "",
+ (map->flags & MAP_USE_WAIT) ? "USE_WAIT " : "");
if (map->map >= MAX_WIN)
return -EINVAL;
@@ -462,8 +468,8 @@ static struct bittbl conf_bits[] = {
{ SS_OUTPUT_ENA, "SS_OUTPUT_ENA" },
};
-static void
-dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
+static void dump_bits(char **p, const char *prefix,
+ unsigned int val, struct bittbl *bits, int sz)
{
char *b = *p;
int i;
@@ -481,13 +487,14 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
*
* Returns: the number of characters added to the buffer
*/
-static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_status(
+ struct device *dev, struct device_attribute *attr, char *buf)
{
struct soc_pcmcia_socket *skt =
container_of(dev, struct soc_pcmcia_socket, socket.dev);
char *p = buf;
- p+=sprintf(p, "slot : %d\n", skt->nr);
+ p += sprintf(p, "slot : %d\n", skt->nr);
dump_bits(&p, "status", skt->status,
status_bits, ARRAY_SIZE(status_bits));
@@ -496,12 +503,12 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr, ch
dump_bits(&p, "cs_flags", skt->cs_state.flags,
conf_bits, ARRAY_SIZE(conf_bits));
- p+=sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc);
- p+=sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp);
- p+=sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq,
+ p += sprintf(p, "Vcc : %d\n", skt->cs_state.Vcc);
+ p += sprintf(p, "Vpp : %d\n", skt->cs_state.Vpp);
+ p += sprintf(p, "IRQ : %d (%d)\n", skt->cs_state.io_irq,
skt->socket.pci_irq);
if (skt->ops->show_timing)
- p+=skt->ops->show_timing(skt, p);
+ p += skt->ops->show_timing(skt, p);
return p-buf;
}
@@ -594,7 +601,7 @@ soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
mutex_lock(&soc_pcmcia_sockets_lock);
list_for_each_entry(skt, &soc_pcmcia_sockets, node)
- if ( skt->ops->frequency_change )
+ if (skt->ops->frequency_change)
ret += skt->ops->frequency_change(skt, val, freqs);
mutex_unlock(&soc_pcmcia_sockets_lock);
@@ -620,7 +627,8 @@ fs_initcall(soc_pcmcia_cpufreq_register);
static void soc_pcmcia_cpufreq_unregister(void)
{
- cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+ cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
}
module_exit(soc_pcmcia_cpufreq_unregister);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index e4a44b641702..88ea52b8647a 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -39,10 +39,10 @@
#include <mach/regs-ost.h>
#endif
-#define RTC_DEF_DIVIDER 32768 - 1
+#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
-static unsigned long rtc_freq = 1024;
+static const unsigned long RTC_FREQ = 1024;
static unsigned long timer_freq;
static struct rtc_time rtc_alarm;
static DEFINE_SPINLOCK(sa1100_rtc_lock);
@@ -61,7 +61,8 @@ static inline int rtc_periodic_alarm(struct rtc_time *tm)
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
*/
-static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm)
+static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
+ struct rtc_time *alrm)
{
unsigned long next_time;
unsigned long now_time;
@@ -116,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
rtsr = RTSR;
/* clear interrupt sources */
RTSR = 0;
- RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+ /* Fix for a nasty initialization problem the in SA11xx RTSR register.
+ * See also the comments in sa1100_rtc_probe(). */
+ if (rtsr & (RTSR_ALE | RTSR_HZE)) {
+ /* This is the original code, before there was the if test
+ * above. This code does not clear interrupts that were not
+ * enabled. */
+ RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+ } else {
+ /* For some reason, it is possible to enter this routine
+ * without interruptions enabled, it has been tested with
+ * several units (Bug in SA11xx chip?).
+ *
+ * This situation leads to an infinite "loop" of interrupt
+ * routine calling and as a result the processor seems to
+ * lock on its first call to open(). */
+ RTSR = RTSR_AL | RTSR_HZ;
+ }
/* clear alarm interrupt if it has occurred */
if (rtsr & RTSR_AL)
@@ -139,8 +156,58 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static int sa1100_irq_set_freq(struct device *dev, int freq)
+{
+ if (freq < 1 || freq > timer_freq) {
+ return -EINVAL;
+ } else {
+ struct rtc_device *rtc = (struct rtc_device *)dev;
+
+ rtc->irq_freq = freq;
+
+ return 0;
+ }
+}
+
static int rtc_timer1_count;
+static int sa1100_irq_set_state(struct device *dev, int enabled)
+{
+ spin_lock_irq(&sa1100_rtc_lock);
+ if (enabled) {
+ struct rtc_device *rtc = (struct rtc_device *)dev;
+
+ OSMR1 = timer_freq / rtc->irq_freq + OSCR;
+ OIER |= OIER_E1;
+ rtc_timer1_count = 1;
+ } else {
+ OIER &= ~OIER_E1;
+ }
+ spin_unlock_irq(&sa1100_rtc_lock);
+
+ return 0;
+}
+
+static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
+{
+ unsigned long diff;
+ unsigned long period = timer_freq / rtc->irq_freq;
+
+ spin_lock_irq(&sa1100_rtc_lock);
+
+ do {
+ OSMR1 += period;
+ diff = OSMR1 - OSCR;
+ /* If OSCR > OSMR1, diff is a very large number (unsigned
+ * math). This means we have a lost interrupt. */
+ } while (diff > period);
+ OIER |= OIER_E1;
+
+ spin_unlock_irq(&sa1100_rtc_lock);
+
+ return 0;
+}
+
static irqreturn_t timer1_interrupt(int irq, void *dev_id)
{
struct platform_device *pdev = to_platform_device(dev_id);
@@ -158,7 +225,11 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
if (rtc_timer1_count == 1)
- rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
+ rtc_timer1_count =
+ (rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
+
+ /* retrigger. */
+ sa1100_timer1_retrigger(rtc);
return IRQ_HANDLED;
}
@@ -166,8 +237,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
static int sa1100_rtc_read_callback(struct device *dev, int data)
{
if (data & RTC_PF) {
+ struct rtc_device *rtc = (struct rtc_device *)dev;
+
/* interpolate missed periods and set match for the next */
- unsigned long period = timer_freq / rtc_freq;
+ unsigned long period = timer_freq / rtc->irq_freq;
unsigned long oscr = OSCR;
unsigned long osmr1 = OSMR1;
unsigned long missed = (oscr - osmr1)/period;
@@ -178,7 +251,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
* Here we compare (match - OSCR) 8 instead of 0 --
* see comment in pxa_timer_interrupt() for explanation.
*/
- while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
+ while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
data += 0x100;
OSSR = OSSR_M1; /* clear match on timer 1 */
OSMR1 = osmr1 + period;
@@ -190,25 +263,29 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
static int sa1100_rtc_open(struct device *dev)
{
int ret;
+ struct rtc_device *rtc = (struct rtc_device *)dev;
ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
- "rtc 1Hz", dev);
+ "rtc 1Hz", dev);
if (ret) {
dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
goto fail_ui;
}
ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
- "rtc Alrm", dev);
+ "rtc Alrm", dev);
if (ret) {
dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
goto fail_ai;
}
ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
- "rtc timer", dev);
+ "rtc timer", dev);
if (ret) {
dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
goto fail_pi;
}
+ rtc->max_user_freq = RTC_FREQ;
+ sa1100_irq_set_freq(dev, RTC_FREQ);
+
return 0;
fail_pi:
@@ -236,7 +313,7 @@ static void sa1100_rtc_release(struct device *dev)
static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
unsigned long arg)
{
- switch(cmd) {
+ switch (cmd) {
case RTC_AIE_OFF:
spin_lock_irq(&sa1100_rtc_lock);
RTSR &= ~RTSR_ALE;
@@ -257,25 +334,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
RTSR |= RTSR_HZE;
spin_unlock_irq(&sa1100_rtc_lock);
return 0;
- case RTC_PIE_OFF:
- spin_lock_irq(&sa1100_rtc_lock);
- OIER &= ~OIER_E1;
- spin_unlock_irq(&sa1100_rtc_lock);
- return 0;
- case RTC_PIE_ON:
- spin_lock_irq(&sa1100_rtc_lock);
- OSMR1 = timer_freq / rtc_freq + OSCR;
- OIER |= OIER_E1;
- rtc_timer1_count = 1;
- spin_unlock_irq(&sa1100_rtc_lock);
- return 0;
- case RTC_IRQP_READ:
- return put_user(rtc_freq, (unsigned long *)arg);
- case RTC_IRQP_SET:
- if (arg < 1 || arg > timer_freq)
- return -EINVAL;
- rtc_freq = arg;
- return 0;
}
return -ENOIOCTLCMD;
}
@@ -327,12 +385,15 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
+ struct rtc_device *rtc = (struct rtc_device *)dev;
+
seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
seq_printf(seq, "update_IRQ\t: %s\n",
(RTSR & RTSR_HZE) ? "yes" : "no");
seq_printf(seq, "periodic_IRQ\t: %s\n",
(OIER & OIER_E1) ? "yes" : "no");
- seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
+ seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
+ seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
return 0;
}
@@ -347,6 +408,8 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
.read_alarm = sa1100_rtc_read_alarm,
.set_alarm = sa1100_rtc_set_alarm,
.proc = sa1100_rtc_proc,
+ .irq_set_freq = sa1100_irq_set_freq,
+ .irq_set_state = sa1100_irq_set_state,
};
static int sa1100_rtc_probe(struct platform_device *pdev)
@@ -364,7 +427,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
*/
if (RTTR == 0) {
RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
- dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
+ dev_warn(&pdev->dev, "warning: "
+ "initializing default clock divider/trim value\n");
/* The current RTC value probably doesn't make sense either */
RCNR = 0;
}
@@ -372,13 +436,42 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
- THIS_MODULE);
+ THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
platform_set_drvdata(pdev, rtc);
+ /* Set the irq_freq */
+ /*TODO: Find out who is messing with this value after we initialize
+ * it here.*/
+ rtc->irq_freq = RTC_FREQ;
+
+ /* Fix for a nasty initialization problem the in SA11xx RTSR register.
+ * See also the comments in sa1100_rtc_interrupt().
+ *
+ * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
+ * interrupt pending, even though interrupts were never enabled.
+ * In this case, this bit it must be reset before enabling
+ * interruptions to avoid a nonexistent interrupt to occur.
+ *
+ * In principle, the same problem would apply to bit 0, although it has
+ * never been observed to happen.
+ *
+ * This issue is addressed both here and in sa1100_rtc_interrupt().
+ * If the issue is not addressed here, in the times when the processor
+ * wakes up with the bit set there will be one spurious interrupt.
+ *
+ * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
+ * safe side, once the condition that lead to this strange
+ * initialization is unknown and could in principle happen during
+ * normal processing.
+ *
+ * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
+ * the corresponding bits in RTSR. */
+ RTSR = RTSR_AL | RTSR_HZ;
+
return 0;
}
@@ -386,7 +479,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
{
struct rtc_device *rtc = platform_get_drvdata(pdev);
- if (rtc)
+ if (rtc)
rtc_device_unregister(rtc);
return 0;
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 2367fb3f70bc..74802bc5ded9 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -499,7 +499,7 @@ static int __init parse_crash_elf64_headers(void)
/* Do some basic Verification. */
if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
(ehdr.e_type != ET_CORE) ||
- !vmcore_elf_check_arch(&ehdr) ||
+ !vmcore_elf64_check_arch(&ehdr) ||
ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
ehdr.e_version != EV_CURRENT ||
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
index 0026f267da20..088cd4ace4ef 100644
--- a/include/linux/crash_dump.h
+++ b/include/linux/crash_dump.h
@@ -20,7 +20,14 @@ extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
#define vmcore_elf_check_arch_cross(x) 0
#endif
-#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+/*
+ * Architecture code can redefine this if there are any special checks
+ * needed for 64-bit ELF vmcores. In case of 32-bit only architecture,
+ * this can be set to zero.
+ */
+#ifndef vmcore_elf64_check_arch
+#define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+#endif
/*
* is_kdump_kernel() checks whether this kernel is booting after a panic of
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index f2f32eee2c5b..038b3d1e2981 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -38,6 +38,7 @@ static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
static char gpfx; /* prefix for global symbol name (sometimes '_') */
static struct stat sb; /* Remember .st_size, etc. */
static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
+static const char *altmcount; /* alternate mcount symbol name */
/* setjmp() return values */
enum {
@@ -299,7 +300,9 @@ do_file(char const *const fname)
fail_file();
} break;
case EM_386: reltype = R_386_32; break;
- case EM_ARM: reltype = R_ARM_ABS32; break;
+ case EM_ARM: reltype = R_ARM_ABS32;
+ altmcount = "__gnu_mcount_nc";
+ break;
case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break;
case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
@@ -357,7 +360,7 @@ do_file(char const *const fname)
int
main(int argc, char const *argv[])
{
- const char ftrace[] = "kernel/trace/ftrace.o";
+ const char ftrace[] = "/ftrace.o";
int ftrace_size = sizeof(ftrace) - 1;
int n_error = 0; /* gcc-4.3.0 false positive complaint */
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 39667174971d..baf187bee983 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -275,11 +275,12 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
Elf_Sym const *const symp =
&sym0[Elf_r_sym(relp)];
char const *symname = &str0[w(symp->st_name)];
+ char const *mcount = '_' == gpfx ? "_mcount" : "mcount";
if ('.' == symname[0])
++symname; /* ppc64 hack */
- if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
- symname))
+ if (0 == strcmp(mcount, symname) ||
+ (altmcount && 0 == strcmp(altmcount, symname)))
mcountsym = Elf_r_sym(relp);
}