diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2012-01-07 07:30:20 -0500 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2012-01-07 07:42:17 -0500 |
| commit | 237c78beb8a988453bac1993d21f025d070a0d8d (patch) | |
| tree | 9864f0924650770881141359a2d5bac623949789 /arch/arm/include | |
| parent | 4eb821999086417ab42a15174b51497122fc406e (diff) | |
| parent | 7b9dd47136c07ffd883aff6926c7b281e4c1eea4 (diff) | |
Merge branch 'depends/rmk/for-linus' into samsung/dt
Conflicts:
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/cpu.c -> common.c
arch/arm/mach-exynos/include/mach/entry-macro.S
arch/arm/mach-exynos/init.c -> common.c
arch/arm/mach-s5p64x0/init.c -> common.c
arch/arm/mach-s5pv210/init.c -> common.c
Multiple files were moved into common.c files in the rmk/for-linus
branch, so this moves over the samsung/dt changes to the new
files.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/include')
31 files changed, 744 insertions, 327 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 29035e86a59..b6e65dedfd7 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
| @@ -187,6 +187,17 @@ | |||
| 187 | #endif | 187 | #endif |
| 188 | 188 | ||
| 189 | /* | 189 | /* |
| 190 | * Instruction barrier | ||
| 191 | */ | ||
| 192 | .macro instr_sync | ||
| 193 | #if __LINUX_ARM_ARCH__ >= 7 | ||
| 194 | isb | ||
| 195 | #elif __LINUX_ARM_ARCH__ == 6 | ||
| 196 | mcr p15, 0, r0, c7, c5, 4 | ||
| 197 | #endif | ||
| 198 | .endm | ||
| 199 | |||
| 200 | /* | ||
| 190 | * SMP data memory barrier | 201 | * SMP data memory barrier |
| 191 | */ | 202 | */ |
| 192 | .macro smp_dmb mode | 203 | .macro smp_dmb mode |
diff --git a/arch/arm/include/asm/bug.h b/arch/arm/include/asm/bug.h index 9abe7a07d5a..fac79dceb73 100644 --- a/arch/arm/include/asm/bug.h +++ b/arch/arm/include/asm/bug.h | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | #define __BUG(__file, __line, __value) \ | 33 | #define __BUG(__file, __line, __value) \ |
| 34 | do { \ | 34 | do { \ |
| 35 | BUILD_BUG_ON(sizeof(struct bug_entry) != 12); \ | ||
| 36 | asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ | 35 | asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \ |
| 37 | ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ | 36 | ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ |
| 38 | "2:\t.asciz " #__file "\n" \ | 37 | "2:\t.asciz " #__file "\n" \ |
diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h new file mode 100644 index 00000000000..a0ada3ea435 --- /dev/null +++ b/arch/arm/include/asm/cti.h | |||
| @@ -0,0 +1,179 @@ | |||
| 1 | #ifndef __ASMARM_CTI_H | ||
| 2 | #define __ASMARM_CTI_H | ||
| 3 | |||
| 4 | #include <asm/io.h> | ||
| 5 | |||
| 6 | /* The registers' definition is from section 3.2 of | ||
| 7 | * Embedded Cross Trigger Revision: r0p0 | ||
| 8 | */ | ||
| 9 | #define CTICONTROL 0x000 | ||
| 10 | #define CTISTATUS 0x004 | ||
| 11 | #define CTILOCK 0x008 | ||
| 12 | #define CTIPROTECTION 0x00C | ||
| 13 | #define CTIINTACK 0x010 | ||
| 14 | #define CTIAPPSET 0x014 | ||
| 15 | #define CTIAPPCLEAR 0x018 | ||
| 16 | #define CTIAPPPULSE 0x01c | ||
| 17 | #define CTIINEN 0x020 | ||
| 18 | #define CTIOUTEN 0x0A0 | ||
| 19 | #define CTITRIGINSTATUS 0x130 | ||
| 20 | #define CTITRIGOUTSTATUS 0x134 | ||
| 21 | #define CTICHINSTATUS 0x138 | ||
| 22 | #define CTICHOUTSTATUS 0x13c | ||
| 23 | #define CTIPERIPHID0 0xFE0 | ||
| 24 | #define CTIPERIPHID1 0xFE4 | ||
| 25 | #define CTIPERIPHID2 0xFE8 | ||
| 26 | #define CTIPERIPHID3 0xFEC | ||
| 27 | #define CTIPCELLID0 0xFF0 | ||
| 28 | #define CTIPCELLID1 0xFF4 | ||
| 29 | #define CTIPCELLID2 0xFF8 | ||
| 30 | #define CTIPCELLID3 0xFFC | ||
| 31 | |||
| 32 | /* The below are from section 3.6.4 of | ||
| 33 | * CoreSight v1.0 Architecture Specification | ||
| 34 | */ | ||
| 35 | #define LOCKACCESS 0xFB0 | ||
| 36 | #define LOCKSTATUS 0xFB4 | ||
| 37 | |||
| 38 | /* write this value to LOCKACCESS will unlock the module, and | ||
| 39 | * other value will lock the module | ||
| 40 | */ | ||
| 41 | #define LOCKCODE 0xC5ACCE55 | ||
| 42 | |||
| 43 | /** | ||
| 44 | * struct cti - cross trigger interface struct | ||
| 45 | * @base: mapped virtual address for the cti base | ||
| 46 | * @irq: irq number for the cti | ||
| 47 | * @trig_out_for_irq: triger out number which will cause | ||
| 48 | * the @irq happen | ||
| 49 | * | ||
| 50 | * cti struct used to operate cti registers. | ||
| 51 | */ | ||
| 52 | struct cti { | ||
| 53 | void __iomem *base; | ||
| 54 | int irq; | ||
| 55 | int trig_out_for_irq; | ||
| 56 | }; | ||
| 57 | |||
| 58 | /** | ||
| 59 | * cti_init - initialize the cti instance | ||
| 60 | * @cti: cti instance | ||
| 61 | * @base: mapped virtual address for the cti base | ||
| 62 | * @irq: irq number for the cti | ||
| 63 | * @trig_out: triger out number which will cause | ||
| 64 | * the @irq happen | ||
| 65 | * | ||
| 66 | * called by machine code to pass the board dependent | ||
| 67 | * @base, @irq and @trig_out to cti. | ||
| 68 | */ | ||
| 69 | static inline void cti_init(struct cti *cti, | ||
| 70 | void __iomem *base, int irq, int trig_out) | ||
| 71 | { | ||
| 72 | cti->base = base; | ||
| 73 | cti->irq = irq; | ||
| 74 | cti->trig_out_for_irq = trig_out; | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * cti_map_trigger - use the @chan to map @trig_in to @trig_out | ||
| 79 | * @cti: cti instance | ||
| 80 | * @trig_in: trigger in number | ||
| 81 | * @trig_out: trigger out number | ||
| 82 | * @channel: channel number | ||
| 83 | * | ||
| 84 | * This function maps one trigger in of @trig_in to one trigger | ||
| 85 | * out of @trig_out using the channel @chan. | ||
| 86 | */ | ||
| 87 | static inline void cti_map_trigger(struct cti *cti, | ||
| 88 | int trig_in, int trig_out, int chan) | ||
| 89 | { | ||
| 90 | void __iomem *base = cti->base; | ||
| 91 | unsigned long val; | ||
| 92 | |||
| 93 | val = __raw_readl(base + CTIINEN + trig_in * 4); | ||
| 94 | val |= BIT(chan); | ||
| 95 | __raw_writel(val, base + CTIINEN + trig_in * 4); | ||
| 96 | |||
| 97 | val = __raw_readl(base + CTIOUTEN + trig_out * 4); | ||
| 98 | val |= BIT(chan); | ||
| 99 | __raw_writel(val, base + CTIOUTEN + trig_out * 4); | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * cti_enable - enable the cti module | ||
| 104 | * @cti: cti instance | ||
| 105 | * | ||
| 106 | * enable the cti module | ||
| 107 | */ | ||
| 108 | static inline void cti_enable(struct cti *cti) | ||
| 109 | { | ||
| 110 | __raw_writel(0x1, cti->base + CTICONTROL); | ||
| 111 | } | ||
| 112 | |||
| 113 | /** | ||
| 114 | * cti_disable - disable the cti module | ||
| 115 | * @cti: cti instance | ||
| 116 | * | ||
| 117 | * enable the cti module | ||
| 118 | */ | ||
| 119 | static inline void cti_disable(struct cti *cti) | ||
| 120 | { | ||
| 121 | __raw_writel(0, cti->base + CTICONTROL); | ||
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * cti_irq_ack - clear the cti irq | ||
| 126 | * @cti: cti instance | ||
| 127 | * | ||
| 128 | * clear the cti irq | ||
| 129 | */ | ||
| 130 | static inline void cti_irq_ack(struct cti *cti) | ||
| 131 | { | ||
| 132 | void __iomem *base = cti->base; | ||
| 133 | unsigned long val; | ||
| 134 | |||
| 135 | val = __raw_readl(base + CTIINTACK); | ||
| 136 | val |= BIT(cti->trig_out_for_irq); | ||
| 137 | __raw_writel(val, base + CTIINTACK); | ||
| 138 | } | ||
| 139 | |||
| 140 | /** | ||
| 141 | * cti_unlock - unlock cti module | ||
| 142 | * @cti: cti instance | ||
| 143 | * | ||
| 144 | * unlock the cti module, or else any writes to the cti | ||
| 145 | * module is not allowed. | ||
| 146 | */ | ||
| 147 | static inline void cti_unlock(struct cti *cti) | ||
| 148 | { | ||
| 149 | void __iomem *base = cti->base; | ||
| 150 | unsigned long val; | ||
| 151 | |||
| 152 | val = __raw_readl(base + LOCKSTATUS); | ||
| 153 | |||
| 154 | if (val & 1) { | ||
| 155 | val = LOCKCODE; | ||
| 156 | __raw_writel(val, base + LOCKACCESS); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | /** | ||
| 161 | * cti_lock - lock cti module | ||
| 162 | * @cti: cti instance | ||
| 163 | * | ||
| 164 | * lock the cti module, so any writes to the cti | ||
| 165 | * module will be not allowed. | ||
| 166 | */ | ||
| 167 | static inline void cti_lock(struct cti *cti) | ||
| 168 | { | ||
| 169 | void __iomem *base = cti->base; | ||
| 170 | unsigned long val; | ||
| 171 | |||
| 172 | val = __raw_readl(base + LOCKSTATUS); | ||
| 173 | |||
| 174 | if (!(val & 1)) { | ||
| 175 | val = ~LOCKCODE; | ||
| 176 | __raw_writel(val, base + LOCKACCESS); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | #endif | ||
diff --git a/arch/arm/include/asm/edac.h b/arch/arm/include/asm/edac.h new file mode 100644 index 00000000000..0df7a2c1fc3 --- /dev/null +++ b/arch/arm/include/asm/edac.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2011 Calxeda, Inc. | ||
| 3 | * Based on PPC version Copyright 2007 MontaVista Software, Inc. | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms and conditions of the GNU General Public License, | ||
| 7 | * version 2, as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along with | ||
| 15 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | #ifndef ASM_EDAC_H | ||
| 18 | #define ASM_EDAC_H | ||
| 19 | /* | ||
| 20 | * ECC atomic, DMA, SMP and interrupt safe scrub function. | ||
| 21 | * Implements the per arch atomic_scrub() that EDAC use for software | ||
| 22 | * ECC scrubbing. It reads memory and then writes back the original | ||
| 23 | * value, allowing the hardware to detect and correct memory errors. | ||
| 24 | */ | ||
| 25 | static inline void atomic_scrub(void *va, u32 size) | ||
| 26 | { | ||
| 27 | #if __LINUX_ARM_ARCH__ >= 6 | ||
| 28 | unsigned int *virt_addr = va; | ||
| 29 | unsigned int temp, temp2; | ||
| 30 | unsigned int i; | ||
| 31 | |||
| 32 | for (i = 0; i < size / sizeof(*virt_addr); i++, virt_addr++) { | ||
| 33 | /* Very carefully read and write to memory atomically | ||
| 34 | * so we are interrupt, DMA and SMP safe. | ||
| 35 | */ | ||
| 36 | __asm__ __volatile__("\n" | ||
| 37 | "1: ldrex %0, [%2]\n" | ||
| 38 | " strex %1, %0, [%2]\n" | ||
| 39 | " teq %1, #0\n" | ||
| 40 | " bne 1b\n" | ||
| 41 | : "=&r"(temp), "=&r"(temp2) | ||
| 42 | : "r"(virt_addr) | ||
| 43 | : "cc"); | ||
| 44 | } | ||
| 45 | #endif | ||
| 46 | } | ||
| 47 | |||
| 48 | #endif | ||
diff --git a/arch/arm/include/asm/entry-macro-vic2.S b/arch/arm/include/asm/entry-macro-vic2.S deleted file mode 100644 index 3ceb85e4385..00000000000 --- a/arch/arm/include/asm/entry-macro-vic2.S +++ /dev/null | |||
| @@ -1,57 +0,0 @@ | |||
| 1 | /* arch/arm/include/asm/entry-macro-vic2.S | ||
| 2 | * | ||
| 3 | * Originally arch/arm/mach-s3c6400/include/mach/entry-macro.S | ||
| 4 | * | ||
| 5 | * Copyright 2008 Openmoko, Inc. | ||
| 6 | * Copyright 2008 Simtec Electronics | ||
| 7 | * http://armlinux.simtec.co.uk/ | ||
| 8 | * Ben Dooks <ben@simtec.co.uk> | ||
| 9 | * | ||
| 10 | * Low-level IRQ helper macros for a device with two VICs | ||
| 11 | * | ||
| 12 | * This file is licensed under the terms of the GNU General Public | ||
| 13 | * License version 2. This program is licensed "as is" without any | ||
| 14 | * warranty of any kind, whether express or implied. | ||
| 15 | */ | ||
| 16 | |||
| 17 | /* This should be included from <mach/entry-macro.S> with the necessary | ||
| 18 | * defines for virtual addresses and IRQ bases for the two vics. | ||
| 19 | * | ||
| 20 | * The code needs the following defined: | ||
| 21 | * IRQ_VIC0_BASE IRQ number of VIC0's first IRQ | ||
| 22 | * IRQ_VIC1_BASE IRQ number of VIC1's first IRQ | ||
| 23 | * VA_VIC0 Virtual address of VIC0 | ||
| 24 | * VA_VIC1 Virtual address of VIC1 | ||
| 25 | * | ||
| 26 | * Note, code assumes VIC0's virtual address is an ARM immediate constant | ||
| 27 | * away from VIC1. | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <asm/hardware/vic.h> | ||
| 31 | |||
| 32 | .macro disable_fiq | ||
| 33 | .endm | ||
| 34 | |||
| 35 | .macro get_irqnr_preamble, base, tmp | ||
| 36 | ldr \base, =VA_VIC0 | ||
| 37 | .endm | ||
| 38 | |||
| 39 | .macro arch_ret_to_user, tmp1, tmp2 | ||
| 40 | .endm | ||
| 41 | |||
| 42 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
| 43 | |||
| 44 | @ check the vic0 | ||
| 45 | mov \irqnr, #IRQ_VIC0_BASE + 31 | ||
| 46 | ldr \irqstat, [ \base, # VIC_IRQ_STATUS ] | ||
| 47 | teq \irqstat, #0 | ||
| 48 | |||
| 49 | @ otherwise try vic1 | ||
| 50 | addeq \tmp, \base, #(VA_VIC1 - VA_VIC0) | ||
| 51 | addeq \irqnr, \irqnr, #(IRQ_VIC1_BASE - IRQ_VIC0_BASE) | ||
| 52 | ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] | ||
| 53 | teqeq \irqstat, #0 | ||
| 54 | |||
| 55 | clzne \irqstat, \irqstat | ||
| 56 | subne \irqnr, \irqnr, \irqstat | ||
| 57 | .endm | ||
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 11ad0bfbb0a..7151753b098 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | #ifndef _ARCH_ARM_GPIO_H | 1 | #ifndef _ARCH_ARM_GPIO_H |
| 2 | #define _ARCH_ARM_GPIO_H | 2 | #define _ARCH_ARM_GPIO_H |
| 3 | 3 | ||
| 4 | #if CONFIG_ARCH_NR_GPIO > 0 | ||
| 5 | #define ARCH_NR_GPIO CONFIG_ARCH_NR_GPIO | ||
| 6 | #endif | ||
| 7 | |||
| 4 | /* not all ARM platforms necessarily support this API ... */ | 8 | /* not all ARM platforms necessarily support this API ... */ |
| 5 | #include <mach/gpio.h> | 9 | #include <mach/gpio.h> |
| 6 | 10 | ||
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index ddf07a92a6c..436e60b2cf7 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h | |||
| @@ -27,23 +27,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu); | |||
| 27 | 27 | ||
| 28 | #define arch_irq_stat_cpu smp_irq_stat_cpu | 28 | #define arch_irq_stat_cpu smp_irq_stat_cpu |
| 29 | 29 | ||
| 30 | #if NR_IRQS > 512 | ||
| 31 | #define HARDIRQ_BITS 10 | ||
| 32 | #elif NR_IRQS > 256 | ||
| 33 | #define HARDIRQ_BITS 9 | ||
| 34 | #else | ||
| 35 | #define HARDIRQ_BITS 8 | ||
| 36 | #endif | ||
| 37 | |||
| 38 | /* | ||
| 39 | * The hardirq mask has to be large enough to have space | ||
| 40 | * for potentially all IRQ sources in the system nesting | ||
| 41 | * on a single CPU: | ||
| 42 | */ | ||
| 43 | #if (1 << HARDIRQ_BITS) < NR_IRQS | ||
| 44 | # error HARDIRQ_BITS is too low! | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 | 30 | #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 |
| 48 | 31 | ||
| 49 | #endif /* __ASM_HARDIRQ_H */ | 32 | #endif /* __ASM_HARDIRQ_H */ |
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S deleted file mode 100644 index 74ebc803904..00000000000 --- a/arch/arm/include/asm/hardware/entry-macro-gic.S +++ /dev/null | |||
| @@ -1,60 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/include/asm/hardware/entry-macro-gic.S | ||
| 3 | * | ||
| 4 | * Low-level IRQ helper macros for GIC | ||
| 5 | * | ||
| 6 | * This file is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2. This program is licensed "as is" without any | ||
| 8 | * warranty of any kind, whether express or implied. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <asm/hardware/gic.h> | ||
| 12 | |||
| 13 | #ifndef HAVE_GET_IRQNR_PREAMBLE | ||
| 14 | .macro get_irqnr_preamble, base, tmp | ||
| 15 | ldr \base, =gic_cpu_base_addr | ||
| 16 | ldr \base, [\base] | ||
| 17 | .endm | ||
| 18 | #endif | ||
| 19 | |||
| 20 | /* | ||
| 21 | * The interrupt numbering scheme is defined in the | ||
| 22 | * interrupt controller spec. To wit: | ||
| 23 | * | ||
| 24 | * Interrupts 0-15 are IPI | ||
| 25 | * 16-31 are local. We allow 30 to be used for the watchdog. | ||
| 26 | * 32-1020 are global | ||
| 27 | * 1021-1022 are reserved | ||
| 28 | * 1023 is "spurious" (no interrupt) | ||
| 29 | * | ||
| 30 | * A simple read from the controller will tell us the number of the highest | ||
| 31 | * priority enabled interrupt. We then just need to check whether it is in the | ||
| 32 | * valid range for an IRQ (30-1020 inclusive). | ||
| 33 | */ | ||
| 34 | |||
| 35 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
| 36 | |||
| 37 | ldr \irqstat, [\base, #GIC_CPU_INTACK] | ||
| 38 | /* bits 12-10 = src CPU, 9-0 = int # */ | ||
| 39 | |||
| 40 | ldr \tmp, =1021 | ||
| 41 | bic \irqnr, \irqstat, #0x1c00 | ||
| 42 | cmp \irqnr, #15 | ||
| 43 | cmpcc \irqnr, \irqnr | ||
| 44 | cmpne \irqnr, \tmp | ||
| 45 | cmpcs \irqnr, \irqnr | ||
| 46 | .endm | ||
| 47 | |||
| 48 | /* We assume that irqstat (the raw value of the IRQ acknowledge | ||
| 49 | * register) is preserved from the macro above. | ||
| 50 | * If there is an IPI, we immediately signal end of interrupt on the | ||
| 51 | * controller, since this requires the original irqstat value which | ||
| 52 | * we won't easily be able to recreate later. | ||
| 53 | */ | ||
| 54 | |||
| 55 | .macro test_for_ipi, irqnr, irqstat, base, tmp | ||
| 56 | bic \irqnr, \irqstat, #0x1c00 | ||
| 57 | cmp \irqnr, #16 | ||
| 58 | strcc \irqstat, [\base, #GIC_CPU_EOI] | ||
| 59 | cmpcs \irqnr, \irqnr | ||
| 60 | .endm | ||
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 3e91f22046f..4bdfe001869 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h | |||
| @@ -36,30 +36,22 @@ | |||
| 36 | #include <linux/irqdomain.h> | 36 | #include <linux/irqdomain.h> |
| 37 | struct device_node; | 37 | struct device_node; |
| 38 | 38 | ||
| 39 | extern void __iomem *gic_cpu_base_addr; | ||
| 40 | extern struct irq_chip gic_arch_extn; | 39 | extern struct irq_chip gic_arch_extn; |
| 41 | 40 | ||
| 42 | void gic_init(unsigned int, int, void __iomem *, void __iomem *); | 41 | void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, |
| 42 | u32 offset); | ||
| 43 | int gic_of_init(struct device_node *node, struct device_node *parent); | 43 | int gic_of_init(struct device_node *node, struct device_node *parent); |
| 44 | void gic_secondary_init(unsigned int); | 44 | void gic_secondary_init(unsigned int); |
| 45 | void gic_handle_irq(struct pt_regs *regs); | ||
| 45 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); | 46 | void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); |
| 46 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); | 47 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); |
| 47 | 48 | ||
| 48 | struct gic_chip_data { | 49 | static inline void gic_init(unsigned int nr, int start, |
| 49 | void __iomem *dist_base; | 50 | void __iomem *dist , void __iomem *cpu) |
| 50 | void __iomem *cpu_base; | 51 | { |
| 51 | #ifdef CONFIG_CPU_PM | 52 | gic_init_bases(nr, start, dist, cpu, 0); |
| 52 | u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; | 53 | } |
| 53 | u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; | 54 | |
| 54 | u32 saved_spi_target[DIV_ROUND_UP(1020, 4)]; | ||
| 55 | u32 __percpu *saved_ppi_enable; | ||
| 56 | u32 __percpu *saved_ppi_conf; | ||
| 57 | #endif | ||
| 58 | #ifdef CONFIG_IRQ_DOMAIN | ||
| 59 | struct irq_domain domain; | ||
| 60 | #endif | ||
| 61 | unsigned int gic_irqs; | ||
| 62 | }; | ||
| 63 | #endif | 55 | #endif |
| 64 | 56 | ||
| 65 | #endif | 57 | #endif |
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/include/asm/hardware/iop3xx.h index 5daea2961d4..077c32326c6 100644 --- a/arch/arm/include/asm/hardware/iop3xx.h +++ b/arch/arm/include/asm/hardware/iop3xx.h | |||
| @@ -234,6 +234,7 @@ extern int iop3xx_get_init_atu(void); | |||
| 234 | void iop3xx_map_io(void); | 234 | void iop3xx_map_io(void); |
| 235 | void iop_init_cp6_handler(void); | 235 | void iop_init_cp6_handler(void); |
| 236 | void iop_init_time(unsigned long tickrate); | 236 | void iop_init_time(unsigned long tickrate); |
| 237 | void iop3xx_restart(char, const char *); | ||
| 237 | 238 | ||
| 238 | static inline u32 read_tmr0(void) | 239 | static inline u32 read_tmr0(void) |
| 239 | { | 240 | { |
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h index 5d72550a809..f42ebd61959 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/arch/arm/include/asm/hardware/vic.h | |||
| @@ -41,7 +41,15 @@ | |||
| 41 | #define VIC_PL192_VECT_ADDR 0xF00 | 41 | #define VIC_PL192_VECT_ADDR 0xF00 |
| 42 | 42 | ||
| 43 | #ifndef __ASSEMBLY__ | 43 | #ifndef __ASSEMBLY__ |
| 44 | #include <linux/compiler.h> | ||
| 45 | #include <linux/types.h> | ||
| 46 | |||
| 47 | struct device_node; | ||
| 48 | struct pt_regs; | ||
| 49 | |||
| 44 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); | 50 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); |
| 45 | #endif | 51 | int vic_of_init(struct device_node *node, struct device_node *parent); |
| 52 | void vic_handle_irq(struct pt_regs *regs); | ||
| 46 | 53 | ||
| 54 | #endif /* __ASSEMBLY__ */ | ||
| 47 | #endif | 55 | #endif |
diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h new file mode 100644 index 00000000000..bf863edb517 --- /dev/null +++ b/arch/arm/include/asm/idmap.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #ifndef __ASM_IDMAP_H | ||
| 2 | #define __ASM_IDMAP_H | ||
| 3 | |||
| 4 | #include <linux/compiler.h> | ||
| 5 | #include <asm/pgtable.h> | ||
| 6 | |||
| 7 | /* Tag a function as requiring to be executed via an identity mapping. */ | ||
| 8 | #define __idmap __section(.idmap.text) noinline notrace | ||
| 9 | |||
| 10 | extern pgd_t *idmap_pgd; | ||
| 11 | |||
| 12 | void setup_mm_for_reboot(void); | ||
| 13 | |||
| 14 | #endif /* __ASM_IDMAP_H */ | ||
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 2b0efc3104a..bcb0c883e21 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h | |||
| @@ -31,10 +31,10 @@ struct machine_desc { | |||
| 31 | unsigned int video_start; /* start of video RAM */ | 31 | unsigned int video_start; /* start of video RAM */ |
| 32 | unsigned int video_end; /* end of video RAM */ | 32 | unsigned int video_end; /* end of video RAM */ |
| 33 | 33 | ||
| 34 | unsigned int reserve_lp0 :1; /* never has lp0 */ | 34 | unsigned char reserve_lp0 :1; /* never has lp0 */ |
| 35 | unsigned int reserve_lp1 :1; /* never has lp1 */ | 35 | unsigned char reserve_lp1 :1; /* never has lp1 */ |
| 36 | unsigned int reserve_lp2 :1; /* never has lp2 */ | 36 | unsigned char reserve_lp2 :1; /* never has lp2 */ |
| 37 | unsigned int soft_reboot :1; /* soft reboot */ | 37 | char restart_mode; /* default restart mode */ |
| 38 | void (*fixup)(struct tag *, char **, | 38 | void (*fixup)(struct tag *, char **, |
| 39 | struct meminfo *); | 39 | struct meminfo *); |
| 40 | void (*reserve)(void);/* reserve mem blocks */ | 40 | void (*reserve)(void);/* reserve mem blocks */ |
| @@ -46,6 +46,7 @@ struct machine_desc { | |||
| 46 | #ifdef CONFIG_MULTI_IRQ_HANDLER | 46 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
| 47 | void (*handle_irq)(struct pt_regs *); | 47 | void (*handle_irq)(struct pt_regs *); |
| 48 | #endif | 48 | #endif |
| 49 | void (*restart)(char, const char *); | ||
| 49 | }; | 50 | }; |
| 50 | 51 | ||
| 51 | /* | 52 | /* |
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h new file mode 100644 index 00000000000..c0efdd60966 --- /dev/null +++ b/arch/arm/include/asm/opcodes.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/include/asm/opcodes.h | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef __ASM_ARM_OPCODES_H | ||
| 10 | #define __ASM_ARM_OPCODES_H | ||
| 11 | |||
| 12 | #ifndef __ASSEMBLY__ | ||
| 13 | extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); | ||
| 14 | #endif | ||
| 15 | |||
| 16 | #define ARM_OPCODE_CONDTEST_FAIL 0 | ||
| 17 | #define ARM_OPCODE_CONDTEST_PASS 1 | ||
| 18 | #define ARM_OPCODE_CONDTEST_UNCOND 2 | ||
| 19 | |||
| 20 | #endif /* __ASM_ARM_OPCODES_H */ | ||
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index ca94653f1ec..97b440c25c5 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h | |||
| @@ -151,7 +151,11 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from, | |||
| 151 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) | 151 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) |
| 152 | extern void copy_page(void *to, const void *from); | 152 | extern void copy_page(void *to, const void *from); |
| 153 | 153 | ||
| 154 | #ifdef CONFIG_ARM_LPAE | ||
| 155 | #include <asm/pgtable-3level-types.h> | ||
| 156 | #else | ||
| 154 | #include <asm/pgtable-2level-types.h> | 157 | #include <asm/pgtable-2level-types.h> |
| 158 | #endif | ||
| 155 | 159 | ||
| 156 | #endif /* CONFIG_MMU */ | 160 | #endif /* CONFIG_MMU */ |
| 157 | 161 | ||
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 0f8e3827a89..99cfe360798 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h | |||
| @@ -32,7 +32,4 @@ enum arm_perf_pmu_ids { | |||
| 32 | extern enum arm_perf_pmu_ids | 32 | extern enum arm_perf_pmu_ids |
| 33 | armpmu_get_pmu_id(void); | 33 | armpmu_get_pmu_id(void); |
| 34 | 34 | ||
| 35 | extern int | ||
| 36 | armpmu_get_max_events(void); | ||
| 37 | |||
| 38 | #endif /* __ARM_PERF_EVENT_H__ */ | 35 | #endif /* __ARM_PERF_EVENT_H__ */ |
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 3e08fd3fbb6..943504f53f5 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h | |||
| @@ -25,12 +25,34 @@ | |||
| 25 | #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) | 25 | #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) |
| 26 | #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) | 26 | #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) |
| 27 | 27 | ||
| 28 | #ifdef CONFIG_ARM_LPAE | ||
| 29 | |||
| 30 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
| 31 | { | ||
| 32 | return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); | ||
| 33 | } | ||
| 34 | |||
| 35 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
| 36 | { | ||
| 37 | BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); | ||
| 38 | free_page((unsigned long)pmd); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | ||
| 42 | { | ||
| 43 | set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); | ||
| 44 | } | ||
| 45 | |||
| 46 | #else /* !CONFIG_ARM_LPAE */ | ||
| 47 | |||
| 28 | /* | 48 | /* |
| 29 | * Since we have only two-level page tables, these are trivial | 49 | * Since we have only two-level page tables, these are trivial |
| 30 | */ | 50 | */ |
| 31 | #define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); }) | 51 | #define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); }) |
| 32 | #define pmd_free(mm, pmd) do { } while (0) | 52 | #define pmd_free(mm, pmd) do { } while (0) |
| 33 | #define pgd_populate(mm,pmd,pte) BUG() | 53 | #define pud_populate(mm,pmd,pte) BUG() |
| 54 | |||
| 55 | #endif /* CONFIG_ARM_LPAE */ | ||
| 34 | 56 | ||
| 35 | extern pgd_t *pgd_alloc(struct mm_struct *mm); | 57 | extern pgd_t *pgd_alloc(struct mm_struct *mm); |
| 36 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | 58 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); |
| @@ -109,7 +131,9 @@ static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, | |||
| 109 | { | 131 | { |
| 110 | pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot; | 132 | pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot; |
| 111 | pmdp[0] = __pmd(pmdval); | 133 | pmdp[0] = __pmd(pmdval); |
| 134 | #ifndef CONFIG_ARM_LPAE | ||
| 112 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); | 135 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); |
| 136 | #endif | ||
| 113 | flush_pmd_entry(pmdp); | 137 | flush_pmd_entry(pmdp); |
| 114 | } | 138 | } |
| 115 | 139 | ||
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index 470457e1cfc..2317a71c8f8 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h | |||
| @@ -140,4 +140,45 @@ | |||
| 140 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ | 140 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ |
| 141 | #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) | 141 | #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) |
| 142 | 142 | ||
| 143 | #ifndef __ASSEMBLY__ | ||
| 144 | |||
| 145 | /* | ||
| 146 | * The "pud_xxx()" functions here are trivial when the pmd is folded into | ||
| 147 | * the pud: the pud entry is never bad, always exists, and can't be set or | ||
| 148 | * cleared. | ||
| 149 | */ | ||
| 150 | #define pud_none(pud) (0) | ||
| 151 | #define pud_bad(pud) (0) | ||
| 152 | #define pud_present(pud) (1) | ||
| 153 | #define pud_clear(pudp) do { } while (0) | ||
| 154 | #define set_pud(pud,pudp) do { } while (0) | ||
| 155 | |||
| 156 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | ||
| 157 | { | ||
| 158 | return (pmd_t *)pud; | ||
| 159 | } | ||
| 160 | |||
| 161 | #define pmd_bad(pmd) (pmd_val(pmd) & 2) | ||
| 162 | |||
| 163 | #define copy_pmd(pmdpd,pmdps) \ | ||
| 164 | do { \ | ||
| 165 | pmdpd[0] = pmdps[0]; \ | ||
| 166 | pmdpd[1] = pmdps[1]; \ | ||
| 167 | flush_pmd_entry(pmdpd); \ | ||
| 168 | } while (0) | ||
| 169 | |||
| 170 | #define pmd_clear(pmdp) \ | ||
| 171 | do { \ | ||
| 172 | pmdp[0] = __pmd(0); \ | ||
| 173 | pmdp[1] = __pmd(0); \ | ||
| 174 | clean_pmd_entry(pmdp); \ | ||
| 175 | } while (0) | ||
| 176 | |||
| 177 | /* we don't need complex calculations here as the pmd is folded into the pgd */ | ||
| 178 | #define pmd_addr_end(addr,end) (end) | ||
| 179 | |||
| 180 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | ||
| 181 | |||
| 182 | #endif /* __ASSEMBLY__ */ | ||
| 183 | |||
| 143 | #endif /* _ASM_PGTABLE_2LEVEL_H */ | 184 | #endif /* _ASM_PGTABLE_2LEVEL_H */ |
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h new file mode 100644 index 00000000000..d7952824c5c --- /dev/null +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/include/asm/pgtable-3level-hwdef.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 ARM Ltd. | ||
| 5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | #ifndef _ASM_PGTABLE_3LEVEL_HWDEF_H | ||
| 21 | #define _ASM_PGTABLE_3LEVEL_HWDEF_H | ||
| 22 | |||
| 23 | /* | ||
| 24 | * Hardware page table definitions. | ||
| 25 | * | ||
| 26 | * + Level 1/2 descriptor | ||
| 27 | * - common | ||
| 28 | */ | ||
| 29 | #define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) | ||
| 30 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) | ||
| 31 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) | ||
| 32 | #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) | ||
| 33 | #define PMD_BIT4 (_AT(pmdval_t, 0)) | ||
| 34 | #define PMD_DOMAIN(x) (_AT(pmdval_t, 0)) | ||
| 35 | |||
| 36 | /* | ||
| 37 | * - section | ||
| 38 | */ | ||
| 39 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) | ||
| 40 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) | ||
| 41 | #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) | ||
| 42 | #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) | ||
| 43 | #define PMD_SECT_nG (_AT(pmdval_t, 1) << 11) | ||
| 44 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) | ||
| 45 | #define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0)) | ||
| 46 | #define PMD_SECT_AP_READ (_AT(pmdval_t, 0)) | ||
| 47 | #define PMD_SECT_TEX(x) (_AT(pmdval_t, 0)) | ||
| 48 | |||
| 49 | /* | ||
| 50 | * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||
| 51 | */ | ||
| 52 | #define PMD_SECT_UNCACHED (_AT(pmdval_t, 0) << 2) /* strongly ordered */ | ||
| 53 | #define PMD_SECT_BUFFERED (_AT(pmdval_t, 1) << 2) /* normal non-cacheable */ | ||
| 54 | #define PMD_SECT_WT (_AT(pmdval_t, 2) << 2) /* normal inner write-through */ | ||
| 55 | #define PMD_SECT_WB (_AT(pmdval_t, 3) << 2) /* normal inner write-back */ | ||
| 56 | #define PMD_SECT_WBWA (_AT(pmdval_t, 7) << 2) /* normal inner write-alloc */ | ||
| 57 | |||
| 58 | /* | ||
| 59 | * + Level 3 descriptor (PTE) | ||
| 60 | */ | ||
| 61 | #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) | ||
| 62 | #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) | ||
| 63 | #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) | ||
| 64 | #define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ | ||
| 65 | #define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ | ||
| 66 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | ||
| 67 | #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ | ||
| 68 | #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ | ||
| 69 | #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ | ||
| 70 | |||
| 71 | /* | ||
| 72 | * 40-bit physical address supported. | ||
| 73 | */ | ||
| 74 | #define PHYS_MASK_SHIFT (40) | ||
| 75 | #define PHYS_MASK ((1ULL << PHYS_MASK_SHIFT) - 1) | ||
| 76 | |||
| 77 | #endif | ||
diff --git a/arch/arm/include/asm/pgtable-3level-types.h b/arch/arm/include/asm/pgtable-3level-types.h new file mode 100644 index 00000000000..921aa30259c --- /dev/null +++ b/arch/arm/include/asm/pgtable-3level-types.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/include/asm/pgtable-3level-types.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 ARM Ltd. | ||
| 5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | #ifndef _ASM_PGTABLE_3LEVEL_TYPES_H | ||
| 21 | #define _ASM_PGTABLE_3LEVEL_TYPES_H | ||
| 22 | |||
| 23 | #include <asm/types.h> | ||
| 24 | |||
| 25 | typedef u64 pteval_t; | ||
| 26 | typedef u64 pmdval_t; | ||
| 27 | typedef u64 pgdval_t; | ||
| 28 | |||
| 29 | #undef STRICT_MM_TYPECHECKS | ||
| 30 | |||
| 31 | #ifdef STRICT_MM_TYPECHECKS | ||
| 32 | |||
| 33 | /* | ||
| 34 | * These are used to make use of C type-checking.. | ||
| 35 | */ | ||
| 36 | typedef struct { pteval_t pte; } pte_t; | ||
| 37 | typedef struct { pmdval_t pmd; } pmd_t; | ||
| 38 | typedef struct { pgdval_t pgd; } pgd_t; | ||
| 39 | typedef struct { pteval_t pgprot; } pgprot_t; | ||
| 40 | |||
| 41 | #define pte_val(x) ((x).pte) | ||
| 42 | #define pmd_val(x) ((x).pmd) | ||
| 43 | #define pgd_val(x) ((x).pgd) | ||
| 44 | #define pgprot_val(x) ((x).pgprot) | ||
| 45 | |||
| 46 | #define __pte(x) ((pte_t) { (x) } ) | ||
| 47 | #define __pmd(x) ((pmd_t) { (x) } ) | ||
| 48 | #define __pgd(x) ((pgd_t) { (x) } ) | ||
| 49 | #define __pgprot(x) ((pgprot_t) { (x) } ) | ||
| 50 | |||
| 51 | #else /* !STRICT_MM_TYPECHECKS */ | ||
| 52 | |||
| 53 | typedef pteval_t pte_t; | ||
| 54 | typedef pmdval_t pmd_t; | ||
| 55 | typedef pgdval_t pgd_t; | ||
| 56 | typedef pteval_t pgprot_t; | ||
| 57 | |||
| 58 | #define pte_val(x) (x) | ||
| 59 | #define pmd_val(x) (x) | ||
| 60 | #define pgd_val(x) (x) | ||
| 61 | #define pgprot_val(x) (x) | ||
| 62 | |||
| 63 | #define __pte(x) (x) | ||
| 64 | #define __pmd(x) (x) | ||
| 65 | #define __pgd(x) (x) | ||
| 66 | #define __pgprot(x) (x) | ||
| 67 | |||
| 68 | #endif /* STRICT_MM_TYPECHECKS */ | ||
| 69 | |||
| 70 | #endif /* _ASM_PGTABLE_3LEVEL_TYPES_H */ | ||
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h new file mode 100644 index 00000000000..759af70f9a0 --- /dev/null +++ b/arch/arm/include/asm/pgtable-3level.h | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/include/asm/pgtable-3level.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 ARM Ltd. | ||
| 5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | #ifndef _ASM_PGTABLE_3LEVEL_H | ||
| 21 | #define _ASM_PGTABLE_3LEVEL_H | ||
| 22 | |||
| 23 | /* | ||
| 24 | * With LPAE, there are 3 levels of page tables. Each level has 512 entries of | ||
| 25 | * 8 bytes each, occupying a 4K page. The first level table covers a range of | ||
| 26 | * 512GB, each entry representing 1GB. Since we are limited to 4GB input | ||
| 27 | * address range, only 4 entries in the PGD are used. | ||
| 28 | * | ||
| 29 | * There are enough spare bits in a page table entry for the kernel specific | ||
| 30 | * state. | ||
| 31 | */ | ||
| 32 | #define PTRS_PER_PTE 512 | ||
| 33 | #define PTRS_PER_PMD 512 | ||
| 34 | #define PTRS_PER_PGD 4 | ||
| 35 | |||
| 36 | #define PTE_HWTABLE_PTRS (PTRS_PER_PTE) | ||
| 37 | #define PTE_HWTABLE_OFF (0) | ||
| 38 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64)) | ||
| 39 | |||
| 40 | /* | ||
| 41 | * PGDIR_SHIFT determines the size a top-level page table entry can map. | ||
| 42 | */ | ||
| 43 | #define PGDIR_SHIFT 30 | ||
| 44 | |||
| 45 | /* | ||
| 46 | * PMD_SHIFT determines the size a middle-level page table entry can map. | ||
| 47 | */ | ||
| 48 | #define PMD_SHIFT 21 | ||
| 49 | |||
| 50 | #define PMD_SIZE (1UL << PMD_SHIFT) | ||
| 51 | #define PMD_MASK (~(PMD_SIZE-1)) | ||
| 52 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | ||
| 53 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
| 54 | |||
| 55 | /* | ||
| 56 | * section address mask and size definitions. | ||
| 57 | */ | ||
| 58 | #define SECTION_SHIFT 21 | ||
| 59 | #define SECTION_SIZE (1UL << SECTION_SHIFT) | ||
| 60 | #define SECTION_MASK (~(SECTION_SIZE-1)) | ||
| 61 | |||
| 62 | #define USER_PTRS_PER_PGD (PAGE_OFFSET / PGDIR_SIZE) | ||
| 63 | |||
| 64 | /* | ||
| 65 | * "Linux" PTE definitions for LPAE. | ||
| 66 | * | ||
| 67 | * These bits overlap with the hardware bits but the naming is preserved for | ||
| 68 | * consistency with the classic page table format. | ||
| 69 | */ | ||
| 70 | #define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Valid */ | ||
| 71 | #define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ | ||
| 72 | #define L_PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ | ||
| 73 | #define L_PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ | ||
| 74 | #define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ | ||
| 75 | #define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ | ||
| 76 | #define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | ||
| 77 | #define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ | ||
| 78 | #define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ | ||
| 79 | #define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */ | ||
| 80 | #define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ | ||
| 81 | |||
| 82 | /* | ||
| 83 | * To be used in assembly code with the upper page attributes. | ||
| 84 | */ | ||
| 85 | #define L_PTE_XN_HIGH (1 << (54 - 32)) | ||
| 86 | #define L_PTE_DIRTY_HIGH (1 << (55 - 32)) | ||
| 87 | |||
| 88 | /* | ||
| 89 | * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||
| 90 | */ | ||
| 91 | #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0) << 2) /* strongly ordered */ | ||
| 92 | #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ | ||
| 93 | #define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 2) << 2) /* normal inner write-through */ | ||
| 94 | #define L_PTE_MT_WRITEBACK (_AT(pteval_t, 3) << 2) /* normal inner write-back */ | ||
| 95 | #define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 7) << 2) /* normal inner write-alloc */ | ||
| 96 | #define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 4) << 2) /* device */ | ||
| 97 | #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 4) << 2) /* device */ | ||
| 98 | #define L_PTE_MT_DEV_WC (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ | ||
| 99 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 3) << 2) /* normal inner write-back */ | ||
| 100 | #define L_PTE_MT_MASK (_AT(pteval_t, 7) << 2) | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Software PGD flags. | ||
| 104 | */ | ||
| 105 | #define L_PGD_SWAPPER (_AT(pgdval_t, 1) << 55) /* swapper_pg_dir entry */ | ||
| 106 | |||
| 107 | #ifndef __ASSEMBLY__ | ||
| 108 | |||
| 109 | #define pud_none(pud) (!pud_val(pud)) | ||
| 110 | #define pud_bad(pud) (!(pud_val(pud) & 2)) | ||
| 111 | #define pud_present(pud) (pud_val(pud)) | ||
| 112 | |||
| 113 | #define pud_clear(pudp) \ | ||
| 114 | do { \ | ||
| 115 | *pudp = __pud(0); \ | ||
| 116 | clean_pmd_entry(pudp); \ | ||
| 117 | } while (0) | ||
| 118 | |||
| 119 | #define set_pud(pudp, pud) \ | ||
| 120 | do { \ | ||
| 121 | *pudp = pud; \ | ||
| 122 | flush_pmd_entry(pudp); \ | ||
| 123 | } while (0) | ||
| 124 | |||
| 125 | static inline pmd_t *pud_page_vaddr(pud_t pud) | ||
| 126 | { | ||
| 127 | return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); | ||
| 128 | } | ||
| 129 | |||
| 130 | /* Find an entry in the second-level page table.. */ | ||
| 131 | #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) | ||
| 132 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | ||
| 133 | { | ||
| 134 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); | ||
| 135 | } | ||
| 136 | |||
| 137 | #define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) | ||
| 138 | |||
| 139 | #define copy_pmd(pmdpd,pmdps) \ | ||
| 140 | do { \ | ||
| 141 | *pmdpd = *pmdps; \ | ||
| 142 | flush_pmd_entry(pmdpd); \ | ||
| 143 | } while (0) | ||
| 144 | |||
| 145 | #define pmd_clear(pmdp) \ | ||
| 146 | do { \ | ||
| 147 | *pmdp = __pmd(0); \ | ||
| 148 | clean_pmd_entry(pmdp); \ | ||
| 149 | } while (0) | ||
| 150 | |||
| 151 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,__pte(pte_val(pte)|(ext))) | ||
| 152 | |||
| 153 | #endif /* __ASSEMBLY__ */ | ||
| 154 | |||
| 155 | #endif /* _ASM_PGTABLE_3LEVEL_H */ | ||
diff --git a/arch/arm/include/asm/pgtable-hwdef.h b/arch/arm/include/asm/pgtable-hwdef.h index 183111164ce..8426229ba29 100644 --- a/arch/arm/include/asm/pgtable-hwdef.h +++ b/arch/arm/include/asm/pgtable-hwdef.h | |||
| @@ -10,6 +10,10 @@ | |||
| 10 | #ifndef _ASMARM_PGTABLE_HWDEF_H | 10 | #ifndef _ASMARM_PGTABLE_HWDEF_H |
| 11 | #define _ASMARM_PGTABLE_HWDEF_H | 11 | #define _ASMARM_PGTABLE_HWDEF_H |
| 12 | 12 | ||
| 13 | #ifdef CONFIG_ARM_LPAE | ||
| 14 | #include <asm/pgtable-3level-hwdef.h> | ||
| 15 | #else | ||
| 13 | #include <asm/pgtable-2level-hwdef.h> | 16 | #include <asm/pgtable-2level-hwdef.h> |
| 17 | #endif | ||
| 14 | 18 | ||
| 15 | #endif | 19 | #endif |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9451dce3a55..f66626d71e7 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
| @@ -11,20 +11,24 @@ | |||
| 11 | #define _ASMARM_PGTABLE_H | 11 | #define _ASMARM_PGTABLE_H |
| 12 | 12 | ||
| 13 | #include <linux/const.h> | 13 | #include <linux/const.h> |
| 14 | #include <asm-generic/4level-fixup.h> | ||
| 15 | #include <asm/proc-fns.h> | 14 | #include <asm/proc-fns.h> |
| 16 | 15 | ||
| 17 | #ifndef CONFIG_MMU | 16 | #ifndef CONFIG_MMU |
| 18 | 17 | ||
| 18 | #include <asm-generic/4level-fixup.h> | ||
| 19 | #include "pgtable-nommu.h" | 19 | #include "pgtable-nommu.h" |
| 20 | 20 | ||
| 21 | #else | 21 | #else |
| 22 | 22 | ||
| 23 | #include <asm-generic/pgtable-nopud.h> | ||
| 23 | #include <asm/memory.h> | 24 | #include <asm/memory.h> |
| 24 | #include <mach/vmalloc.h> | ||
| 25 | #include <asm/pgtable-hwdef.h> | 25 | #include <asm/pgtable-hwdef.h> |
| 26 | 26 | ||
| 27 | #ifdef CONFIG_ARM_LPAE | ||
| 28 | #include <asm/pgtable-3level.h> | ||
| 29 | #else | ||
| 27 | #include <asm/pgtable-2level.h> | 30 | #include <asm/pgtable-2level.h> |
| 31 | #endif | ||
| 28 | 32 | ||
| 29 | /* | 33 | /* |
| 30 | * Just any arbitrary offset to the start of the vmalloc VM area: the | 34 | * Just any arbitrary offset to the start of the vmalloc VM area: the |
| @@ -33,15 +37,10 @@ | |||
| 33 | * any out-of-bounds memory accesses will hopefully be caught. | 37 | * any out-of-bounds memory accesses will hopefully be caught. |
| 34 | * The vmalloc() routines leaves a hole of 4kB between each vmalloced | 38 | * The vmalloc() routines leaves a hole of 4kB between each vmalloced |
| 35 | * area for the same reason. ;) | 39 | * area for the same reason. ;) |
| 36 | * | ||
| 37 | * Note that platforms may override VMALLOC_START, but they must provide | ||
| 38 | * VMALLOC_END. VMALLOC_END defines the (exclusive) limit of this space, | ||
| 39 | * which may not overlap IO space. | ||
| 40 | */ | 40 | */ |
| 41 | #ifndef VMALLOC_START | ||
| 42 | #define VMALLOC_OFFSET (8*1024*1024) | 41 | #define VMALLOC_OFFSET (8*1024*1024) |
| 43 | #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) | 42 | #define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) |
| 44 | #endif | 43 | #define VMALLOC_END 0xff000000UL |
| 45 | 44 | ||
| 46 | #define LIBRARY_TEXT_START 0x0c000000 | 45 | #define LIBRARY_TEXT_START 0x0c000000 |
| 47 | 46 | ||
| @@ -163,39 +162,8 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
| 163 | /* to find an entry in a kernel page-table-directory */ | 162 | /* to find an entry in a kernel page-table-directory */ |
| 164 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) | 163 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) |
| 165 | 164 | ||
| 166 | /* | ||
| 167 | * The "pgd_xxx()" functions here are trivial for a folded two-level | ||
| 168 | * setup: the pgd is never bad, and a pmd always exists (as it's folded | ||
| 169 | * into the pgd entry) | ||
| 170 | */ | ||
| 171 | #define pgd_none(pgd) (0) | ||
| 172 | #define pgd_bad(pgd) (0) | ||
| 173 | #define pgd_present(pgd) (1) | ||
| 174 | #define pgd_clear(pgdp) do { } while (0) | ||
| 175 | #define set_pgd(pgd,pgdp) do { } while (0) | ||
| 176 | #define set_pud(pud,pudp) do { } while (0) | ||
| 177 | |||
| 178 | |||
| 179 | /* Find an entry in the second-level page table.. */ | ||
| 180 | #define pmd_offset(dir, addr) ((pmd_t *)(dir)) | ||
| 181 | |||
| 182 | #define pmd_none(pmd) (!pmd_val(pmd)) | 165 | #define pmd_none(pmd) (!pmd_val(pmd)) |
| 183 | #define pmd_present(pmd) (pmd_val(pmd)) | 166 | #define pmd_present(pmd) (pmd_val(pmd)) |
| 184 | #define pmd_bad(pmd) (pmd_val(pmd) & 2) | ||
| 185 | |||
| 186 | #define copy_pmd(pmdpd,pmdps) \ | ||
| 187 | do { \ | ||
| 188 | pmdpd[0] = pmdps[0]; \ | ||
| 189 | pmdpd[1] = pmdps[1]; \ | ||
| 190 | flush_pmd_entry(pmdpd); \ | ||
| 191 | } while (0) | ||
| 192 | |||
| 193 | #define pmd_clear(pmdp) \ | ||
| 194 | do { \ | ||
| 195 | pmdp[0] = __pmd(0); \ | ||
| 196 | pmdp[1] = __pmd(0); \ | ||
| 197 | clean_pmd_entry(pmdp); \ | ||
| 198 | } while (0) | ||
| 199 | 167 | ||
| 200 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) | 168 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) |
| 201 | { | 169 | { |
| @@ -204,10 +172,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
| 204 | 172 | ||
| 205 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | 173 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) |
| 206 | 174 | ||
| 207 | /* we don't need complex calculations here as the pmd is folded into the pgd */ | ||
| 208 | #define pmd_addr_end(addr,end) (end) | ||
| 209 | |||
| 210 | |||
| 211 | #ifndef CONFIG_HIGHPTE | 175 | #ifndef CONFIG_HIGHPTE |
| 212 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) | 176 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) |
| 213 | #define __pte_unmap(pte) do { } while (0) | 177 | #define __pte_unmap(pte) do { } while (0) |
| @@ -229,7 +193,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
| 229 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) | 193 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) |
| 230 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot) | 194 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot) |
| 231 | 195 | ||
| 232 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | ||
| 233 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | 196 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) |
| 234 | 197 | ||
| 235 | #if __LINUX_ARM_ARCH__ < 6 | 198 | #if __LINUX_ARM_ARCH__ < 6 |
| @@ -336,6 +299,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
| 336 | * We provide our own arch_get_unmapped_area to cope with VIPT caches. | 299 | * We provide our own arch_get_unmapped_area to cope with VIPT caches. |
| 337 | */ | 300 | */ |
| 338 | #define HAVE_ARCH_UNMAPPED_AREA | 301 | #define HAVE_ARCH_UNMAPPED_AREA |
| 302 | #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN | ||
| 339 | 303 | ||
| 340 | /* | 304 | /* |
| 341 | * remap a physical page `pfn' of size `size' with page protection `prot' | 305 | * remap a physical page `pfn' of size `size' with page protection `prot' |
| @@ -346,9 +310,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
| 346 | 310 | ||
| 347 | #define pgtable_cache_init() do { } while (0) | 311 | #define pgtable_cache_init() do { } while (0) |
| 348 | 312 | ||
| 349 | void identity_mapping_add(pgd_t *, unsigned long, unsigned long); | ||
| 350 | void identity_mapping_del(pgd_t *, unsigned long, unsigned long); | ||
| 351 | |||
| 352 | #endif /* !__ASSEMBLY__ */ | 313 | #endif /* !__ASSEMBLY__ */ |
| 353 | 314 | ||
| 354 | #endif /* CONFIG_MMU */ | 315 | #endif /* CONFIG_MMU */ |
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 0bda22c094a..b5a5be2536c 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h | |||
| @@ -27,13 +27,22 @@ enum arm_pmu_type { | |||
| 27 | /* | 27 | /* |
| 28 | * struct arm_pmu_platdata - ARM PMU platform data | 28 | * struct arm_pmu_platdata - ARM PMU platform data |
| 29 | * | 29 | * |
| 30 | * @handle_irq: an optional handler which will be called from the interrupt and | 30 | * @handle_irq: an optional handler which will be called from the |
| 31 | * passed the address of the low level handler, and can be used to implement | 31 | * interrupt and passed the address of the low level handler, |
| 32 | * any platform specific handling before or after calling it. | 32 | * and can be used to implement any platform specific handling |
| 33 | * before or after calling it. | ||
| 34 | * @enable_irq: an optional handler which will be called after | ||
| 35 | * request_irq and be used to handle some platform specific | ||
| 36 | * irq enablement | ||
| 37 | * @disable_irq: an optional handler which will be called before | ||
| 38 | * free_irq and be used to handle some platform specific | ||
| 39 | * irq disablement | ||
| 33 | */ | 40 | */ |
| 34 | struct arm_pmu_platdata { | 41 | struct arm_pmu_platdata { |
| 35 | irqreturn_t (*handle_irq)(int irq, void *dev, | 42 | irqreturn_t (*handle_irq)(int irq, void *dev, |
| 36 | irq_handler_t pmu_handler); | 43 | irq_handler_t pmu_handler); |
| 44 | void (*enable_irq)(int irq); | ||
| 45 | void (*disable_irq)(int irq); | ||
| 37 | }; | 46 | }; |
| 38 | 47 | ||
| 39 | #ifdef CONFIG_CPU_HAS_PMU | 48 | #ifdef CONFIG_CPU_HAS_PMU |
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 9e92cb205e6..f3628fb3d2b 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h | |||
| @@ -65,7 +65,11 @@ extern struct processor { | |||
| 65 | * Set a possibly extended PTE. Non-extended PTEs should | 65 | * Set a possibly extended PTE. Non-extended PTEs should |
| 66 | * ignore 'ext'. | 66 | * ignore 'ext'. |
| 67 | */ | 67 | */ |
| 68 | #ifdef CONFIG_ARM_LPAE | ||
| 69 | void (*set_pte_ext)(pte_t *ptep, pte_t pte); | ||
| 70 | #else | ||
| 68 | void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext); | 71 | void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext); |
| 72 | #endif | ||
| 69 | 73 | ||
| 70 | /* Suspend/resume */ | 74 | /* Suspend/resume */ |
| 71 | unsigned int suspend_size; | 75 | unsigned int suspend_size; |
| @@ -79,7 +83,11 @@ extern void cpu_proc_fin(void); | |||
| 79 | extern int cpu_do_idle(void); | 83 | extern int cpu_do_idle(void); |
| 80 | extern void cpu_dcache_clean_area(void *, int); | 84 | extern void cpu_dcache_clean_area(void *, int); |
| 81 | extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); | 85 | extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); |
| 86 | #ifdef CONFIG_ARM_LPAE | ||
| 87 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte); | ||
| 88 | #else | ||
| 82 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); | 89 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); |
| 90 | #endif | ||
| 83 | extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); | 91 | extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); |
| 84 | 92 | ||
| 85 | /* These three are private to arch/arm/kernel/suspend.c */ | 93 | /* These three are private to arch/arm/kernel/suspend.c */ |
| @@ -107,6 +115,18 @@ extern void cpu_resume(void); | |||
| 107 | 115 | ||
| 108 | #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) | 116 | #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) |
| 109 | 117 | ||
| 118 | #ifdef CONFIG_ARM_LPAE | ||
| 119 | #define cpu_get_pgd() \ | ||
| 120 | ({ \ | ||
| 121 | unsigned long pg, pg2; \ | ||
| 122 | __asm__("mrrc p15, 0, %0, %1, c2" \ | ||
| 123 | : "=r" (pg), "=r" (pg2) \ | ||
| 124 | : \ | ||
| 125 | : "cc"); \ | ||
| 126 | pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \ | ||
| 127 | (pgd_t *)phys_to_virt(pg); \ | ||
| 128 | }) | ||
| 129 | #else | ||
| 110 | #define cpu_get_pgd() \ | 130 | #define cpu_get_pgd() \ |
| 111 | ({ \ | 131 | ({ \ |
| 112 | unsigned long pg; \ | 132 | unsigned long pg; \ |
| @@ -115,6 +135,7 @@ extern void cpu_resume(void); | |||
| 115 | pg &= ~0x3fff; \ | 135 | pg &= ~0x3fff; \ |
| 116 | (pgd_t *)phys_to_virt(pg); \ | 136 | (pgd_t *)phys_to_virt(pg); \ |
| 117 | }) | 137 | }) |
| 138 | #endif | ||
| 118 | 139 | ||
| 119 | #endif | 140 | #endif |
| 120 | 141 | ||
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index b2d9df5667a..ce280b8d613 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h | |||
| @@ -123,6 +123,8 @@ static inline void prefetch(const void *ptr) | |||
| 123 | 123 | ||
| 124 | #endif | 124 | #endif |
| 125 | 125 | ||
| 126 | #define HAVE_ARCH_PICK_MMAP_LAYOUT | ||
| 127 | |||
| 126 | #endif | 128 | #endif |
| 127 | 129 | ||
| 128 | #endif /* __ASM_ARM_PROCESSOR_H */ | 130 | #endif /* __ASM_ARM_PROCESSOR_H */ |
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index c8e6ddf3e86..e3f75726343 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h | |||
| @@ -8,113 +8,7 @@ | |||
| 8 | #ifndef ASM_SCHED_CLOCK | 8 | #ifndef ASM_SCHED_CLOCK |
| 9 | #define ASM_SCHED_CLOCK | 9 | #define ASM_SCHED_CLOCK |
| 10 | 10 | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/types.h> | ||
| 13 | |||
| 14 | struct clock_data { | ||
| 15 | u64 epoch_ns; | ||
| 16 | u32 epoch_cyc; | ||
| 17 | u32 epoch_cyc_copy; | ||
| 18 | u32 mult; | ||
| 19 | u32 shift; | ||
| 20 | }; | ||
| 21 | |||
| 22 | #define DEFINE_CLOCK_DATA(name) struct clock_data name | ||
| 23 | |||
| 24 | static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift) | ||
| 25 | { | ||
| 26 | return (cyc * mult) >> shift; | ||
| 27 | } | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Atomically update the sched_clock epoch. Your update callback will | ||
| 31 | * be called from a timer before the counter wraps - read the current | ||
| 32 | * counter value, and call this function to safely move the epochs | ||
| 33 | * forward. Only use this from the update callback. | ||
| 34 | */ | ||
| 35 | static inline void update_sched_clock(struct clock_data *cd, u32 cyc, u32 mask) | ||
| 36 | { | ||
| 37 | unsigned long flags; | ||
| 38 | u64 ns = cd->epoch_ns + | ||
| 39 | cyc_to_ns((cyc - cd->epoch_cyc) & mask, cd->mult, cd->shift); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Write epoch_cyc and epoch_ns in a way that the update is | ||
| 43 | * detectable in cyc_to_fixed_sched_clock(). | ||
| 44 | */ | ||
| 45 | raw_local_irq_save(flags); | ||
| 46 | cd->epoch_cyc = cyc; | ||
| 47 | smp_wmb(); | ||
| 48 | cd->epoch_ns = ns; | ||
| 49 | smp_wmb(); | ||
| 50 | cd->epoch_cyc_copy = cyc; | ||
| 51 | raw_local_irq_restore(flags); | ||
| 52 | } | ||
| 53 | |||
| 54 | /* | ||
| 55 | * If your clock rate is known at compile time, using this will allow | ||
| 56 | * you to optimize the mult/shift loads away. This is paired with | ||
| 57 | * init_fixed_sched_clock() to ensure that your mult/shift are correct. | ||
| 58 | */ | ||
| 59 | static inline unsigned long long cyc_to_fixed_sched_clock(struct clock_data *cd, | ||
| 60 | u32 cyc, u32 mask, u32 mult, u32 shift) | ||
| 61 | { | ||
| 62 | u64 epoch_ns; | ||
| 63 | u32 epoch_cyc; | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Load the epoch_cyc and epoch_ns atomically. We do this by | ||
| 67 | * ensuring that we always write epoch_cyc, epoch_ns and | ||
| 68 | * epoch_cyc_copy in strict order, and read them in strict order. | ||
| 69 | * If epoch_cyc and epoch_cyc_copy are not equal, then we're in | ||
| 70 | * the middle of an update, and we should repeat the load. | ||
| 71 | */ | ||
| 72 | do { | ||
| 73 | epoch_cyc = cd->epoch_cyc; | ||
| 74 | smp_rmb(); | ||
| 75 | epoch_ns = cd->epoch_ns; | ||
| 76 | smp_rmb(); | ||
| 77 | } while (epoch_cyc != cd->epoch_cyc_copy); | ||
| 78 | |||
| 79 | return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, mult, shift); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Otherwise, you need to use this, which will obtain the mult/shift | ||
| 84 | * from the clock_data structure. Use init_sched_clock() with this. | ||
| 85 | */ | ||
| 86 | static inline unsigned long long cyc_to_sched_clock(struct clock_data *cd, | ||
| 87 | u32 cyc, u32 mask) | ||
| 88 | { | ||
| 89 | return cyc_to_fixed_sched_clock(cd, cyc, mask, cd->mult, cd->shift); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Initialize the clock data - calculate the appropriate multiplier | ||
| 94 | * and shift. Also setup a timer to ensure that the epoch is refreshed | ||
| 95 | * at the appropriate time interval, which will call your update | ||
| 96 | * handler. | ||
| 97 | */ | ||
| 98 | void init_sched_clock(struct clock_data *, void (*)(void), | ||
| 99 | unsigned int, unsigned long); | ||
| 100 | |||
| 101 | /* | ||
| 102 | * Use this initialization function rather than init_sched_clock() if | ||
| 103 | * you're using cyc_to_fixed_sched_clock, which will warn if your | ||
| 104 | * constants are incorrect. | ||
| 105 | */ | ||
| 106 | static inline void init_fixed_sched_clock(struct clock_data *cd, | ||
| 107 | void (*update)(void), unsigned int bits, unsigned long rate, | ||
| 108 | u32 mult, u32 shift) | ||
| 109 | { | ||
| 110 | init_sched_clock(cd, update, bits, rate); | ||
| 111 | if (cd->mult != mult || cd->shift != shift) { | ||
| 112 | pr_crit("sched_clock: wrong multiply/shift: %u>>%u vs calculated %u>>%u\n" | ||
| 113 | "sched_clock: fix multiply/shift to avoid scheduler hiccups\n", | ||
| 114 | mult, shift, cd->mult, cd->shift); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | extern void sched_clock_postinit(void); | 11 | extern void sched_clock_postinit(void); |
| 12 | extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); | ||
| 119 | 13 | ||
| 120 | #endif | 14 | #endif |
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index 915696dd9c7..23ebc0c82a3 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h | |||
| @@ -192,11 +192,7 @@ static const struct tagtable __tagtable_##fn __tag = { tag, fn } | |||
| 192 | /* | 192 | /* |
| 193 | * Memory map description | 193 | * Memory map description |
| 194 | */ | 194 | */ |
| 195 | #ifdef CONFIG_ARCH_EP93XX | 195 | #define NR_BANKS CONFIG_ARM_NR_BANKS |
| 196 | # define NR_BANKS 16 | ||
| 197 | #else | ||
| 198 | # define NR_BANKS 8 | ||
| 199 | #endif | ||
| 200 | 196 | ||
| 201 | struct membank { | 197 | struct membank { |
| 202 | phys_addr_t start; | 198 | phys_addr_t start; |
diff --git a/arch/arm/include/asm/swab.h b/arch/arm/include/asm/swab.h index 9997ad20eff..32ee164a2f6 100644 --- a/arch/arm/include/asm/swab.h +++ b/arch/arm/include/asm/swab.h | |||
| @@ -24,12 +24,13 @@ | |||
| 24 | 24 | ||
| 25 | #if defined(__KERNEL__) && __LINUX_ARM_ARCH__ >= 6 | 25 | #if defined(__KERNEL__) && __LINUX_ARM_ARCH__ >= 6 |
| 26 | 26 | ||
| 27 | static inline __attribute_const__ __u16 __arch_swab16(__u16 x) | 27 | static inline __attribute_const__ __u32 __arch_swahb32(__u32 x) |
| 28 | { | 28 | { |
| 29 | __asm__ ("rev16 %0, %1" : "=r" (x) : "r" (x)); | 29 | __asm__ ("rev16 %0, %1" : "=r" (x) : "r" (x)); |
| 30 | return x; | 30 | return x; |
| 31 | } | 31 | } |
| 32 | #define __arch_swab16 __arch_swab16 | 32 | #define __arch_swahb32 __arch_swahb32 |
| 33 | #define __arch_swab16(x) ((__u16)__arch_swahb32(x)) | ||
| 33 | 34 | ||
| 34 | static inline __attribute_const__ __u32 __arch_swab32(__u32 x) | 35 | static inline __attribute_const__ __u32 __arch_swab32(__u32 x) |
| 35 | { | 36 | { |
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 984014b9264..e4c96cc6ec0 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
| @@ -80,6 +80,14 @@ struct siginfo; | |||
| 80 | void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, | 80 | void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, |
| 81 | unsigned long err, unsigned long trap); | 81 | unsigned long err, unsigned long trap); |
| 82 | 82 | ||
| 83 | #ifdef CONFIG_ARM_LPAE | ||
| 84 | #define FAULT_CODE_ALIGNMENT 33 | ||
| 85 | #define FAULT_CODE_DEBUG 34 | ||
| 86 | #else | ||
| 87 | #define FAULT_CODE_ALIGNMENT 1 | ||
| 88 | #define FAULT_CODE_DEBUG 2 | ||
| 89 | #endif | ||
| 90 | |||
| 83 | void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, | 91 | void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, |
| 84 | struct pt_regs *), | 92 | struct pt_regs *), |
| 85 | int sig, int code, const char *name); | 93 | int sig, int code, const char *name); |
| @@ -100,7 +108,7 @@ extern void __show_regs(struct pt_regs *); | |||
| 100 | extern int __pure cpu_architecture(void); | 108 | extern int __pure cpu_architecture(void); |
| 101 | extern void cpu_init(void); | 109 | extern void cpu_init(void); |
| 102 | 110 | ||
| 103 | void arm_machine_restart(char mode, const char *cmd); | 111 | void soft_restart(unsigned long); |
| 104 | extern void (*arm_pm_restart)(char str, const char *cmd); | 112 | extern void (*arm_pm_restart)(char str, const char *cmd); |
| 105 | 113 | ||
| 106 | #define UDBG_UNDEFINED (1 << 0) | 114 | #define UDBG_UNDEFINED (1 << 0) |
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 265f908c4a6..5d3ed7e3856 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h | |||
| @@ -202,8 +202,18 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | |||
| 202 | tlb_remove_page(tlb, pte); | 202 | tlb_remove_page(tlb, pte); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, | ||
| 206 | unsigned long addr) | ||
| 207 | { | ||
| 208 | #ifdef CONFIG_ARM_LPAE | ||
| 209 | tlb_add_flush(tlb, addr); | ||
| 210 | tlb_remove_page(tlb, virt_to_page(pmdp)); | ||
| 211 | #endif | ||
| 212 | } | ||
| 213 | |||
| 205 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) | 214 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) |
| 206 | #define pmd_free_tlb(tlb, pmdp, addr) pmd_free((tlb)->mm, pmdp) | 215 | #define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) |
| 216 | #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) | ||
| 207 | 217 | ||
| 208 | #define tlb_migrate_finish(mm) do { } while (0) | 218 | #define tlb_migrate_finish(mm) do { } while (0) |
| 209 | 219 | ||
