From 8a9618f5dfca35edb0d7ab6374ff586e2e9e989b Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 6 Oct 2010 16:18:08 +0100 Subject: [PATCH 01/40] ARM: 6432/1: move timer-sp.c from versatile to common From: Rob Herring The timer-sp h/w used on versatile platforms can also be used for other platforms, so move it to a common location. Signed-off-by: Rob Herring Signed-off-by: Russell King --- arch/arm/common/Makefile | 1 + arch/arm/{plat-versatile => common}/timer-sp.c | 4 +--- .../include/plat => include/asm/hardware}/timer-sp.h | 0 arch/arm/mach-integrator/integrator_cp.c | 2 +- arch/arm/mach-realview/core.c | 2 +- arch/arm/mach-versatile/core.c | 2 +- arch/arm/mach-vexpress/ct-ca9x4.c | 2 +- arch/arm/mach-vexpress/v2m.c | 2 +- arch/arm/plat-versatile/Makefile | 1 - 9 files changed, 7 insertions(+), 9 deletions(-) rename arch/arm/{plat-versatile => common}/timer-sp.c (98%) rename arch/arm/{plat-versatile/include/plat => include/asm/hardware}/timer-sp.h (100%) 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/plat-versatile/timer-sp.c b/arch/arm/common/timer-sp.c similarity index 98% rename from arch/arm/plat-versatile/timer-sp.c rename to 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 -#include - /* * These timers are currently always setup to be clocked at 1MHz. */ diff --git a/arch/arm/plat-versatile/include/plat/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h similarity index 100% rename from arch/arm/plat-versatile/include/plat/timer-sp.h rename to arch/arm/include/asm/hardware/timer-sp.h 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 #include -#include +#include #include "common.h" diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 07c08151dfe6..aa54b577fc1e 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include "core.h" 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 #include #include -#include +#include #include "core.h" diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index c2e405a9e025..101e79fd5ab6 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include 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 #include -#include +#include #include "core.h" 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) From d03f322c41890a86bf64d00314f0ec72738a7f21 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:31:26 +0100 Subject: [PATCH 02/40] ARM: 6450/1: Fix checkpatch.pl issues in arch/arm/mach-sa1100/cpu-sa1100.c. This patch fixes checkpatch.pl issues in arch/arm/mach-sa1100/cpu-sa1100.c. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- arch/arm/mach-sa1100/cpu-sa1100.c | 51 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 26 deletions(-) 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--; From a404ad1ff593589bdd34c48ebecddada9edbfaf3 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:33:53 +0100 Subject: [PATCH 03/40] ARM: 6452/1: Fix checkpatch.pl issues in drivers/rtc/rtc-sa1100.c. This patch fixes checkpatch.pl issues in drivers/rtc/rtc-sa1100.c, which I will later modify. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- drivers/rtc/rtc-sa1100.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index e4a44b641702..e19ed0f6dca0 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -39,7 +39,7 @@ #include #endif -#define RTC_DEF_DIVIDER 32768 - 1 +#define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_TRIM 0 static unsigned long rtc_freq = 1024; @@ -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; @@ -178,7 +179,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; @@ -192,19 +193,19 @@ static int sa1100_rtc_open(struct device *dev) int ret; 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; @@ -236,7 +237,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; @@ -364,7 +365,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; } @@ -386,7 +388,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; From fd3ee6d3421bc05ce42ee7f48071aee72051af28 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:34:47 +0100 Subject: [PATCH 04/40] ARM: 6453/1: sa1100: Print the value of RTSR on /proc/drivers/rtc. This patch adds a line to the output of /proc/drivers/rtc to show the value of the RTSR register. It will be used to demonstrate a nasty initialization bug that will be fixed in the sequence. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- drivers/rtc/rtc-sa1100.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index e19ed0f6dca0..b04c8374a279 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -334,6 +334,7 @@ static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) 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, "RTSR\t\t: 0x%08x\n", (u32)RTSR); return 0; } From 7decaa557a20f48aabef35f817ec16ef563567b0 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:35:54 +0100 Subject: [PATCH 05/40] ARM: 6454/1: sa1100: Fix for a nasty initialization bug in the RTSR. This patch fixes a nasty initialization condition on the RTSR register. Sometimes, bit 1 will wake up set, sometimes not. This can be seen by checking the value of the RTSR by typing '$ cat /proc/driver/rtc', which has been provided by the previous patch. If this bit is set, the command '$ cat /dev/rtc0' will lock the system in an endless interrupt routine calling loop. This patch fixes the issue both at sa1100_rtc_probe(), where it avoids a spurious interrupt from happening, and at sa1100_rtc_interrupt(), which is the robust solution, though it does not avoid the first spurious interrupt. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- drivers/rtc/rtc-sa1100.c | 42 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index b04c8374a279..b0985f727078 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -117,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) @@ -382,6 +398,30 @@ static int sa1100_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); + /* 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; } From 9833c39400c3e6ee19daeded6910df648741611e Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 19 Nov 2010 09:29:24 +0100 Subject: [PATCH 06/40] ARM: 6485/5: proc/vmcore - allow archs to override vmcore_elf_check_arch() Allow architectures to redefine this macro if needed. This is useful for example in architectures where 64-bit ELF vmcores are not supported. Specifying zero vmcore_elf64_check_arch() allows compiler to optimize away unnecessary parts of parse_crash_elf64_headers(). We also rename the macro to vmcore_elf64_check_arch() to reflect that it is used for 64-bit vmcores only. Signed-off-by: Mika Westerberg Signed-off-by: Russell King --- fs/proc/vmcore.c | 2 +- include/linux/crash_dump.h | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) 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 From 4b3bf7aef94fc337610d78fce0d960e2ee1d5a8f Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 18 Nov 2010 19:13:19 +0100 Subject: [PATCH 07/40] ARM: 6486/1: provide zero vmcore_elf64_check_arch() Since we don't support 64-bit ELF vmcores. This also prevents the following warning: fs/proc/vmcore.c: In function 'parse_crash_elf64_headers': fs/proc/vmcore.c:502: warning: passing argument 1 of 'elf_check_arch' from incompatible pointer type Signed-off-by: Mika Westerberg Signed-off-by: Russell King --- arch/arm/include/asm/elf.h | 2 ++ 1 file changed, 2 insertions(+) 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) From cb5d39b3a1440eca79c742d95f1d78180c272286 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 18 Nov 2010 19:14:52 +0100 Subject: [PATCH 08/40] ARM: 6487/1: add CONFIG_CRASH_DUMP to Kconfig Add CONFIG_CRASH_DUMP configuration option which is used by dump capture kernels. Signed-off-by: Mika Westerberg Signed-off-by: Russell King --- arch/arm/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db524e75c4a2..03582fd14b87 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1650,6 +1650,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 From 8931360eb9c6ec8bd30efef579cef81917a2fcf3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 12 Nov 2010 13:02:46 +0000 Subject: [PATCH 09/40] ARM: module: clean up handling of ELF unwind tables There's no need to keep pointers to the ELF sections available while the module is loaded - we only need the section pointers while we're finding and registering the unwind tables, which can all be done during the finalize stage of loading. Signed-off-by: Russell King --- arch/arm/include/asm/module.h | 17 ++---- arch/arm/kernel/module.c | 106 ++++++++++++++++------------------ 2 files changed, 57 insertions(+), 66 deletions(-) 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,14 +16,14 @@ enum { ARM_SEC_DEVEXIT, ARM_SEC_MAX, }; -struct mod_arch_specific { - struct arm_unwind_mapping map[ARM_SEC_MAX]; -}; -#else -struct mod_arch_specific { -}; #endif +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/module.c b/arch/arm/kernel/module.c index d9bd786ce23d..f9937c4b7d1a 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,66 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, return -ENOEXEC; } +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 -static void register_unwind_tables(struct module *mod) -{ + 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 (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 } From 50005a8deb38e5e6456ebd94e57adb321d4589de Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 12 Nov 2010 13:04:16 +0000 Subject: [PATCH 10/40] ARM: module: ignore unwind for sections not marked SHF_ALLOC If a section is not marked with SHF_ALLOC, it will be discarded by the module code. Therefore, it is not correct to register the unwind tables. Signed-off-by: Russell King --- arch/arm/kernel/module.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index f9937c4b7d1a..0c1bb68ff4a8 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -290,6 +290,9 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, 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) From 0946b8c5c5982088a26da7ad99e8bcf57f972fb5 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Wed, 1 Dec 2010 18:05:13 +0100 Subject: [PATCH 11/40] ARM: 6517/1: kexec: Add missing memory clobber to inline asm in crash_setup_regs() Currently, the inline asm is passed &newregs->ARM_r0 as in input, when modifying multiple fields of newregs. It's plausible to assume that GCC will assume newregs->ARM_r0 is modified when passed the address, but unfortunately this assumption is incorrect. Also, GCC has no way to guess that the other ARM_r* fields are modified without the addition of a "memory" clobber. Signed-off-by: Dave Martin Acked-by: Catalin Marinas Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/kexec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h index 8ec9ef5c3c7b..b37e02c91693 100644 --- a/arch/arm/include/asm/kexec.h +++ b/arch/arm/include/asm/kexec.h @@ -34,7 +34,7 @@ static inline void crash_setup_regs(struct pt_regs *newregs, memcpy(newregs, oldregs, sizeof(*newregs)); } else { __asm__ __volatile__ ("stmia %0, {r0 - r15}" - : : "r" (&newregs->ARM_r0)); + : : "r" (&newregs->ARM_r0) : "memory"); __asm__ __volatile__ ("mrs %0, cpsr" : "=r" (newregs->ARM_cpsr)); } From cd849ae9cd291117c0f7e0e8d531ab62a906e308 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Wed, 1 Dec 2010 18:05:14 +0100 Subject: [PATCH 12/40] ARM: 6518/1: kexec: Fix crash_setup_regs() for ARMv7 and CONFIG_THUMB2_KERNEL * Fix kexec build failure with CONFIG_THUMB2_KERNEL. * Avoids deprecated/forbidden sp and pc usage in for ARMv7 onwards, retaining compatibility with older architecture versions. * The pc value saved to newregs is now aligned on a predictable instruction boundary. (stmia { ... pc } or str pc has implementation-defined results in most versions of the ARM architecutre, and is prohibited (unpredictable) in Thumb-2.) * Switch to named inline asm arguments (else I get readily confused ...) The resulting code should be compatible with all architecture versions >= v3, with or without CONFIG_THUMB2_KERNEL. Reviewed-by: Will Deacon Tested-by: Mika Westerberg Signed-off-by: Dave Martin Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/kexec.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h index b37e02c91693..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) : "memory"); - __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" + ); } } From b23065313297e750edd57ab6edfd36224826724e Mon Sep 17 00:00:00 2001 From: Per Fransson Date: Fri, 3 Dec 2010 10:53:38 +0100 Subject: [PATCH 13/40] ARM: 6522/1: kexec: Add call to non-crashing cores through IPI When kexec is used to start a crash kernel the other cores are notified. These non-crashing cores will save their state in the crash notes and then do nothing. Signed-off-by: Per Fransson Signed-off-by: Russell King --- arch/arm/kernel/machine_kexec.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) 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(®s, NULL); + printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n", + smp_processor_id()); + crash_save_cpu(®s, 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"); From cd3478f2bd8f2cec19f9247a8a9cd711cbe37683 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 30 Nov 2010 17:33:53 +0100 Subject: [PATCH 14/40] ARM: 6509/1: ftrace: ignore any ftrace.o in C version of recordmcount arch/arm/kernel/ftrace.c references mcount like kernel/tracing/ftrace.c, so change the exclusion filter to match any ftrace.o. Acked-by: Steven Rostedt Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- scripts/recordmcount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index f2f32eee2c5b..ac6e51ceed50 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -357,7 +357,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 */ From ed60453fa8f8fc3d034dfdf10371a99cc6905626 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 30 Nov 2010 17:36:48 +0100 Subject: [PATCH 15/40] ARM: 6511/1: ftrace: add ARM support for C version of recordmcount Depending on the compiler version, ARM GCC calls the mcount function either __gnu_mcount_nc or mcount. Acked-by: Steven Rostedt Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + scripts/recordmcount.c | 5 ++++- scripts/recordmcount.h | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db524e75c4a2..a7b9070b661e 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 diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index ac6e51ceed50..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; diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index 58e933a20544..8087bc8cd2d1 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); } From 9a4af112bd252be801a433fc3bef793b7b487c3c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 1 Dec 2010 07:45:00 +0100 Subject: [PATCH 16/40] ARM: 6515/1: Add zboot support for SuperH Mobile ARM When CONFIG_ZBOOT_ROM is selected, the resulting zImage file will be small boot loader and may be burned to rom or flash. This is the non-board-specific framework portion of this patch-set. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman Acked-by: Magnus Damm Signed-off-by: Russell King --- arch/arm/boot/compressed/Makefile | 4 ++ arch/arm/boot/compressed/head-shmobile.S | 53 +++++++++++++++++++++ arch/arm/mach-shmobile/include/mach/zboot.h | 12 +++++ 3 files changed, 69 insertions(+) create mode 100644 arch/arm/boot/compressed/head-shmobile.S create mode 100644 arch/arm/mach-shmobile/include/mach/zboot.h 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 + * Simon Horman + * + * 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 + + 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/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h new file mode 100644 index 000000000000..e0c218fde687 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/zboot.h @@ -0,0 +1,12 @@ +#ifndef ZBOOT_H +#define ZBOOT_H + +/************************************************** + * + * board specific settings + * + **************************************************/ + +#error "unsupported board." + +#endif /* ZBOOT_H */ From 3d09fbcd26851ffb2c40cec411b8e56db02520d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 1 Dec 2010 07:40:16 +0100 Subject: [PATCH 17/40] ARM: 6514/1: mach-shmobile: Add zboot support for SuperH Mobile ARM When CONFIG_ZBOOT_ROM is selected, the resulting zImage file will be small boot loader and may be burned to rom or flash. This is the board-specific portion of this patch-set. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman Acked-by: Magnus Damm Signed-off-by: Russell King --- arch/arm/mach-shmobile/board-ap4evb.c | 1 + .../include/mach/head-ap4evb.txt | 87 +++++++++++++++++++ arch/arm/mach-shmobile/include/mach/zboot.h | 8 ++ .../mach-shmobile/include/mach/zboot_macros.h | 65 ++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 arch/arm/mach-shmobile/include/mach/head-ap4evb.txt create mode 100644 arch/arm/mach-shmobile/include/mach/zboot_macros.h 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 #include #include +#include /* * 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 " + +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 index e0c218fde687..3ad86b7708e9 100644 --- a/arch/arm/mach-shmobile/include/mach/zboot.h +++ b/arch/arm/mach-shmobile/include/mach/zboot.h @@ -1,12 +1,20 @@ #ifndef ZBOOT_H #define ZBOOT_H +#include +#include + /************************************************** * * 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 */ From 161d1907607a5a562a152058c8daf1780ce7a00b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Nov 2010 00:48:07 +0100 Subject: [PATCH 18/40] ARM: 6475/1: Introduce asm/hardware/entry-macro-gic.S This patch is the identical GIC demux implementation merge V3. Instead of implementing same code over and over simply share it in entry-macro-gic.S. The shared code is based on the realview implementation. Each GIC demux instance still has to setup the base address of the controller using the get_irqnr_preamble macro. The rest of the GIC specific code can be shared. Signed-off-by: Magnus Damm Acked-by: Srinidhi Kasagar Signed-off-by: Russell King --- .../include/asm/hardware/entry-macro-gic.S | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 arch/arm/include/asm/hardware/entry-macro-gic.S 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..05587f125a13 --- /dev/null +++ b/arch/arm/include/asm/hardware/entry-macro-gic.S @@ -0,0 +1,68 @@ +/* + * 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 + +/* + * 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 From 960351fb8e980f0aa6682f11630ff98d3a18e2c0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Nov 2010 00:54:55 +0100 Subject: [PATCH 19/40] ARM: 6476/1: Use shared GIC entry macros on CNS3XXX Use the GIC demux code in asm/hardware/entry-macro-gic.S on the CNS3XXX subarchitecture. Signed-off-by: Magnus Damm Signed-off-by: Russell King --- .../mach-cns3xxx/include/mach/entry-macro.S | 61 +------------------ 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S index 5e1c5545680f..e793c3376728 100644 --- a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S +++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S @@ -9,7 +9,7 @@ */ #include -#include +#include .macro disable_fiq .endm @@ -21,62 +21,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 - - 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 From c4d8c80f59f0611d747399a774ebef71f517a30c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Nov 2010 00:58:43 +0100 Subject: [PATCH 20/40] ARM: 6477/1: Use shared GIC entry macros on Realview Use the GIC demux code in asm/hardware/entry-macro-gic.S on the Realview subarchitecture. Signed-off-by: Magnus Damm Signed-off-by: Russell King --- .../mach-realview/include/mach/entry-macro.S | 60 +------------------ 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/arch/arm/mach-realview/include/mach/entry-macro.S b/arch/arm/mach-realview/include/mach/entry-macro.S index 340a5c276946..4417b1039615 100644 --- a/arch/arm/mach-realview/include/mach/entry-macro.S +++ b/arch/arm/mach-realview/include/mach/entry-macro.S @@ -8,7 +8,7 @@ * warranty of any kind, whether express or implied. */ #include -#include +#include .macro disable_fiq .endm @@ -21,61 +21,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 - - 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 From 0005b349d5dc71471e1d47bd3efbf93f685620e1 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Nov 2010 01:00:40 +0100 Subject: [PATCH 21/40] ARM: 6478/1: Use shared GIC entry macros on Tegra Use the GIC demux code in asm/hardware/entry-macro-gic.S on the Tegra subarchitecture. Signed-off-by: Magnus Damm Acked-by: Olof Johansson Signed-off-by: Russell King --- .../arm/mach-tegra/include/mach/entry-macro.S | 64 +------------------ 1 file changed, 1 insertion(+), 63 deletions(-) diff --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S index 2ba9e5c9d2f6..dc0924915183 100644 --- a/arch/arm/mach-tegra/include/mach/entry-macro.S +++ b/arch/arm/mach-tegra/include/mach/entry-macro.S @@ -17,7 +17,7 @@ #if defined(CONFIG_ARM_GIC) -#include +#include /* 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 From 5488324a6cbae617d103c42944827d82d8f5efd4 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Nov 2010 01:02:06 +0100 Subject: [PATCH 22/40] ARM: 6479/1: Use shared GIC entry macros on UX500 Use the GIC demux code in asm/hardware/entry-macro-gic.S on the UX500 subarchitecture. Signed-off-by: Magnus Damm Signed-off-by: Russell King --- .../arm/mach-ux500/include/mach/entry-macro.S | 67 +------------------ 1 file changed, 1 insertion(+), 66 deletions(-) diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S index 60ea88db8283..3cc3cdf55180 100644 --- a/arch/arm/mach-ux500/include/mach/entry-macro.S +++ b/arch/arm/mach-ux500/include/mach/entry-macro.S @@ -11,7 +11,7 @@ * warranty of any kind, whether express or implied. */ #include -#include +#include .macro disable_fiq .endm @@ -22,68 +22,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 From c91a2bd70a617a638e157a7e99d4b21ee0e7b1cf Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Nov 2010 01:03:34 +0100 Subject: [PATCH 23/40] ARM: 6480/1: Use shared GIC entry macros on Vexpress Use the GIC demux code in asm/hardware/entry-macro-gic.S on the Versatile Express subarchitecture. Signed-off-by: Magnus Damm Signed-off-by: Russell King --- .../mach-vexpress/include/mach/entry-macro.S | 57 +------------------ 1 file changed, 1 insertion(+), 56 deletions(-) diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S index 20e9fb514f0a..19d5ac8ba071 100644 --- a/arch/arm/mach-vexpress/include/mach/entry-macro.S +++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S @@ -1,4 +1,4 @@ -#include +#include .macro disable_fiq .endm @@ -10,58 +10,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 - 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 - From e745a6676c76280f9721adeec79b08a0f2dfcc21 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Nov 2010 01:07:19 +0100 Subject: [PATCH 24/40] ARM: 6481/1: Use shared GIC entry macros on OMAP Common GIC entry macro for omap Signed-off-by: Tony Lindgren Signed-off-by: Magnus Damm Acked-by: Santosh Shilimkar Signed-off-by: Russell King --- .../arm/mach-omap2/include/mach/entry-macro.S | 92 +++++++------------ 1 file changed, 31 insertions(+), 61 deletions(-) diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S index 06e64e1fc28a..2e358df3fe19 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,15 @@ omap_irq_base: .word 0 #ifdef CONFIG_ARCH_OMAP4 +#include .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 */ - .macro irq_prio_table .endm From a0b7bd0829194c03921915a68ee4a331ee394223 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 8 Dec 2010 13:49:04 +0000 Subject: [PATCH 25/40] ARM: io: make iounmap() a simple macro Defining iounmap() with arguments prevents it from being used as a function pointer, causing platforms to work around this. Instead, define it to be a simple macro. Do the same for __arch_io(re|un)map too. Signed-off-by: Russell King --- arch/arm/include/asm/io.h | 4 ++-- arch/arm/mach-davinci/include/mach/io.h | 4 ++-- arch/arm/mach-iop13xx/include/mach/io.h | 4 ++-- arch/arm/mach-iop32x/include/mach/io.h | 4 ++-- arch/arm/mach-iop33x/include/mach/io.h | 4 ++-- arch/arm/mach-ixp23xx/include/mach/io.h | 4 ++-- arch/arm/mach-ixp4xx/include/mach/io.h | 4 ++-- arch/arm/mach-kirkwood/include/mach/io.h | 4 ++-- arch/arm/mach-orion5x/include/mach/io.h | 4 ++-- arch/arm/mach-tegra/include/mach/io.h | 4 ++-- arch/arm/plat-omap/include/plat/io.h | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 815efa2d4e07..91be1f8c2d25 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -245,13 +245,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #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) +#define iounmap __iounmap #else #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) +#define iounmap __arch_iounmap #endif /* 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-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-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-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/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); From 28257f7fdee0facc3b7f934e82c2485f27120d41 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 8 Dec 2010 13:57:48 +0000 Subject: [PATCH 26/40] ARM: io: simplify ioremap* and iounmap definitions We don't need to repeat the same definitions of the ioremap*(), once in terms of __arch_ioremap() and again in terms of __arm_ioremap(). Instead, if the platform hasn't provided an __arch_ioremap, define this to be __arm_ioremap, and only define the ioremap*() set using __arch_ioremap. Signed-off-by: Russell King --- arch/arm/include/asm/io.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 91be1f8c2d25..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 __iounmap -#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 __arch_iounmap -#endif /* * io{read,write}{8,16,32} macros From b580b899dd05a007ad232ee49a07b32d91876462 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Dec 2010 15:55:14 +0000 Subject: [PATCH 27/40] ARM: GIC: provide a single initialization function for boot CPU Provide gic_init() which initializes the GIC distributor and current CPU's GIC interface for the boot (or single) CPU. Reviewed-by: Catalin Marinas Tested-by: Abhijeet Dharmapurikar Signed-off-by: Russell King --- arch/arm/common/gic.c | 11 +++++++++-- arch/arm/include/asm/hardware/gic.h | 2 +- arch/arm/mach-cns3xxx/core.c | 4 ++-- arch/arm/mach-msm/board-msm8x60.c | 3 +-- arch/arm/mach-omap2/omap4-common.c | 4 ++-- arch/arm/mach-realview/realview_eb.c | 12 ++++++------ arch/arm/mach-realview/realview_pb1176.c | 10 ++++++---- arch/arm/mach-realview/realview_pb11mp.c | 9 +++++---- arch/arm/mach-realview/realview_pba8.c | 5 +++-- arch/arm/mach-realview/realview_pbx.c | 11 +++++------ arch/arm/mach-s5pv310/cpu.c | 3 +-- arch/arm/mach-tegra/irq.c | 4 ++-- arch/arm/mach-ux500/cpu.c | 4 ++-- arch/arm/mach-vexpress/ct-ca9x4.c | 3 +-- 14 files changed, 46 insertions(+), 39 deletions(-) diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index e6388dcd8cfa..8eab2f34a7fa 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -213,8 +213,8 @@ 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(unsigned int gic_nr, void __iomem *base, + unsigned int irq_start) { unsigned int gic_irqs, irq_limit, i; u32 cpumask = 1 << smp_processor_id(); @@ -314,6 +314,13 @@ 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) +{ + gic_dist_init(gic_nr, dist_base, irq_start); + gic_cpu_init(gic_nr, cpu_base); +} + #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 7f34333bb545..387c6ae55673 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -33,8 +33,8 @@ #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); +void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); #endif diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 9ca4d581016f..e9c491552ca1 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -74,8 +74,8 @@ 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), + gic_cpu_base_addr); } void cns3xxx_power_off(void) diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c index 7486a681cc71..aaf8ec8a1495 100644 --- a/arch/arm/mach-msm/board-msm8x60.c +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -44,9 +44,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, gic_cpu_base_addr); /* 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/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 2f895553e6a8..3fd3df7a7697 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -35,12 +35,12 @@ void __init gic_init_irq(void) /* 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_init(0, 29, gic_dist_base_addr, gic_cpu_base_addr); } #ifdef CONFIG_CACHE_L2X0 diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index f2697106f809..241bcbc73f61 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -365,20 +365,20 @@ static void __init gic_init_irq(void) /* 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), + gic_cpu_base_addr); #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), + gic_cpu_base_addr); } } diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index a4125619d71b..8047b198f847 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -305,12 +305,14 @@ 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), + gic_cpu_base_addr); /* 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..61204265b4e4 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -310,12 +310,13 @@ static void __init gic_init_irq(void) /* 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), + gic_cpu_base_addr); /* 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..90f492a35d4f 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -274,8 +274,9 @@ 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..86f28f725a23 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -314,14 +314,13 @@ 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..bce3e91be432 100644 --- a/arch/arm/mach-s5pv310/cpu.c +++ b/arch/arm/mach-s5pv310/cpu.c @@ -123,8 +123,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-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-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-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index fd25ccd7272f..25a3ca6e5a48 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -65,8 +65,7 @@ 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), gic_cpu_base_addr); } #if 0 From 384895330e0f3954d9478fd0853145f9c169df12 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Dec 2010 16:01:03 +0000 Subject: [PATCH 28/40] ARM: GIC: Remove MMIO address from gic_cpu_init, rename to gic_secondary_init We don't need to re-pass the base address for the CPU interfaces to the GIC for secondary CPUs, as it will never be different from the boot CPU - and even if it was, we'd overwrite the boot CPU's base address. Get rid of this argument, and rename to gic_secondary_init(). Reviewed-by: Catalin Marinas Tested-by: Abhijeet Dharmapurikar Signed-off-by: Russell King --- arch/arm/common/gic.c | 7 ++++++- arch/arm/include/asm/hardware/gic.h | 2 +- arch/arm/mach-omap2/omap-smp.c | 2 +- arch/arm/mach-realview/platsmp.c | 2 +- arch/arm/mach-s5pv310/platsmp.c | 2 +- arch/arm/mach-tegra/platsmp.c | 2 +- arch/arm/mach-ux500/platsmp.c | 2 +- arch/arm/mach-vexpress/platsmp.c | 2 +- 8 files changed, 13 insertions(+), 8 deletions(-) diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 8eab2f34a7fa..dd0d18d560ac 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -284,7 +284,7 @@ static 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(unsigned int gic_nr, void __iomem *base) { void __iomem *dist_base; int i; @@ -321,6 +321,11 @@ void __init gic_init(unsigned int gic_nr, unsigned int irq_start, gic_cpu_init(gic_nr, cpu_base); } +void __cpuinit gic_secondary_init(unsigned int gic_nr) +{ + gic_cpu_init(gic_nr, gic_data[gic_nr].cpu_base); +} + #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 387c6ae55673..48876a3fbda8 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -33,8 +33,8 @@ #define GIC_DIST_SOFTINT 0xf00 #ifndef __ASSEMBLY__ -void gic_cpu_init(unsigned int gic_nr, void __iomem *base); 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); #endif 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-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-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-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/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-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 From ff2e27ae0b17f53a6a289c87d325f706598f3788 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Dec 2010 16:13:29 +0000 Subject: [PATCH 29/40] ARM: GIC: consolidate gic_cpu_base_addr to common GIC code Every architecture using the GIC has a gic_cpu_base_addr pointer for GIC 0 for their entry assembly code to use to decode the cause of the current interrupt. Move this into the common GIC code. Reviewed-by: Catalin Marinas Tested-by: Abhijeet Dharmapurikar Signed-off-by: Russell King --- arch/arm/common/gic.c | 5 +++++ arch/arm/include/asm/hardware/gic.h | 2 ++ arch/arm/mach-cns3xxx/core.c | 5 +---- arch/arm/mach-cns3xxx/core.h | 1 - arch/arm/mach-msm/board-msm8x60.c | 6 ++---- arch/arm/mach-omap2/include/mach/omap4-common.h | 1 - arch/arm/mach-omap2/omap4-common.c | 9 +++++---- arch/arm/mach-realview/core.c | 3 --- arch/arm/mach-realview/core.h | 1 - arch/arm/mach-realview/realview_eb.c | 6 ++---- arch/arm/mach-realview/realview_pb1176.c | 3 +-- arch/arm/mach-realview/realview_pb11mp.c | 3 +-- arch/arm/mach-realview/realview_pba8.c | 1 - arch/arm/mach-realview/realview_pbx.c | 2 -- arch/arm/mach-s5pv310/cpu.c | 3 --- arch/arm/mach-s5pv310/include/mach/smp.h | 2 -- arch/arm/mach-vexpress/core.h | 2 -- arch/arm/mach-vexpress/ct-ca9x4.c | 6 ++---- 18 files changed, 21 insertions(+), 40 deletions(-) diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index dd0d18d560ac..9105d48c02de 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; + struct gic_chip_data { unsigned int irq_offset; void __iomem *dist_base; @@ -317,6 +320,8 @@ static void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) void __init gic_init(unsigned int gic_nr, unsigned int irq_start, void __iomem *dist_base, void __iomem *cpu_base) { + if (gic_nr == 0) + gic_cpu_base_addr = cpu_base; gic_dist_init(gic_nr, dist_base, irq_start); gic_cpu_init(gic_nr, cpu_base); } diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 48876a3fbda8..a82a77703544 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -33,6 +33,8 @@ #define GIC_DIST_SOFTINT 0xf00 #ifndef __ASSEMBLY__ +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); diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index e9c491552ca1..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_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), - gic_cpu_base_addr); + __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-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c index aaf8ec8a1495..9b5eb2b4ae1b 100644 --- a/arch/arm/mach-msm/board-msm8x60.c +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -28,8 +28,6 @@ #include #include -void __iomem *gic_cpu_base_addr; - unsigned long clk_get_max_axi_khz(void) { return 0; @@ -44,8 +42,8 @@ static void __init msm8x60_init_irq(void) { unsigned int i; - gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE; - gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, gic_cpu_base_addr); + 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/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/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 3fd3df7a7697..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); /* Static mapping, never released */ - gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512); - BUG_ON(!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_addr); + gic_init(0, 29, gic_dist_base_addr, gic_cpu_base); } #ifdef CONFIG_CACHE_L2X0 diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 07c08151dfe6..e292eb8c3c4e 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -54,9 +54,6 @@ #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/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 241bcbc73f61..6ef5c5e528b2 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -364,9 +364,8 @@ 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_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), - gic_cpu_base_addr); + __io_address(REALVIEW_EB11MP_GIC_CPU_BASE)); #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB /* board GIC, secondary */ @@ -376,9 +375,8 @@ static void __init gic_init_irq(void) #endif } else { /* board GIC, primary */ - gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE); gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE), - gic_cpu_base_addr); + __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 8047b198f847..cbdc97a5685f 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -304,10 +304,9 @@ 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_init(0, IRQ_DC1176_GIC_START, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), - gic_cpu_base_addr); + __io_address(REALVIEW_DC1176_GIC_CPU_BASE)); /* board GIC, secondary */ gic_init(1, IRQ_PB1176_GIC_START, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 61204265b4e4..8e8ab7d29a6a 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -309,9 +309,8 @@ 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_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), - gic_cpu_base_addr); + __io_address(REALVIEW_TC11MP_GIC_CPU_BASE)); /* board GIC, secondary */ gic_init(1, IRQ_PB11MP_GIC_START, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 90f492a35d4f..841118e3e118 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -273,7 +273,6 @@ 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_init(0, IRQ_PBA8_GIC_START, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), __io_address(REALVIEW_PBA8_GIC_CPU_BASE)); diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 86f28f725a23..02b755b009db 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -313,11 +313,9 @@ 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_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_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 bce3e91be432..72ab289e7816 100644 --- a/arch/arm/mach-s5pv310/cpu.c +++ b/arch/arm/mach-s5pv310/cpu.c @@ -24,8 +24,6 @@ #include -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,7 +120,6 @@ void __init s5pv310_init_irq(void) { int irq; - gic_cpu_base_addr = 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++) { 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 #include -extern void __iomem *gic_cpu_base_addr; - /* * We use IRQ1 as the IPI */ 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 25a3ca6e5a48..8e0a3b7c8638 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -60,12 +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_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST), gic_cpu_base_addr); + gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST), + MMIO_P2V(A9_MPCORE_GIC_CPU)); } #if 0 From bef8f9ee32511a28f1c9a7d3b8c51cdac030b564 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 4 Dec 2010 16:50:58 +0000 Subject: [PATCH 30/40] ARM: GIC: move gic_data[] initialization into gic_init() This avoids writing unnecessarily to gic_data[] from other CPUs, making this a mostly read-only variable. Reviewed-by: Catalin Marinas Tested-by: Abhijeet Dharmapurikar Signed-off-by: Russell King --- arch/arm/common/gic.c | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 9105d48c02de..c7155bdeb815 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -36,7 +36,7 @@ static DEFINE_SPINLOCK(irq_controller_lock); /* Address of GIC 0 CPU interface */ -void __iomem *gic_cpu_base_addr; +void __iomem *gic_cpu_base_addr __read_mostly; struct gic_chip_data { unsigned int irq_offset; @@ -48,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) { @@ -216,21 +216,16 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) set_irq_chained_handler(irq, gic_handle_cascade_irq); } -static void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, +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); /* @@ -270,7 +265,7 @@ static 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; @@ -279,7 +274,7 @@ static 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); } @@ -287,19 +282,12 @@ static void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, writel(1, base + GIC_DIST_CTRL); } -static 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. @@ -320,15 +308,27 @@ static void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) 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_nr, dist_base, irq_start); - gic_cpu_init(gic_nr, cpu_base); + + gic_dist_init(gic, irq_start); + gic_cpu_init(gic); } void __cpuinit gic_secondary_init(unsigned int gic_nr) { - gic_cpu_init(gic_nr, gic_data[gic_nr].cpu_base); + BUG_ON(gic_nr >= MAX_GIC_NR); + + gic_cpu_init(&gic_data[gic_nr]); } #ifdef CONFIG_SMP From 7627dc802a98aebebc6a34e5b6558ea4717c968c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 5 Dec 2010 08:51:38 +0000 Subject: [PATCH 31/40] ARM: GIC: private a standard get_irqnr_preamble assembler macro Provide a standard get_irqnr_preamble assembler macro for platforms to use, which retrieves the base address of the GIC CPU interface from gic_cpu_base_addr. Allow platforms to override this by defining HAVE_GET_IRQNR_PREAMBLE. Reviewed-by: Catalin Marinas Tested-by: Abhijeet Dharmapurikar Signed-off-by: Russell King --- arch/arm/include/asm/hardware/entry-macro-gic.S | 7 +++++++ arch/arm/mach-cns3xxx/include/mach/entry-macro.S | 5 ----- arch/arm/mach-omap2/include/mach/entry-macro.S | 1 + arch/arm/mach-realview/include/mach/entry-macro.S | 5 ----- arch/arm/mach-tegra/include/mach/entry-macro.S | 2 +- arch/arm/mach-ux500/include/mach/entry-macro.S | 1 + arch/arm/mach-vexpress/include/mach/entry-macro.S | 5 ----- 7 files changed, 10 insertions(+), 16 deletions(-) diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S index 05587f125a13..c115b82fe80a 100644 --- a/arch/arm/include/asm/hardware/entry-macro-gic.S +++ b/arch/arm/include/asm/hardware/entry-macro-gic.S @@ -10,6 +10,13 @@ #include +#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: diff --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S index e793c3376728..6bd83ed90afe 100644 --- a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S +++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S @@ -14,10 +14,5 @@ .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 diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S index 2e358df3fe19..d54c4f89a8bd 100644 --- a/arch/arm/mach-omap2/include/mach/entry-macro.S +++ b/arch/arm/mach-omap2/include/mach/entry-macro.S @@ -170,6 +170,7 @@ omap_irq_base: .word 0 #ifdef CONFIG_ARCH_OMAP4 +#define HAVE_GET_IRQNR_PREAMBLE #include .macro get_irqnr_preamble, base, tmp diff --git a/arch/arm/mach-realview/include/mach/entry-macro.S b/arch/arm/mach-realview/include/mach/entry-macro.S index 4417b1039615..4071164aebaa 100644 --- a/arch/arm/mach-realview/include/mach/entry-macro.S +++ b/arch/arm/mach-realview/include/mach/entry-macro.S @@ -13,11 +13,6 @@ .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 diff --git a/arch/arm/mach-tegra/include/mach/entry-macro.S b/arch/arm/mach-tegra/include/mach/entry-macro.S index dc0924915183..dd165c53889d 100644 --- a/arch/arm/mach-tegra/include/mach/entry-macro.S +++ b/arch/arm/mach-tegra/include/mach/entry-macro.S @@ -16,7 +16,7 @@ #include #if defined(CONFIG_ARM_GIC) - +#define HAVE_GET_IRQNR_PREAMBLE #include /* Uses the GIC interrupt controller built into the cpu */ diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S index 3cc3cdf55180..a37f585a3ecb 100644 --- a/arch/arm/mach-ux500/include/mach/entry-macro.S +++ b/arch/arm/mach-ux500/include/mach/entry-macro.S @@ -11,6 +11,7 @@ * warranty of any kind, whether express or implied. */ #include +#define HAVE_GET_IRQNR_PREAMBLE #include .macro disable_fiq diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S index 19d5ac8ba071..73c11297509e 100644 --- a/arch/arm/mach-vexpress/include/mach/entry-macro.S +++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S @@ -3,10 +3,5 @@ .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 From ac61d143ffe2a6db4d4bcf47c21a5159d6a1b644 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 6 Dec 2010 10:38:14 +0000 Subject: [PATCH 32/40] ARM: GIC: move enablement of PPI interrupts to gic.c Avoid adding nasty genirq-specific code to local timers to enable PPI interrupts. Instead, provide a gic function to do this. Signed-off-by: Russell King --- arch/arm/common/gic.c | 10 ++++++++++ arch/arm/include/asm/hardware/gic.h | 1 + arch/arm/kernel/smp_twd.c | 7 +------ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index c7155bdeb815..0b89ef001330 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -331,6 +331,16 @@ void __cpuinit gic_secondary_init(unsigned int 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/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index a82a77703544..84557d321001 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -39,6 +39,7 @@ 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/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); } From 9f15d2caca102c4b79e34562296bcbf982665cb2 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Thu, 16 Dec 2010 20:51:30 +0100 Subject: [PATCH 33/40] ARM: 6447/3: sa1100: Put nanoEngine support back in the kernel Adds Bright Star Engineering's nanoEngine board support to the kernel. Also: - Adds the nanoEngine memory chip to arch/arm/mach-sa1100/cpu-sa1110.c (Micron MT48LC8M16A2TG-75). - Increase in the sdram_params->name[] field length to accomodate the name of the memory chip. - Clean up of header content and order of arch/arm/mach-sa1100/cpu-sa1110.c Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- arch/arm/mach-sa1100/Kconfig | 8 +++ arch/arm/mach-sa1100/Makefile | 2 + arch/arm/mach-sa1100/cpu-sa1110.c | 33 +++++---- arch/arm/mach-sa1100/nanoengine.c | 112 ++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 arch/arm/mach-sa1100/nanoengine.c diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index 5da8c35aa0de..3563d4637f6e 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig @@ -118,6 +118,14 @@ config SA1100_LART (also known as the LART). See for information on the LART. +config SA1100_NANOENGINE + bool "nanoEngine" + select CPU_FREQ_SA1110 + help + Say Y here if you are using the Bright Star Engineering nanoEngine. + See 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..8029fe25bfcc 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -37,6 +37,8 @@ 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_SA1100_PLEB) += pleb.o obj-$(CONFIG_SA1100_SHANNON) += shannon.o diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 7252874d328b..8251af277c1a 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 -#include -#include -#include #include #include #include -#include +#include +#include +#include -#include #include #include -#include + +#include #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, }, }; @@ -336,7 +341,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, @@ -369,14 +376,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"; + if (machine_is_nanoengine()) + name = "MT48LC8M16A2TG-75"; } sdram = sa1110_find_sdram(name); diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c new file mode 100644 index 000000000000..e4a03099e2a3 --- /dev/null +++ b/arch/arm/mach-sa1100/nanoengine.c @@ -0,0 +1,112 @@ +/* + * linux/arch/arm/mach-sa1100/nanoengine.c + * + * Bright Star Engineering's nanoEngine board init code. + * + * Copyright (C) 2009 Marcelo Roberto Jimenez + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#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 Config Space */ + .virtual = 0xf1000000, + .pfn = __phys_to_pfn(0x18A00000), + .length = 0x00100000, + .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 From 47bb3b31ab2c95e275b850a291794a29aaaa31cd Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:32:48 +0100 Subject: [PATCH 34/40] ARM: 6451/1: sa1100: Fix checkpatch.pl issues in arch/arm/mach-sa1100/cpu-sa1110.c. This patch fixes checkpatch.pl issues in arch/arm/mach-sa1100/cpu-sa1110.c. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- arch/arm/mach-sa1100/cpu-sa1110.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 8251af277c1a..675bf8ef97e8 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -185,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 } @@ -218,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); @@ -237,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) @@ -285,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 @@ -300,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\ @@ -356,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; @@ -381,7 +383,7 @@ static int __init sa1110_clk_init(void) if (machine_is_h3100()) name = "KM416S4030CT"; if (machine_is_jornada720()) - name = "K4S281632B-1H"; + name = "K4S281632B-1H"; if (machine_is_nanoengine()) name = "MT48LC8M16A2TG-75"; } From d2ccb52d88dcb7eb3539d0e0c77a7028b8d46037 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Thu, 16 Dec 2010 21:31:32 +0100 Subject: [PATCH 35/40] ARM: 6455/2: Better use of the RTC framework for sa11xx. This patch uses the RTC framework to treat some common ioctl. In particular, it fixes the behaviour of rtc_irq_set_freq(), which did not work as expected because the timer was not beeing retriggered. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- drivers/rtc/rtc-sa1100.c | 98 ++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index b0985f727078..88ea52b8647a 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -42,7 +42,7 @@ #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); @@ -156,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); @@ -175,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; } @@ -183,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; @@ -207,6 +263,7 @@ 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); @@ -226,6 +283,9 @@ static int sa1100_rtc_open(struct device *dev) 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: @@ -274,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; } @@ -344,12 +385,14 @@ 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; @@ -365,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) @@ -391,13 +436,18 @@ 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(). * From 17b38ebb6a32250a220d6af77293f7e3f9c62a6e Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:39:05 +0100 Subject: [PATCH 36/40] ARM: 6457/1: pcmcia: Fix checkpatch.pl issues in drivers/pcmcia/soc_common.c. This patch fixes checkpatch.pl issues in drivers/pcmcia/soc_common.c. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- drivers/pcmcia/soc_common.c | 130 +++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 61 deletions(-) diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 689e3c02edb8..b42e129b7673 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -31,20 +31,20 @@ ======================================================================*/ +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -#include -#include #include -#include +#include #include -#include #include #include "soc_common.h" @@ -68,7 +68,8 @@ void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, #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) @@ -85,11 +86,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); @@ -131,8 +136,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; @@ -144,7 +149,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); @@ -298,24 +304,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)?" ":"", - (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)?" ":"", - (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) ? " " : "", + (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) ? " " : "", + (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); @@ -330,8 +336,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; @@ -340,14 +346,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)?"":"", - (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) ? "" : "", + (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__, @@ -384,8 +390,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; @@ -394,14 +400,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)?"":"", - (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) ? "" : "", + (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; @@ -456,8 +462,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; @@ -475,13 +481,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)); @@ -490,12 +497,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; } @@ -588,7 +595,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); @@ -614,7 +621,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); From fa87672ab30ce6564393778b8cbc67fc32712a30 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Mon, 18 Oct 2010 22:41:29 +0100 Subject: [PATCH 37/40] ARM: 6458/1: pcmcia: Adds nanoEngine PCMCIA support. This patch adds nanoEngine PCMCIA support, with support for two sockets. 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/ Acked-by: Dominik Brodowski Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- .../arm/mach-sa1100/include/mach/nanoengine.h | 30 +++ arch/arm/mach-sa1100/nanoengine.c | 2 +- drivers/pcmcia/Makefile | 3 +- drivers/pcmcia/sa1100_generic.c | 3 + drivers/pcmcia/sa1100_generic.h | 1 + drivers/pcmcia/sa1100_nanoengine.c | 219 ++++++++++++++++++ 6 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-sa1100/include/mach/nanoengine.h create mode 100644 drivers/pcmcia/sa1100_nanoengine.c 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..053776645526 --- /dev/null +++ b/arch/arm/mach-sa1100/include/mach/nanoengine.h @@ -0,0 +1,30 @@ +/* + * 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 + * + * 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 + +#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_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 + +#endif + diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c index e4a03099e2a3..844ec61415a7 100644 --- a/arch/arm/mach-sa1100/nanoengine.c +++ b/arch/arm/mach-sa1100/nanoengine.c @@ -3,7 +3,7 @@ * * Bright Star Engineering's nanoEngine board init code. * - * Copyright (C) 2009 Marcelo Roberto Jimenez + * Copyright (C) 2010 Marcelo Roberto Jimenez * * 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 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 945857f8c284..ff8a027a4afb 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 + * + * Based on original work for kernel 2.4 by + * Miguel Freitas + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#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; +} + From b080ac8ad47aeeb845d8d11924f09255cf49b5e9 Mon Sep 17 00:00:00 2001 From: Marcelo Roberto Jimenez Date: Thu, 16 Dec 2010 21:34:51 +0100 Subject: [PATCH 38/40] ARM: 6459/2: sa1100: Add nanoEngine PCI support. This patch adds nanoEngine's PCI support. Signed-off-by: Marcelo Roberto Jimenez Signed-off-by: Russell King --- arch/arm/Kconfig | 8 +- arch/arm/mach-sa1100/Kconfig | 2 + arch/arm/mach-sa1100/Makefile | 1 + arch/arm/mach-sa1100/include/mach/hardware.h | 8 + .../arm/mach-sa1100/include/mach/nanoengine.h | 22 ++ arch/arm/mach-sa1100/nanoengine.c | 13 +- arch/arm/mach-sa1100/pci-nanoengine.c | 284 ++++++++++++++++++ 7 files changed, 334 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-sa1100/pci-nanoengine.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a19a5266d5fc..6af6c79ade2e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1164,7 +1164,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 +1175,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 diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index 3563d4637f6e..42625e4d949a 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig @@ -121,6 +121,8 @@ config SA1100_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 for information diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index 8029fe25bfcc..e697691eed28 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -38,6 +38,7 @@ 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 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 index 053776645526..14f8382d0665 100644 --- a/arch/arm/mach-sa1100/include/mach/nanoengine.h +++ b/arch/arm/mach-sa1100/include/mach/nanoengine.h @@ -14,6 +14,8 @@ #ifndef __ASM_ARCH_NANOENGINE_H #define __ASM_ARCH_NANOENGINE_H +#include + #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) */ @@ -21,10 +23,30 @@ #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 index 844ec61415a7..72087f0658b7 100644 --- a/arch/arm/mach-sa1100/nanoengine.c +++ b/arch/arm/mach-sa1100/nanoengine.c @@ -26,6 +26,7 @@ #include #include +#include #include "generic.h" @@ -74,11 +75,17 @@ static struct map_desc nanoengine_io_desc[] __initdata = { .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 = 0xf1000000, - .pfn = __phys_to_pfn(0x18A00000), - .length = 0x00100000, + .virtual = NANO_PCI_CONFIG_SPACE_VIRT, + .pfn = __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS), + .length = NANO_PCI_CONFIG_SPACE_SIZE, .type = MT_DEVICE } }; 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 + * + * 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 +#include +#include +#include + +#include +#include + +#include + +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- SERR+ 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); From 4f444e2b59dd4255d121b57ec41a4a8c5d6bce46 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Mon, 3 Jan 2011 12:09:05 +0100 Subject: [PATCH 39/40] ARM: 6606/1: sa1100: Fix platform device registration Since commit 7a5b4e16c880f8350d255dc188f81622905618c1, simpad devices don't boot anymore, since platform devices are registered too early. Fix by moving the registration from map_io to arch_initcall as done on other sa1100 boards. Signed-off-by: Jochen Friedrich Acked-by: Kristoffer Ericson Signed-off-by: Russell King --- arch/arm/mach-sa1100/simpad.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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"); From cf562b4a550b3cd9d602a05bc27aaaaa376947b4 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Mon, 3 Jan 2011 12:19:00 +0100 Subject: [PATCH 40/40] ARM: 6607/1: sa1100: Update platform device registration Replace some magic numbers with constants and add interrupt definitions. Signed-off-by: Jochen Friedrich Signed-off-by: Russell King --- arch/arm/mach-sa1100/generic.c | 41 +++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) 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;