Commit 0e51793e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.linaro.org/people/rmk/linux-arm

Pull ARM updates from Russell King:
 "This is the first chunk of ARM updates for this merge window.
  Conflicts are expected in two files - asm/timex.h and
  mach-integrator/integrator_cp.c.  Nothing particularly stands out more
  than anything else.

  Most of the growth is down to the opcodes stuff from Dave Martin,
  which is countered by Rob's patches to use more of the asm-generic
  headers on ARM."

(A few more conflicts grew since then, but it all looked fairly trivial)

* 'for-linus' of git://git.linaro.org/people/rmk/linux-arm: (44 commits)
  ARM: 7548/1: include linux/sched.h in syscall.h
  ARM: 7541/1: Add ARM ERRATA 775420 workaround
  ARM: ensure vm_struct has its phys_addr member filled in
  ARM: 7540/1: kexec: Check segment memory addresses
  ARM: 7539/1: kexec: scan for dtb magic in segments
  ARM: 7538/1: delay: add registration mechanism for delay timer sources
  ARM: 7536/1: smp: Formalize an IPI for wakeup
  ARM: 7525/1: ptrace: use updated syscall number for syscall auditing
  ARM: 7524/1: support syscall tracing
  ARM: 7519/1: integrator: convert platform devices to Device Tree
  ARM: 7518/1: integrator: convert AMBA devices to device tree
  ARM: 7517/1: integrator: initial device tree support
  ARM: 7516/1: plat-versatile: add DT support to FPGA IRQ
  ARM: 7515/1: integrator: check PL010 base address from resource
  ARM: 7514/1: integrator: call common init function from machine
  ARM: 7522/1: arch_timers: register a time/cycle counter
  ARM: 7523/1: arch_timers: enable the use of the virtual timer
  ARM: 7531/1: mark kernelmode mem{cpy,set} non-experimental
  ARM: 7520/1: Build dtb files in all target
  ARM: Fix build warning in arch/arm/mm/alignment.c
  ...
parents 5cad3598 b4874a3d
ARM Integrator/AP (Application Platform) and Integrator/CP (Compact Platform)
-----------------------------------------------------------------------------
ARM's oldest Linux-supported platform with connectors for different core
tiles of ARMv4, ARMv5 and ARMv6 type.
Required properties (in root node):
compatible = "arm,integrator-ap"; /* Application Platform */
compatible = "arm,integrator-cp"; /* Compact Platform */
FPGA type interrupt controllers, see the versatile-fpga-irq binding doc.
ARM Versatile Application and Platform Baseboards ARM Versatile Application and Platform Baseboards
------------------------------------------------- -------------------------------------------------
ARM's development hardware platform with connectors for customizable ARM's development hardware platform with connectors for customizable
......
* ARM Versatile FPGA interrupt controller
One or more FPGA IRQ controllers can be synthesized in an ARM reference board
such as the Integrator or Versatile family. The output of these different
controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
instance can handle up to 32 interrupts.
Required properties:
- compatible: "arm,versatile-fpga-irq"
- interrupt-controller: Identifies the node as an interrupt controller
- #interrupt-cells: The number of cells to define the interrupts. Must be 1
as the FPGA IRQ controller has no configuration options for interrupt
sources. The cell is a u32 and defines the interrupt number.
- reg: The register bank for the FPGA interrupt controller.
- clear-mask: a u32 number representing the mask written to clear all IRQs
on the controller at boot for example.
- valid-mask: a u32 number representing a bit mask determining which of
the interrupts are valid. Unconnected/unused lines are set to 0, and
the system till not make it possible for devices to request these
interrupts.
Example:
pic: pic@14000000 {
compatible = "arm,versatile-fpga-irq";
#interrupt-cells = <1>;
interrupt-controller;
reg = <0x14000000 0x100>;
clear-mask = <0xffffffff>;
valid-mask = <0x003fffff>;
};
...@@ -16,6 +16,7 @@ config ARM ...@@ -16,6 +16,7 @@ config ARM
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
select HAVE_ARCH_KGDB select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES if !XIP_KERNEL select HAVE_KPROBES if !XIP_KERNEL
select HAVE_KRETPROBES if (HAVE_KPROBES) select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
...@@ -1402,6 +1403,16 @@ config PL310_ERRATA_769419 ...@@ -1402,6 +1403,16 @@ config PL310_ERRATA_769419
on systems with an outer cache, the store buffer is drained on systems with an outer cache, the store buffer is drained
explicitly. explicitly.
config ARM_ERRATA_775420
bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
depends on CPU_V7
help
This option enables the workaround for the 775420 Cortex-A9 (r2p2,
r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance
operation aborts with MMU exception, it might cause the processor
to deadlock. This workaround puts DSB before executing ISB if
an abort may occur on cache maintenance.
endmenu endmenu
source "arch/arm/common/Kconfig" source "arch/arm/common/Kconfig"
...@@ -1786,8 +1797,8 @@ config ALIGNMENT_TRAP ...@@ -1786,8 +1797,8 @@ config ALIGNMENT_TRAP
configuration it is safe to say N, otherwise say Y. configuration it is safe to say N, otherwise say Y.
config UACCESS_WITH_MEMCPY config UACCESS_WITH_MEMCPY
bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user() (EXPERIMENTAL)" bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user()"
depends on MMU && EXPERIMENTAL depends on MMU
default y if CPU_FEROCEON default y if CPU_FEROCEON
help help
Implement faster copy_to_user and clear_user methods for CPU Implement faster copy_to_user and clear_user methods for CPU
...@@ -1828,12 +1839,6 @@ config CC_STACKPROTECTOR ...@@ -1828,12 +1839,6 @@ config CC_STACKPROTECTOR
neutralized via a kernel panic. neutralized via a kernel panic.
This feature requires gcc version 4.2 or above. This feature requires gcc version 4.2 or above.
config DEPRECATED_PARAM_STRUCT
bool "Provide old way to pass kernel parameters"
help
This was deprecated in 2001 and announced to live on for 5 years.
Some old boot loaders still use this way.
config XEN_DOM0 config XEN_DOM0
def_bool y def_bool y
depends on XEN depends on XEN
...@@ -1856,6 +1861,23 @@ config USE_OF ...@@ -1856,6 +1861,23 @@ config USE_OF
help help
Include support for flattened device tree machine descriptions. Include support for flattened device tree machine descriptions.
config ATAGS
bool "Support for the traditional ATAGS boot data passing" if USE_OF
default y
help
This is the traditional way of passing data to the kernel at boot
time. If you are solely relying on the flattened device tree (or
the ARM_ATAG_DTB_COMPAT option) then you may unselect this option
to remove ATAGS support from your kernel binary. If unsure,
leave this to y.
config DEPRECATED_PARAM_STRUCT
bool "Provide old way to pass kernel parameters"
depends on ATAGS
help
This was deprecated in 2001 and announced to live on for 5 years.
Some old boot loaders still use this way.
# Compressed boot loader in ROM. Yes, we really want to ask about # Compressed boot loader in ROM. Yes, we really want to ask about
# TEXT and BSS so we preserve their values in the config files. # TEXT and BSS so we preserve their values in the config files.
config ZBOOT_ROM_TEXT config ZBOOT_ROM_TEXT
...@@ -1982,6 +2004,7 @@ config CMDLINE ...@@ -1982,6 +2004,7 @@ config CMDLINE
choice choice
prompt "Kernel command line type" if CMDLINE != "" prompt "Kernel command line type" if CMDLINE != ""
default CMDLINE_FROM_BOOTLOADER default CMDLINE_FROM_BOOTLOADER
depends on ATAGS
config CMDLINE_FROM_BOOTLOADER config CMDLINE_FROM_BOOTLOADER
bool "Use bootloader kernel arguments if available" bool "Use bootloader kernel arguments if available"
...@@ -2051,7 +2074,7 @@ config KEXEC ...@@ -2051,7 +2074,7 @@ config KEXEC
config ATAGS_PROC config ATAGS_PROC
bool "Export atags in procfs" bool "Export atags in procfs"
depends on KEXEC depends on ATAGS && KEXEC
default y default y
help help
Should the atags used to boot the kernel be exported in an "atags" Should the atags used to boot the kernel be exported in an "atags"
......
...@@ -269,7 +269,12 @@ else ...@@ -269,7 +269,12 @@ else
KBUILD_IMAGE := zImage KBUILD_IMAGE := zImage
endif endif
all: $(KBUILD_IMAGE) # Build the DT binary blobs if we have OF configured
ifeq ($(CONFIG_USE_OF),y)
KBUILD_DTBS := dtbs
endif
all: $(KBUILD_IMAGE) $(KBUILD_DTBS)
boot := arch/arm/boot boot := arch/arm/boot
...@@ -307,7 +312,7 @@ define archhelp ...@@ -307,7 +312,7 @@ define archhelp
echo ' uImage - U-Boot wrapped zImage' echo ' uImage - U-Boot wrapped zImage'
echo ' bootpImage - Combined zImage and initial RAM disk' echo ' bootpImage - Combined zImage and initial RAM disk'
echo ' (supply initrd image via make variable INITRD=<path>)' echo ' (supply initrd image via make variable INITRD=<path>)'
echo ' dtbs - Build device tree blobs for enabled boards' echo '* dtbs - Build device tree blobs for enabled boards'
echo ' install - Install uncompressed kernel' echo ' install - Install uncompressed kernel'
echo ' zinstall - Install compressed kernel' echo ' zinstall - Install compressed kernel'
echo ' uinstall - Install U-Boot wrapped compressed kernel' echo ' uinstall - Install U-Boot wrapped compressed kernel'
......
...@@ -32,6 +32,9 @@ extern void error(char *); ...@@ -32,6 +32,9 @@ extern void error(char *);
# define Tracecv(c,x) # define Tracecv(c,x)
#endif #endif
/* Not needed, but used in some headers pulled in by decompressors */
extern char * strstr(const char * s1, const char *s2);
#ifdef CONFIG_KERNEL_GZIP #ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c" #include "../../../../lib/decompress_inflate.c"
#endif #endif
......
/*
* SoC core Device Tree for the ARM Integrator platforms
*/
/include/ "skeleton.dtsi"
/ {
timer@13000000 {
reg = <0x13000000 0x100>;
interrupt-parent = <&pic>;
interrupts = <5>;
};
timer@13000100 {
reg = <0x13000100 0x100>;
interrupt-parent = <&pic>;
interrupts = <6>;
};
timer@13000200 {
reg = <0x13000200 0x100>;
interrupt-parent = <&pic>;
interrupts = <7>;
};
pic@14000000 {
compatible = "arm,versatile-fpga-irq";
#interrupt-cells = <1>;
interrupt-controller;
reg = <0x14000000 0x100>;
clear-mask = <0xffffffff>;
};
flash@24000000 {
compatible = "cfi-flash";
reg = <0x24000000 0x02000000>;
};
fpga {
compatible = "arm,amba-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
interrupt-parent = <&pic>;
/*
* These PrimeCells are in the same locations and using the
* same interrupts in all Integrators, however the silicon
* version deployed is different.
*/
rtc@15000000 {
reg = <0x15000000 0x1000>;
interrupts = <8>;
};
uart@16000000 {
reg = <0x16000000 0x1000>;
interrupts = <1>;
};
uart@17000000 {
reg = <0x17000000 0x1000>;
interrupts = <2>;
};
kmi@18000000 {
reg = <0x18000000 0x1000>;
interrupts = <3>;
};
kmi@19000000 {
reg = <0x19000000 0x1000>;
interrupts = <4>;
};
};
};
/*
* Device Tree for the ARM Integrator/AP platform
*/
/dts-v1/;
/include/ "integrator.dtsi"
/ {
model = "ARM Integrator/AP";
compatible = "arm,integrator-ap";
aliases {
arm,timer-primary = &timer2;
arm,timer-secondary = &timer1;
};
chosen {
bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
};
timer0: timer@13000000 {
compatible = "arm,integrator-timer";
};
timer1: timer@13000100 {
compatible = "arm,integrator-timer";
};
timer2: timer@13000200 {
compatible = "arm,integrator-timer";
};
pic: pic@14000000 {
valid-mask = <0x003fffff>;
};
fpga {
/*
* The Integator/AP predates the idea to have magic numbers
* identifying the PrimeCell in hardware, thus we have to
* supply these from the device tree.
*/
rtc: rtc@15000000 {
compatible = "arm,pl030", "arm,primecell";
arm,primecell-periphid = <0x00041030>;
};
uart0: uart@16000000 {
compatible = "arm,pl010", "arm,primecell";
arm,primecell-periphid = <0x00041010>;
};
uart1: uart@17000000 {
compatible = "arm,pl010", "arm,primecell";
arm,primecell-periphid = <0x00041010>;
};
kmi0: kmi@18000000 {
compatible = "arm,pl050", "arm,primecell";
arm,primecell-periphid = <0x00041050>;
};
kmi1: kmi@19000000 {
compatible = "arm,pl050", "arm,primecell";
arm,primecell-periphid = <0x00041050>;
};
};
};
/*
* Device Tree for the ARM Integrator/CP platform
*/
/dts-v1/;
/include/ "integrator.dtsi"
/ {
model = "ARM Integrator/CP";
compatible = "arm,integrator-cp";
aliases {
arm,timer-primary = &timer2;
arm,timer-secondary = &timer1;
};
chosen {
bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
};
timer0: timer@13000000 {
compatible = "arm,sp804", "arm,primecell";
};
timer1: timer@13000100 {
compatible = "arm,sp804", "arm,primecell";
};
timer2: timer@13000200 {
compatible = "arm,sp804", "arm,primecell";
};
pic: pic@14000000 {
valid-mask = <0x1fc003ff>;
};
cic: cic@10000040 {
compatible = "arm,versatile-fpga-irq";
#interrupt-cells = <1>;
interrupt-controller;
reg = <0x10000040 0x100>;
clear-mask = <0xffffffff>;
valid-mask = <0x00000007>;
};
sic: sic@ca000000 {
compatible = "arm,versatile-fpga-irq";
#interrupt-cells = <1>;
interrupt-controller;
reg = <0xca000000 0x100>;
clear-mask = <0x00000fff>;
valid-mask = <0x00000fff>;
};
ethernet@c8000000 {
compatible = "smsc,lan91c111";
reg = <0xc8000000 0x10>;
interrupt-parent = <&pic>;
interrupts = <27>;
};
fpga {
/*
* These PrimeCells are at the same location and using
* the same interrupts in all Integrators, but in the CP
* slightly newer versions are deployed.
*/
rtc@15000000 {
compatible = "arm,pl031", "arm,primecell";
};
uart@16000000 {
compatible = "arm,pl011", "arm,primecell";
};
uart@17000000 {
compatible = "arm,pl011", "arm,primecell";
};
kmi@18000000 {
compatible = "arm,pl050", "arm,primecell";
};
kmi@19000000 {
compatible = "arm,pl050", "arm,primecell";
};
/*
* These PrimeCells are only available on the Integrator/CP
*/
mmc@1c000000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x1c000000 0x1000>;
interrupts = <23 24>;
max-frequency = <515633>;
};
aaci@1d000000 {
compatible = "arm,pl041", "arm,primecell";
reg = <0x1d000000 0x1000>;
interrupts = <25>;
};
clcd@c0000000 {
compatible = "arm,pl110", "arm,primecell";
reg = <0xC0000000 0x1000>;
interrupts = <22>;
};
};
};
...@@ -5,16 +5,33 @@ header-y += hwcap.h ...@@ -5,16 +5,33 @@ header-y += hwcap.h
generic-y += auxvec.h generic-y += auxvec.h
generic-y += bitsperlong.h generic-y += bitsperlong.h
generic-y += cputime.h generic-y += cputime.h
generic-y += current.h
generic-y += emergency-restart.h generic-y += emergency-restart.h
generic-y += errno.h generic-y += errno.h
generic-y += exec.h
generic-y += ioctl.h generic-y += ioctl.h
generic-y += ipcbuf.h
generic-y += irq_regs.h generic-y += irq_regs.h
generic-y += kdebug.h generic-y += kdebug.h
generic-y += local.h generic-y += local.h
generic-y += local64.h generic-y += local64.h
generic-y += msgbuf.h
generic-y += param.h
generic-y += parport.h
generic-y += percpu.h generic-y += percpu.h
generic-y += poll.h generic-y += poll.h
generic-y += resource.h generic-y += resource.h
generic-y += sections.h generic-y += sections.h
generic-y += segment.h
generic-y += sembuf.h
generic-y += serial.h
generic-y += shmbuf.h
generic-y += siginfo.h generic-y += siginfo.h
generic-y += sizes.h generic-y += sizes.h
generic-y += socket.h
generic-y += sockios.h
generic-y += termbits.h
generic-y += termios.h
generic-y += timex.h
generic-y += types.h
generic-y += unaligned.h
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
#define __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H
#include <asm/errno.h> #include <asm/errno.h>
#include <linux/clocksource.h>
#ifdef CONFIG_ARM_ARCH_TIMER #ifdef CONFIG_ARM_ARCH_TIMER
#define ARCH_HAS_READ_CURRENT_TIMER
int arch_timer_of_register(void); int arch_timer_of_register(void);
int arch_timer_sched_clock_init(void); int arch_timer_sched_clock_init(void);
struct timecounter *arch_timer_get_timecounter(void);
#else #else
static inline int arch_timer_of_register(void) static inline int arch_timer_of_register(void)
{ {
...@@ -17,6 +18,11 @@ static inline int arch_timer_sched_clock_init(void) ...@@ -17,6 +18,11 @@ static inline int arch_timer_sched_clock_init(void)
{ {
return -ENXIO; return -ENXIO;
} }
static inline struct timecounter *arch_timer_get_timecounter(void)
{
return NULL;
}
#endif #endif
#endif #endif
#ifndef _ASMARM_CURRENT_H
#define _ASMARM_CURRENT_H
#include <linux/thread_info.h>
static inline struct task_struct *get_current(void) __attribute_const__;
static inline struct task_struct *get_current(void)
{
return current_thread_info()->task;
}
#define current (get_current())
#endif /* _ASMARM_CURRENT_H */
...@@ -15,6 +15,11 @@ ...@@ -15,6 +15,11 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
struct delay_timer {
unsigned long (*read_current_timer)(void);
unsigned long freq;
};
extern struct arm_delay_ops { extern struct arm_delay_ops {
void (*delay)(unsigned long); void (*delay)(unsigned long);
void (*const_udelay)(unsigned long); void (*const_udelay)(unsigned long);
...@@ -56,6 +61,10 @@ extern void __loop_delay(unsigned long loops); ...@@ -56,6 +61,10 @@ extern void __loop_delay(unsigned long loops);
extern void __loop_udelay(unsigned long usecs); extern void __loop_udelay(unsigned long usecs);
extern void __loop_const_udelay(unsigned long); extern void __loop_const_udelay(unsigned long);
/* Delay-loop timer registration. */
#define ARCH_HAS_READ_CURRENT_TIMER
extern void register_current_timer_delay(const struct delay_timer *timer);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* defined(_ARM_DELAY_H) */ #endif /* defined(_ARM_DELAY_H) */
......
#ifndef __ASM_ARM_EXEC_H
#define __ASM_ARM_EXEC_H
#define arch_align_stack(x) (x)
#endif /* __ASM_ARM_EXEC_H */
...@@ -110,19 +110,19 @@ ...@@ -110,19 +110,19 @@
#endif #endif
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
//# ifdef _CACHE # ifdef _CACHE
# define MULTI_CACHE 1 # define MULTI_CACHE 1
//# else # else
//# define _CACHE v6 # define _CACHE v6
//# endif # endif
#endif #endif
#if defined(CONFIG_CPU_V7) #if defined(CONFIG_CPU_V7)
//# ifdef _CACHE # ifdef _CACHE
# define MULTI_CACHE 1 # define MULTI_CACHE 1
//# else # else
//# define _CACHE v7 # define _CACHE v7
//# endif # endif
#endif #endif
#if !defined(_CACHE) && !defined(MULTI_CACHE) #if !defined(_CACHE) && !defined(MULTI_CACHE)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/irq.h> #include <asm/irq.h>
#define NR_IPI 5 #define NR_IPI 6
typedef struct { typedef struct {
unsigned int __softirq_pending; unsigned int __softirq_pending;
......
/*
*
* Definitions for H3600 Handheld Computer
*
* Copyright 2001 Compaq Computer Corporation.
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
* FITNESS FOR ANY PARTICULAR PURPOSE.
*
* Author: Jamey Hicks.
*
*/
/* LinkUp Systems PCCard/CompactFlash Interface for SA-1100 */
/* PC Card Status Register */
#define LINKUP_PRS_S1 (1 << 0) /* voltage control bits S1-S4 */
#define LINKUP_PRS_S2 (1 << 1)
#define LINKUP_PRS_S3 (1 << 2)
#define LINKUP_PRS_S4 (1 << 3)
#define LINKUP_PRS_BVD1 (1 << 4)
#define LINKUP_PRS_BVD2 (1 << 5)
#define LINKUP_PRS_VS1 (1 << 6)
#define LINKUP_PRS_VS2 (1 << 7)
#define LINKUP_PRS_RDY (1 << 8)
#define LINKUP_PRS_CD1 (1 << 9)
#define LINKUP_PRS_CD2 (1 << 10)
/* PC Card Command Register */
#define LINKUP_PRC_S1 (1 << 0)
#define LINKUP_PRC_S2 (1 << 1)
#define LINKUP_PRC_S3 (1 << 2)
#define LINKUP_PRC_S4 (1 << 3)
#define LINKUP_PRC_RESET (1 << 4)
#define LINKUP_PRC_APOE (1 << 5) /* Auto Power Off Enable: clears S1-S4 when either nCD goes high */
#define LINKUP_PRC_CFE (1 << 6) /* CompactFlash mode Enable: addresses A[10:0] only, A[25:11] high */
#define LINKUP_PRC_SOE (1 << 7) /* signal output driver enable */
#define LINKUP_PRC_SSP (1 << 8) /* sock select polarity: 0 for socket 0, 1 for socket 1 */
#define LINKUP_PRC_MBZ (1 << 15) /* must be zero */
struct linkup_l1110 {
volatile short prc;
};
...@@ -47,13 +47,68 @@ extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen); ...@@ -47,13 +47,68 @@ extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen);
extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen); extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
#define __raw_writeb(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v))) #if __LINUX_ARM_ARCH__ < 6
/*
* Half-word accesses are problematic with RiscPC due to limitations of
* the bus. Rather than special-case the machine, just let the compiler
* generate the access for CPUs prior to ARMv6.
*/
#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
#define __raw_writew(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))) #define __raw_writew(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
#define __raw_writel(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))) #else
/*
* When running under a hypervisor, we want to avoid I/O accesses with
* writeback addressing modes as these incur a significant performance
* overhead (the address generation must be emulated in software).
*/
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
asm volatile("strh %1, %0"
: "+Qo" (*(volatile u16 __force *)addr)
: "r" (val));
}
#define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a)) static inline u16 __raw_readw(const volatile void __iomem *addr)
#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) {
#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a)) u16 val;
asm volatile("ldrh %1, %0"
: "+Qo" (*(volatile u16 __force *)addr),
"=r" (val));
return val;
}
#endif
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
asm volatile("strb %1, %0"
: "+Qo" (*(volatile u8 __force *)addr)
: "r" (val));
}
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
asm volatile("str %1, %0"
: "+Qo" (*(volatile u32 __force *)addr)
: "r" (val));
}
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
asm volatile("ldrb %1, %0"
: "+Qo" (*(volatile u8 __force *)addr),
"=r" (val));
return val;
}
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
asm volatile("ldr %1, %0"
: "+Qo" (*(volatile u32 __force *)addr),
"=r" (val));
return val;
}
/* /*
* Architecture ioremap implementation. * Architecture ioremap implementation.
......
#include <asm-generic/ipcbuf.h>
#ifndef _ASMARM_MSGBUF_H
#define _ASMARM_MSGBUF_H
/*
* The msqid64_ds structure for arm architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 64-bit time_t to solve y2038 problem
* - 2 miscellaneous 32-bit values
*/
struct msqid64_ds {
struct ipc64_perm msg_perm;
__kernel_time_t msg_stime; /* last msgsnd time */
unsigned long __unused1;
__kernel_time_t msg_rtime; /* last msgrcv time */
unsigned long __unused2;
__kernel_time_t msg_ctime; /* last change time */
unsigned long __unused3;
unsigned long msg_cbytes; /* current number of bytes on queue */
unsigned long msg_qnum; /* number of messages in queue */
unsigned long msg_qbytes; /* max number of bytes on queue */
__kernel_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_pid_t msg_lrpid; /* last receive pid */
unsigned long __unused4;
unsigned long __unused5;
};
#endif /* _ASMARM_MSGBUF_H */
...@@ -9,8 +9,13 @@ ...@@ -9,8 +9,13 @@
#define _ASM_MUTEX_H #define _ASM_MUTEX_H
/* /*
* On pre-ARMv6 hardware this results in a swp-based implementation, * On pre-ARMv6 hardware this results in a swp-based implementation,
* which is the most efficient. For ARMv6+, we emit a pair of exclusive * which is the most efficient. For ARMv6+, we have exclusive memory
* accesses instead. * accessors and use atomic_dec to avoid the extra xchg operations
* on the locking slowpaths.
*/ */
#if __LINUX_ARM_ARCH__ < 6
#include <asm-generic/mutex-xchg.h> #include <asm-generic/mutex-xchg.h>
#else
#include <asm-generic/mutex-dec.h>
#endif #endif
#endif /* _ASM_MUTEX_H */
/*
* opcodes-virt.h: Opcode definitions for the ARM virtualization extensions
* Copyright (C) 2012 Linaro Limited
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __ASM_ARM_OPCODES_VIRT_H
#define __ASM_ARM_OPCODES_VIRT_H
#include <asm/opcodes.h>
#define __HVC(imm16) __inst_arm_thumb32( \
0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F), \
0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF) \
)
#endif /* ! __ASM_ARM_OPCODES_VIRT_H */
...@@ -18,6 +18,33 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); ...@@ -18,6 +18,33 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
#define ARM_OPCODE_CONDTEST_UNCOND 2 #define ARM_OPCODE_CONDTEST_UNCOND 2
/*
* Assembler opcode byteswap helpers.
* These are only intended for use by this header: don't use them directly,
* because they will be suboptimal in most cases.
*/
#define ___asm_opcode_swab32(x) ( \
(((x) << 24) & 0xFF000000) \
| (((x) << 8) & 0x00FF0000) \
| (((x) >> 8) & 0x0000FF00) \
| (((x) >> 24) & 0x000000FF) \
)
#define ___asm_opcode_swab16(x) ( \
(((x) << 8) & 0xFF00) \
| (((x) >> 8) & 0x00FF) \
)
#define ___asm_opcode_swahb32(x) ( \
(((x) << 8) & 0xFF00FF00) \
| (((x) >> 8) & 0x00FF00FF) \
)
#define ___asm_opcode_swahw32(x) ( \
(((x) << 16) & 0xFFFF0000) \
| (((x) >> 16) & 0x0000FFFF) \
)
#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
/* /*
* Opcode byteswap helpers * Opcode byteswap helpers
* *
...@@ -41,39 +68,163 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); ...@@ -41,39 +68,163 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
* Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
* represent any valid Thumb-2 instruction. For this range, * represent any valid Thumb-2 instruction. For this range,
* __opcode_is_thumb32() and __opcode_is_thumb16() will both be false. * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
*
* The ___asm variants are intended only for use by this header, in situations
* involving inline assembler. For .S files, the normal __opcode_*() macros
* should do the right thing.
*/ */
#ifdef __ASSEMBLY__
#ifndef __ASSEMBLY__ #define ___opcode_swab32(x) ___asm_opcode_swab32(x)
#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
#else /* ! __ASSEMBLY__ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/swab.h> #include <linux/swab.h>
#define ___opcode_swab32(x) swab32(x)
#define ___opcode_swab16(x) swab16(x)
#define ___opcode_swahb32(x) swahb32(x)
#define ___opcode_swahw32(x) swahw32(x)
#define ___opcode_identity32(x) ((u32)(x))
#define ___opcode_identity16(x) ((u16)(x))
#endif /* ! __ASSEMBLY__ */
#ifdef CONFIG_CPU_ENDIAN_BE8 #ifdef CONFIG_CPU_ENDIAN_BE8
#define __opcode_to_mem_arm(x) swab32(x)
#define __opcode_to_mem_thumb16(x) swab16(x) #define __opcode_to_mem_arm(x) ___opcode_swab32(x)
#define __opcode_to_mem_thumb32(x) swahb32(x) #define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
#else #define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
#define __opcode_to_mem_arm(x) ((u32)(x)) #define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
#define __opcode_to_mem_thumb16(x) ((u16)(x)) #define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
#define __opcode_to_mem_thumb32(x) swahw32(x) #define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
#else /* ! CONFIG_CPU_ENDIAN_BE8 */
#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
#ifndef CONFIG_CPU_ENDIAN_BE32
/*
* On BE32 systems, using 32-bit accesses to store Thumb instructions will not
* work in all cases, due to alignment constraints. For now, a correct
* version is not provided for BE32.
*/
#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
#endif #endif
#endif /* ! CONFIG_CPU_ENDIAN_BE8 */
#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x) #define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x) #define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
#ifndef CONFIG_CPU_ENDIAN_BE32
#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x) #define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
#endif
/* Operations specific to Thumb opcodes */ /* Operations specific to Thumb opcodes */
/* Instruction size checks: */ /* Instruction size checks: */
#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL) #define __opcode_is_thumb32(x) ( \
#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL) ((x) & 0xF8000000) == 0xE8000000 \
|| ((x) & 0xF0000000) == 0xF0000000 \
)
#define __opcode_is_thumb16(x) ( \
((x) & 0xFFFF0000) == 0 \
&& !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000) \
)
/* Operations to construct or split 32-bit Thumb instructions: */ /* Operations to construct or split 32-bit Thumb instructions: */
#define __opcode_thumb32_first(x) ((u16)((x) >> 16)) #define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
#define __opcode_thumb32_second(x) ((u16)(x)) #define __opcode_thumb32_second(x) (___opcode_identity16(x))
#define __opcode_thumb32_compose(first, second) \ #define __opcode_thumb32_compose(first, second) ( \
(((u32)(u16)(first) << 16) | (u32)(u16)(second)) (___opcode_identity32(___opcode_identity16(first)) << 16) \
| ___opcode_identity32(___opcode_identity16(second)) \
)
#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
#define ___asm_opcode_thumb32_compose(first, second) ( \
(___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
| ___asm_opcode_identity32(___asm_opcode_identity16(second)) \
)
#endif /* __ASSEMBLY__ */ /*
* Opcode injection helpers
*
* In rare cases it is necessary to assemble an opcode which the
* assembler does not support directly, or which would normally be
* rejected because of the CFLAGS or AFLAGS used to build the affected
* file.
*
* Before using these macros, consider carefully whether it is feasible
* instead to change the build flags for your file, or whether it really
* makes sense to support old assembler versions when building that
* particular kernel feature.
*
* The macros defined here should only be used where there is no viable
* alternative.
*
*
* __inst_arm(x): emit the specified ARM opcode
* __inst_thumb16(x): emit the specified 16-bit Thumb opcode
* __inst_thumb32(x): emit the specified 32-bit Thumb opcode
*
* __inst_arm_thumb16(arm, thumb): emit either the specified arm or
* 16-bit Thumb opcode, depending on whether an ARM or Thumb-2
* kernel is being built
*
* __inst_arm_thumb32(arm, thumb): emit either the specified arm or
* 32-bit Thumb opcode, depending on whether an ARM or Thumb-2
* kernel is being built
*
*
* Note that using these macros directly is poor practice. Instead, you
* should use them to define human-readable wrapper macros to encode the
* instructions that you care about. In code which might run on ARMv7 or
* above, you can usually use the __inst_arm_thumb{16,32} macros to
* specify the ARM and Thumb alternatives at the same time. This ensures
* that the correct opcode gets emitted depending on the instruction set
* used for the kernel build.
*
* Look at opcodes-virt.h for an example of how to use these macros.
*/
#include <linux/stringify.h>
#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
#define __inst_thumb32(x) ___inst_thumb32( \
___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)), \
___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x)) \
)
#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
#ifdef CONFIG_THUMB2_KERNEL
#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
__inst_thumb16(thumb_opcode)
#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
__inst_thumb32(thumb_opcode)
#else
#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
#endif
/* Helpers for the helpers. Don't use these directly. */
#ifdef __ASSEMBLY__
#define ___inst_arm(x) .long x
#define ___inst_thumb16(x) .short x
#define ___inst_thumb32(first, second) .short first, second
#else
#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
#define ___inst_thumb32(first, second) \
".short " __stringify(first) ", " __stringify(second) "\n\t"
#endif
#endif /* __ASM_ARM_OPCODES_H */ #endif /* __ASM_ARM_OPCODES_H */
/*
* arch/arm/include/asm/param.h
*
* Copyright (C) 1995-1999 Russell King
*
* 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_PARAM_H
#define __ASM_PARAM_H
#ifdef __KERNEL__
# define HZ CONFIG_HZ /* Internal kernel timer frequency */
# define USER_HZ 100 /* User interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#else
# define HZ 100
#endif
#define EXEC_PAGESIZE 4096
#ifndef NOGROUP
#define NOGROUP (-1)
#endif
/* max length of hostname */
#define MAXHOSTNAMELEN 64
#endif
/*
* arch/arm/include/asm/parport.h: ARM-specific parport initialisation
*
* Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
*
* This file should only be included by drivers/parport/parport_pc.c.
*/
#ifndef __ASMARM_PARPORT_H
#define __ASMARM_PARPORT_H
static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
{
return parport_pc_find_isa_ports (autoirq, autodma);
}
#endif /* !(_ASMARM_PARPORT_H) */
#ifndef __ASM_ARM_SEGMENT_H
#define __ASM_ARM_SEGMENT_H
#define __KERNEL_CS 0x0
#define __KERNEL_DS 0x0
#define __USER_CS 0x1
#define __USER_DS 0x1
#endif /* __ASM_ARM_SEGMENT_H */
#ifndef _ASMARM_SEMBUF_H
#define _ASMARM_SEMBUF_H
/*
* The semid64_ds structure for arm architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 64-bit time_t to solve y2038 problem
* - 2 miscellaneous 32-bit values
*/
struct semid64_ds {
struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
__kernel_time_t sem_otime; /* last semop time */
unsigned long __unused1;
__kernel_time_t sem_ctime; /* last change time */
unsigned long __unused2;
unsigned long sem_nsems; /* no. of semaphores in array */
unsigned long __unused3;
unsigned long __unused4;
};
#endif /* _ASMARM_SEMBUF_H */
/*
* arch/arm/include/asm/serial.h
*
* Copyright (C) 1996 Russell King.
*
* 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.
*
* Changelog:
* 15-10-1996 RMK Created
*/
#ifndef __ASM_SERIAL_H
#define __ASM_SERIAL_H
#define BASE_BAUD (1843200 / 16)
#endif
#ifndef _ASMARM_SHMBUF_H
#define _ASMARM_SHMBUF_H
/*
* The shmid64_ds structure for arm architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* Pad space is left for:
* - 64-bit time_t to solve y2038 problem
* - 2 miscellaneous 32-bit values
*/
struct shmid64_ds {
struct ipc64_perm shm_perm; /* operation perms */
size_t shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
unsigned long __unused1;
__kernel_time_t shm_dtime; /* last detach time */
unsigned long __unused2;
__kernel_time_t shm_ctime; /* last change time */
unsigned long __unused3;
__kernel_pid_t shm_cpid; /* pid of creator */
__kernel_pid_t shm_lpid; /* pid of last operator */
unsigned long shm_nattch; /* no. of current attaches */
unsigned long __unused4;
unsigned long __unused5;
};
struct shminfo64 {
unsigned long shmmax;
unsigned long shmmin;
unsigned long shmmni;
unsigned long shmseg;
unsigned long shmall;
unsigned long __unused1;
unsigned long __unused2;
unsigned long __unused3;
unsigned long __unused4;
};
#endif /* _ASMARM_SHMBUF_H */
#ifndef _ASMARM_SOCKET_H
#define _ASMARM_SOCKET_H
#include <asm/sockios.h>
/* For setsockopt(2) */
#define SOL_SOCKET 1
#define SO_DEBUG 1
#define SO_REUSEADDR 2
#define SO_TYPE 3
#define SO_ERROR 4
#define SO_DONTROUTE 5
#define SO_BROADCAST 6
#define SO_SNDBUF 7
#define SO_RCVBUF 8
#define SO_SNDBUFFORCE 32
#define SO_RCVBUFFORCE 33
#define SO_KEEPALIVE 9
#define SO_OOBINLINE 10
#define SO_NO_CHECK 11
#define SO_PRIORITY 12
#define SO_LINGER 13
#define SO_BSDCOMPAT 14
/* To add :#define SO_REUSEPORT 15 */
#define SO_PASSCRED 16
#define SO_PEERCRED 17
#define SO_RCVLOWAT 18
#define SO_SNDLOWAT 19
#define SO_RCVTIMEO 20
#define SO_SNDTIMEO 21
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 22
#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
#define SO_SECURITY_ENCRYPTION_NETWORK 24
#define SO_BINDTODEVICE 25
/* Socket filtering */
#define SO_ATTACH_FILTER 26
#define SO_DETACH_FILTER 27
#define SO_PEERNAME 28
#define SO_TIMESTAMP 29
#define SCM_TIMESTAMP SO_TIMESTAMP
#define SO_ACCEPTCONN 30
#define SO_PEERSEC 31
#define SO_PASSSEC 34
#define SO_TIMESTAMPNS 35
#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
#define SO_MARK 36
#define SO_TIMESTAMPING 37
#define SCM_TIMESTAMPING SO_TIMESTAMPING
#define SO_PROTOCOL 38
#define SO_DOMAIN 39
#define SO_RXQ_OVFL 40
#define SO_WIFI_STATUS 41
#define SCM_WIFI_STATUS SO_WIFI_STATUS
#define SO_PEEK_OFF 42
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define SO_NOFCS 43
#endif /* _ASM_SOCKET_H */
#ifndef __ARCH_ARM_SOCKIOS_H
#define __ARCH_ARM_SOCKIOS_H
/* Socket-level I/O control calls. */
#define FIOSETOWN 0x8901
#define SIOCSPGRP 0x8902
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
#endif
...@@ -8,6 +8,11 @@ ...@@ -8,6 +8,11 @@
#define _ASM_ARM_SYSCALL_H #define _ASM_ARM_SYSCALL_H
#include <linux/err.h> #include <linux/err.h>
#include <linux/sched.h>
#include <asm/unistd.h>
#define NR_syscalls (__NR_syscalls)
extern const unsigned long sys_call_table[]; extern const unsigned long sys_call_table[];
......
#ifndef __ASM_ARM_TERMBITS_H
#define __ASM_ARM_TERMBITS_H
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 19
struct termios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
};
struct termios2 {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* c_iflag bits */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
#define OLCUC 0000002
#define ONLCR 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 0000100
#define OFDEL 0000200
#define NLDLY 0000400
#define NL0 0000000
#define NL1 0000400
#define CRDLY 0003000
#define CR0 0000000
#define CR1 0001000
#define CR2 0002000
#define CR3 0003000
#define TABDLY 0014000
#define TAB0 0000000
#define TAB1 0004000
#define TAB2 0010000
#define TAB3 0014000
#define XTABS 0014000
#define BSDLY 0020000
#define BS0 0000000
#define BS1 0020000
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0100000
#define FF0 0000000
#define FF1 0100000
/* c_cflag bit meaning */
#define CBAUD 0010017
#define B0 0000000 /* hang up */
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define PARENB 0000400
#define PARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
#define IBSHIFT 16
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* tcflow() and TCXONC use these */
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
/* tcflush() and TCFLSH use these */
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
/* tcsetattr uses these */
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
#endif /* __ASM_ARM_TERMBITS_H */
#ifndef __ASM_ARM_TERMIOS_H
#define __ASM_ARM_TERMIOS_H
#include <asm/termbits.h>
#include <asm/ioctls.h>
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
#define NCC 8
struct termio {
unsigned short c_iflag; /* input mode flags */
unsigned short c_oflag; /* output mode flags */
unsigned short c_cflag; /* control mode flags */
unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[NCC]; /* control characters */
};
#ifdef __KERNEL__
/* intr=^C quit=^| erase=del kill=^U
eof=^D vtime=\0 vmin=\1 sxtc=\0
start=^Q stop=^S susp=^Z eol=\0
reprint=^R discard=^U werase=^W lnext=^V
eol2=\0
*/
#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
#endif
/* modem lines */
#define TIOCM_LE 0x001
#define TIOCM_DTR 0x002
#define TIOCM_RTS 0x004
#define TIOCM_ST 0x008
#define TIOCM_SR 0x010
#define TIOCM_CTS 0x020
#define TIOCM_CAR 0x040
#define TIOCM_RNG 0x080
#define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG
#define TIOCM_OUT1 0x2000
#define TIOCM_OUT2 0x4000
#define TIOCM_LOOP 0x8000
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
#ifdef __KERNEL__
/*
* Translate a "termio" structure into a "termios". Ugh.
*/
#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
unsigned short __tmp; \
get_user(__tmp,&(termio)->x); \
*(unsigned short *) &(termios)->x = __tmp; \
}
#define user_termio_to_kernel_termios(termios, termio) \
({ \
SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
})
/*
* Translate a "termios" structure into a "termio". Ugh.
*/
#define kernel_termios_to_user_termio(termio, termios) \
({ \
put_user((termios)->c_iflag, &(termio)->c_iflag); \
put_user((termios)->c_oflag, &(termio)->c_oflag); \
put_user((termios)->c_cflag, &(termio)->c_cflag); \
put_user((termios)->c_lflag, &(termio)->c_lflag); \
put_user((termios)->c_line, &(termio)->c_line); \
copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
})
#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_TERMIOS_H */
...@@ -59,7 +59,9 @@ struct thread_info { ...@@ -59,7 +59,9 @@ struct thread_info {
__u32 syscall; /* syscall number */ __u32 syscall; /* syscall number */
__u8 used_cp[16]; /* thread used copro */ __u8 used_cp[16]; /* thread used copro */
unsigned long tp_value; unsigned long tp_value;
#ifdef CONFIG_CRUNCH
struct crunch_state crunchstate; struct crunch_state crunchstate;
#endif
union fp_state fpstate __attribute__((aligned(8))); union fp_state fpstate __attribute__((aligned(8)));
union vfp_state vfpstate; union vfp_state vfpstate;
#ifdef CONFIG_ARM_THUMBEE #ifdef CONFIG_ARM_THUMBEE
...@@ -148,6 +150,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, ...@@ -148,6 +150,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
#define TIF_SYSCALL_TRACE 8 #define TIF_SYSCALL_TRACE 8
#define TIF_SYSCALL_AUDIT 9 #define TIF_SYSCALL_AUDIT 9
#define TIF_SYSCALL_TRACEPOINT 10
#define TIF_POLLING_NRFLAG 16 #define TIF_POLLING_NRFLAG 16
#define TIF_USING_IWMMXT 17 #define TIF_USING_IWMMXT 17
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */ #define TIF_MEMDIE 18 /* is terminating due to OOM killer */
...@@ -160,12 +163,13 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *, ...@@ -160,12 +163,13 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_SECCOMP (1 << TIF_SECCOMP)
/* Checks for any syscall work in entry-common.S */ /* Checks for any syscall work in entry-common.S */
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT) #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
/* /*
* Change these and you break ASM code in entry-common.S * Change these and you break ASM code in entry-common.S
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#ifndef _ASMARM_TIMEX_H #ifndef _ASMARM_TIMEX_H
#define _ASMARM_TIMEX_H #define _ASMARM_TIMEX_H
#include <asm/arch_timer.h>
#ifdef CONFIG_ARCH_MULTIPLATFORM #ifdef CONFIG_ARCH_MULTIPLATFORM
#define CLOCK_TICK_RATE 1000000 #define CLOCK_TICK_RATE 1000000
#else #else
...@@ -20,11 +19,6 @@ ...@@ -20,11 +19,6 @@
#endif #endif
typedef unsigned long cycles_t; typedef unsigned long cycles_t;
#ifdef ARCH_HAS_READ_CURRENT_TIMER
#define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; }) #define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; })
#else
#define get_cycles() (0)
#endif
#endif #endif
#ifndef __ASM_ARM_TYPES_H
#define __ASM_ARM_TYPES_H
#include <asm-generic/int-ll64.h>
/*
* These aren't exported outside the kernel to avoid name space clashes
*/
#ifdef __KERNEL__
#define BITS_PER_LONG 32
#endif /* __KERNEL__ */
#endif
#ifndef _ASM_ARM_UNALIGNED_H
#define _ASM_ARM_UNALIGNED_H
#include <linux/unaligned/le_byteshift.h>
#include <linux/unaligned/be_byteshift.h>
#include <linux/unaligned/generic.h>
/*
* Select endianness
*/
#ifndef __ARMEB__
#define get_unaligned __get_unaligned_le
#define put_unaligned __put_unaligned_le
#else
#define get_unaligned __get_unaligned_be
#define put_unaligned __put_unaligned_be
#endif
#endif /* _ASM_ARM_UNALIGNED_H */
...@@ -406,6 +406,14 @@ ...@@ -406,6 +406,14 @@
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
/* 378 for kcmp */ /* 378 for kcmp */
/*
* This may need to be greater than __NR_last_syscall+1 in order to
* account for the padding in the syscall table
*/
#ifdef __KERNEL__
#define __NR_syscalls (380)
#endif /* __KERNEL__ */
/* /*
* The following SWIs are ARM private. * The following SWIs are ARM private.
*/ */
......
...@@ -19,7 +19,9 @@ obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \ ...@@ -19,7 +19,9 @@ obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \
process.o ptrace.o return_address.o sched_clock.o \ process.o ptrace.o return_address.o sched_clock.o \
setup.o signal.o stacktrace.o sys_arm.o time.o traps.o setup.o signal.o stacktrace.o sys_arm.o time.o traps.o
obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o obj-$(CONFIG_ATAGS) += atags_parse.o
obj-$(CONFIG_ATAGS_PROC) += atags_proc.o
obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += atags_compat.o
obj-$(CONFIG_OC_ETM) += etm.o obj-$(CONFIG_OC_ETM) += etm.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o
...@@ -51,7 +53,6 @@ test-kprobes-objs += kprobes-test-thumb.o ...@@ -51,7 +53,6 @@ test-kprobes-objs += kprobes-test-thumb.o
else else
test-kprobes-objs += kprobes-test-arm.o test-kprobes-objs += kprobes-test-arm.o
endif endif
obj-$(CONFIG_ATAGS_PROC) += atags.o
obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_KGDB) += kgdb.o
......
...@@ -21,18 +21,28 @@ ...@@ -21,18 +21,28 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm/cputype.h> #include <asm/cputype.h>
#include <asm/delay.h>
#include <asm/localtimer.h> #include <asm/localtimer.h>
#include <asm/arch_timer.h> #include <asm/arch_timer.h>
#include <asm/system_info.h> #include <asm/system_info.h>
#include <asm/sched_clock.h> #include <asm/sched_clock.h>
static unsigned long arch_timer_rate; static unsigned long arch_timer_rate;
static int arch_timer_ppi;
static int arch_timer_ppi2; enum ppi_nr {
PHYS_SECURE_PPI,
PHYS_NONSECURE_PPI,
VIRT_PPI,
HYP_PPI,
MAX_TIMER_PPI
};
static int arch_timer_ppi[MAX_TIMER_PPI];
static struct clock_event_device __percpu **arch_timer_evt; static struct clock_event_device __percpu **arch_timer_evt;
static struct delay_timer arch_delay_timer;
extern void init_current_timer_delay(unsigned long freq); static bool arch_timer_use_virtual = true;
/* /*
* Architected system timer support. * Architected system timer support.
...@@ -46,8 +56,17 @@ extern void init_current_timer_delay(unsigned long freq); ...@@ -46,8 +56,17 @@ extern void init_current_timer_delay(unsigned long freq);
#define ARCH_TIMER_REG_FREQ 1 #define ARCH_TIMER_REG_FREQ 1
#define ARCH_TIMER_REG_TVAL 2 #define ARCH_TIMER_REG_TVAL 2
static void arch_timer_reg_write(int reg, u32 val) #define ARCH_TIMER_PHYS_ACCESS 0
#define ARCH_TIMER_VIRT_ACCESS 1
/*
* These register accessors are marked inline so the compiler can
* nicely work out which register we want, and chuck away the rest of
* the code. At least it does so with a recent GCC (4.6.3).
*/
static inline void arch_timer_reg_write(const int access, const int reg, u32 val)
{ {
if (access == ARCH_TIMER_PHYS_ACCESS) {
switch (reg) { switch (reg) {
case ARCH_TIMER_REG_CTRL: case ARCH_TIMER_REG_CTRL:
asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
...@@ -56,40 +75,85 @@ static void arch_timer_reg_write(int reg, u32 val) ...@@ -56,40 +75,85 @@ static void arch_timer_reg_write(int reg, u32 val)
asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
break; break;
} }
}
if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
break;
case ARCH_TIMER_REG_TVAL:
asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
break;
}
}
isb(); isb();
} }
static u32 arch_timer_reg_read(int reg) static inline u32 arch_timer_reg_read(const int access, const int reg)
{ {
u32 val; u32 val = 0;
if (access == ARCH_TIMER_PHYS_ACCESS) {
switch (reg) { switch (reg) {
case ARCH_TIMER_REG_CTRL: case ARCH_TIMER_REG_CTRL:
asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
break; break;
case ARCH_TIMER_REG_TVAL:
asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
break;
case ARCH_TIMER_REG_FREQ: case ARCH_TIMER_REG_FREQ:
asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val)); asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
break; break;
}
}
if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
break;
case ARCH_TIMER_REG_TVAL: case ARCH_TIMER_REG_TVAL:
asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
break; break;
default: }
BUG();
} }
return val; return val;
} }
static irqreturn_t arch_timer_handler(int irq, void *dev_id) static inline cycle_t arch_timer_counter_read(const int access)
{ {
struct clock_event_device *evt = *(struct clock_event_device **)dev_id; cycle_t cval = 0;
unsigned long ctrl;
if (access == ARCH_TIMER_PHYS_ACCESS)
asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL); if (access == ARCH_TIMER_VIRT_ACCESS)
asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
return cval;
}
static inline cycle_t arch_counter_get_cntpct(void)
{
return arch_timer_counter_read(ARCH_TIMER_PHYS_ACCESS);
}
static inline cycle_t arch_counter_get_cntvct(void)
{
return arch_timer_counter_read(ARCH_TIMER_VIRT_ACCESS);
}
static irqreturn_t inline timer_handler(const int access,
struct clock_event_device *evt)
{
unsigned long ctrl;
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL);
if (ctrl & ARCH_TIMER_CTRL_IT_STAT) { if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
ctrl |= ARCH_TIMER_CTRL_IT_MASK; ctrl |= ARCH_TIMER_CTRL_IT_MASK;
arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl); arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl);
evt->event_handler(evt); evt->event_handler(evt);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -97,63 +161,100 @@ static irqreturn_t arch_timer_handler(int irq, void *dev_id) ...@@ -97,63 +161,100 @@ static irqreturn_t arch_timer_handler(int irq, void *dev_id)
return IRQ_NONE; return IRQ_NONE;
} }
static void arch_timer_disable(void) static irqreturn_t arch_timer_handler_virt(int irq, void *dev_id)
{ {
unsigned long ctrl; struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL); return timer_handler(ARCH_TIMER_VIRT_ACCESS, evt);
ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
} }
static void arch_timer_set_mode(enum clock_event_mode mode, static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id)
struct clock_event_device *clk)
{ {
struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt);
}
static inline void timer_set_mode(const int access, int mode)
{
unsigned long ctrl;
switch (mode) { switch (mode) {
case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_SHUTDOWN:
arch_timer_disable(); ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL);
ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl);
break; break;
default: default:
break; break;
} }
} }
static int arch_timer_set_next_event(unsigned long evt, static void arch_timer_set_mode_virt(enum clock_event_mode mode,
struct clock_event_device *unused) struct clock_event_device *clk)
{ {
unsigned long ctrl; timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode);
}
static void arch_timer_set_mode_phys(enum clock_event_mode mode,
struct clock_event_device *clk)
{
timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode);
}
ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL); static inline void set_next_event(const int access, unsigned long evt)
{
unsigned long ctrl;
ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL);
ctrl |= ARCH_TIMER_CTRL_ENABLE; ctrl |= ARCH_TIMER_CTRL_ENABLE;
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt);
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl);
}
arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt); static int arch_timer_set_next_event_virt(unsigned long evt,
arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl); struct clock_event_device *unused)
{
set_next_event(ARCH_TIMER_VIRT_ACCESS, evt);
return 0;
}
static int arch_timer_set_next_event_phys(unsigned long evt,
struct clock_event_device *unused)
{
set_next_event(ARCH_TIMER_PHYS_ACCESS, evt);
return 0; return 0;
} }
static int __cpuinit arch_timer_setup(struct clock_event_device *clk) static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
{ {
/* Be safe... */
arch_timer_disable();
clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP;
clk->name = "arch_sys_timer"; clk->name = "arch_sys_timer";
clk->rating = 450; clk->rating = 450;
clk->set_mode = arch_timer_set_mode; if (arch_timer_use_virtual) {
clk->set_next_event = arch_timer_set_next_event; clk->irq = arch_timer_ppi[VIRT_PPI];
clk->irq = arch_timer_ppi; clk->set_mode = arch_timer_set_mode_virt;
clk->set_next_event = arch_timer_set_next_event_virt;
} else {
clk->irq = arch_timer_ppi[PHYS_SECURE_PPI];
clk->set_mode = arch_timer_set_mode_phys;
clk->set_next_event = arch_timer_set_next_event_phys;
}
clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, NULL);
clockevents_config_and_register(clk, arch_timer_rate, clockevents_config_and_register(clk, arch_timer_rate,
0xf, 0x7fffffff); 0xf, 0x7fffffff);
*__this_cpu_ptr(arch_timer_evt) = clk; *__this_cpu_ptr(arch_timer_evt) = clk;
enable_percpu_irq(clk->irq, 0); if (arch_timer_use_virtual)
if (arch_timer_ppi2) enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0);
enable_percpu_irq(arch_timer_ppi2, 0); else {
enable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], 0);
if (arch_timer_ppi[PHYS_NONSECURE_PPI])
enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
}
return 0; return 0;
} }
...@@ -173,8 +274,8 @@ static int arch_timer_available(void) ...@@ -173,8 +274,8 @@ static int arch_timer_available(void)
return -ENXIO; return -ENXIO;
if (arch_timer_rate == 0) { if (arch_timer_rate == 0) {
arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0); freq = arch_timer_reg_read(ARCH_TIMER_PHYS_ACCESS,
freq = arch_timer_reg_read(ARCH_TIMER_REG_FREQ); ARCH_TIMER_REG_FREQ);
/* Check the timer frequency. */ /* Check the timer frequency. */
if (freq == 0) { if (freq == 0) {
...@@ -185,52 +286,57 @@ static int arch_timer_available(void) ...@@ -185,52 +286,57 @@ static int arch_timer_available(void)
arch_timer_rate = freq; arch_timer_rate = freq;
} }
pr_info_once("Architected local timer running at %lu.%02luMHz.\n", pr_info_once("Architected local timer running at %lu.%02luMHz (%s).\n",
arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100); arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100,
arch_timer_use_virtual ? "virt" : "phys");
return 0; return 0;
} }
static inline cycle_t arch_counter_get_cntpct(void) static u32 notrace arch_counter_get_cntpct32(void)
{ {
u32 cvall, cvalh; cycle_t cnt = arch_counter_get_cntpct();
asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh)); /*
* The sched_clock infrastructure only knows about counters
return ((cycle_t) cvalh << 32) | cvall; * with at most 32bits. Forget about the upper 24 bits for the
} * time being...
*/
static inline cycle_t arch_counter_get_cntvct(void) return (u32)cnt;
{
u32 cvall, cvalh;
asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
return ((cycle_t) cvalh << 32) | cvall;
} }
static u32 notrace arch_counter_get_cntvct32(void) static u32 notrace arch_counter_get_cntvct32(void)
{ {
cycle_t cntvct = arch_counter_get_cntvct(); cycle_t cnt = arch_counter_get_cntvct();
/* /*
* The sched_clock infrastructure only knows about counters * The sched_clock infrastructure only knows about counters
* with at most 32bits. Forget about the upper 24 bits for the * with at most 32bits. Forget about the upper 24 bits for the
* time being... * time being...
*/ */
return (u32)(cntvct & (u32)~0); return (u32)cnt;
} }
static cycle_t arch_counter_read(struct clocksource *cs) static cycle_t arch_counter_read(struct clocksource *cs)
{ {
/*
* Always use the physical counter for the clocksource.
* CNTHCTL.PL1PCTEN must be set to 1.
*/
return arch_counter_get_cntpct(); return arch_counter_get_cntpct();
} }
int read_current_timer(unsigned long *timer_val) static unsigned long arch_timer_read_current_timer(void)
{ {
if (!arch_timer_rate) return arch_counter_get_cntpct();
return -ENXIO; }
*timer_val = arch_counter_get_cntpct();
return 0; static cycle_t arch_counter_read_cc(const struct cyclecounter *cc)
{
/*
* Always use the physical counter for the clocksource.
* CNTHCTL.PL1PCTEN must be set to 1.
*/
return arch_counter_get_cntpct();
} }
static struct clocksource clocksource_counter = { static struct clocksource clocksource_counter = {
...@@ -241,14 +347,32 @@ static struct clocksource clocksource_counter = { ...@@ -241,14 +347,32 @@ static struct clocksource clocksource_counter = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS, .flags = CLOCK_SOURCE_IS_CONTINUOUS,
}; };
static struct cyclecounter cyclecounter = {
.read = arch_counter_read_cc,
.mask = CLOCKSOURCE_MASK(56),
};
static struct timecounter timecounter;
struct timecounter *arch_timer_get_timecounter(void)
{
return &timecounter;
}
static void __cpuinit arch_timer_stop(struct clock_event_device *clk) static void __cpuinit arch_timer_stop(struct clock_event_device *clk)
{ {
pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
clk->irq, smp_processor_id()); clk->irq, smp_processor_id());
disable_percpu_irq(clk->irq);
if (arch_timer_ppi2) if (arch_timer_use_virtual)
disable_percpu_irq(arch_timer_ppi2); disable_percpu_irq(arch_timer_ppi[VIRT_PPI]);
arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk); else {
disable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI]);
if (arch_timer_ppi[PHYS_NONSECURE_PPI])
disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]);
}
clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk);
} }
static struct local_timer_ops arch_timer_ops __cpuinitdata = { static struct local_timer_ops arch_timer_ops __cpuinitdata = {
...@@ -261,34 +385,46 @@ static struct clock_event_device arch_timer_global_evt; ...@@ -261,34 +385,46 @@ static struct clock_event_device arch_timer_global_evt;
static int __init arch_timer_register(void) static int __init arch_timer_register(void)
{ {
int err; int err;
int ppi;
err = arch_timer_available(); err = arch_timer_available();
if (err) if (err)
return err; goto out;
arch_timer_evt = alloc_percpu(struct clock_event_device *); arch_timer_evt = alloc_percpu(struct clock_event_device *);
if (!arch_timer_evt) if (!arch_timer_evt) {
return -ENOMEM; err = -ENOMEM;
goto out;
}
clocksource_register_hz(&clocksource_counter, arch_timer_rate); clocksource_register_hz(&clocksource_counter, arch_timer_rate);
cyclecounter.mult = clocksource_counter.mult;
err = request_percpu_irq(arch_timer_ppi, arch_timer_handler, cyclecounter.shift = clocksource_counter.shift;
timecounter_init(&timecounter, &cyclecounter,
arch_counter_get_cntpct());
if (arch_timer_use_virtual) {
ppi = arch_timer_ppi[VIRT_PPI];
err = request_percpu_irq(ppi, arch_timer_handler_virt,
"arch_timer", arch_timer_evt); "arch_timer", arch_timer_evt);
if (err) { } else {
pr_err("arch_timer: can't register interrupt %d (%d)\n", ppi = arch_timer_ppi[PHYS_SECURE_PPI];
arch_timer_ppi, err); err = request_percpu_irq(ppi, arch_timer_handler_phys,
goto out_free; "arch_timer", arch_timer_evt);
if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) {
ppi = arch_timer_ppi[PHYS_NONSECURE_PPI];
err = request_percpu_irq(ppi, arch_timer_handler_phys,
"arch_timer", arch_timer_evt);
if (err)
free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI],
arch_timer_evt);
}
} }
if (arch_timer_ppi2) {
err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,
"arch_timer", arch_timer_evt);
if (err) { if (err) {
pr_err("arch_timer: can't register interrupt %d (%d)\n", pr_err("arch_timer: can't register interrupt %d (%d)\n",
arch_timer_ppi2, err); ppi, err);
arch_timer_ppi2 = 0; goto out_free;
goto out_free_irq;
}
} }
err = local_timer_register(&arch_timer_ops); err = local_timer_register(&arch_timer_ops);
...@@ -302,21 +438,29 @@ static int __init arch_timer_register(void) ...@@ -302,21 +438,29 @@ static int __init arch_timer_register(void)
arch_timer_global_evt.cpumask = cpumask_of(0); arch_timer_global_evt.cpumask = cpumask_of(0);
err = arch_timer_setup(&arch_timer_global_evt); err = arch_timer_setup(&arch_timer_global_evt);
} }
if (err) if (err)
goto out_free_irq; goto out_free_irq;
init_current_timer_delay(arch_timer_rate); /* Use the architected timer for the delay loop. */
arch_delay_timer.read_current_timer = &arch_timer_read_current_timer;
arch_delay_timer.freq = arch_timer_rate;
register_current_timer_delay(&arch_delay_timer);
return 0; return 0;
out_free_irq: out_free_irq:
free_percpu_irq(arch_timer_ppi, arch_timer_evt); if (arch_timer_use_virtual)
if (arch_timer_ppi2) free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt);
free_percpu_irq(arch_timer_ppi2, arch_timer_evt); else {
free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI],
arch_timer_evt);
if (arch_timer_ppi[PHYS_NONSECURE_PPI])
free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI],
arch_timer_evt);
}
out_free: out_free:
free_percpu(arch_timer_evt); free_percpu(arch_timer_evt);
out:
return err; return err;
} }
...@@ -329,6 +473,7 @@ int __init arch_timer_of_register(void) ...@@ -329,6 +473,7 @@ int __init arch_timer_of_register(void)
{ {
struct device_node *np; struct device_node *np;
u32 freq; u32 freq;
int i;
np = of_find_matching_node(NULL, arch_timer_of_match); np = of_find_matching_node(NULL, arch_timer_of_match);
if (!np) { if (!np) {
...@@ -340,22 +485,40 @@ int __init arch_timer_of_register(void) ...@@ -340,22 +485,40 @@ int __init arch_timer_of_register(void)
if (!of_property_read_u32(np, "clock-frequency", &freq)) if (!of_property_read_u32(np, "clock-frequency", &freq))
arch_timer_rate = freq; arch_timer_rate = freq;
arch_timer_ppi = irq_of_parse_and_map(np, 0); for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
arch_timer_ppi2 = irq_of_parse_and_map(np, 1); arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
pr_info("arch_timer: found %s irqs %d %d\n",
np->name, arch_timer_ppi, arch_timer_ppi2); /*
* If no interrupt provided for virtual timer, we'll have to
* stick to the physical timer. It'd better be accessible...
*/
if (!arch_timer_ppi[VIRT_PPI]) {
arch_timer_use_virtual = false;
if (!arch_timer_ppi[PHYS_SECURE_PPI] ||
!arch_timer_ppi[PHYS_NONSECURE_PPI]) {
pr_warn("arch_timer: No interrupt available, giving up\n");
return -EINVAL;
}
}
return arch_timer_register(); return arch_timer_register();
} }
int __init arch_timer_sched_clock_init(void) int __init arch_timer_sched_clock_init(void)
{ {
u32 (*cnt32)(void);
int err; int err;
err = arch_timer_available(); err = arch_timer_available();
if (err) if (err)
return err; return err;
setup_sched_clock(arch_counter_get_cntvct32, 32, arch_timer_rate); if (arch_timer_use_virtual)
cnt32 = arch_counter_get_cntvct32;
else
cnt32 = arch_counter_get_cntpct32;
setup_sched_clock(cnt32, 32, arch_timer_rate);
return 0; return 0;
} }
...@@ -59,10 +59,12 @@ int main(void) ...@@ -59,10 +59,12 @@ int main(void)
DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp)); DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp));
DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value)); DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate)); DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
#ifdef CONFIG_VFP
DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate)); DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu)); DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu));
#endif #endif
#endif
#ifdef CONFIG_ARM_THUMBEE #ifdef CONFIG_ARM_THUMBEE
DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state)); DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state));
#endif #endif
......
...@@ -3,3 +3,17 @@ extern void save_atags(struct tag *tags); ...@@ -3,3 +3,17 @@ extern void save_atags(struct tag *tags);
#else #else
static inline void save_atags(struct tag *tags) { } static inline void save_atags(struct tag *tags) { }
#endif #endif
void convert_to_tag_list(struct tag *tags);
#ifdef CONFIG_ATAGS
struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr);
#else
static inline struct machine_desc *
setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
{
early_print("no ATAGS support: can't continue\n");
while (true);
unreachable();
}
#endif
/* /*
* linux/arch/arm/kernel/compat.c * linux/arch/arm/kernel/atags_compat.c
* *
* Copyright (C) 2001 Russell King * Copyright (C) 2001 Russell King
* *
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include "compat.h" #include "atags.h"
/* /*
* Usage: * Usage:
......
/*
* Tag parsing.
*
* Copyright (C) 1995-2001 Russell King
*
* 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.
*/
/*
* This is the traditional way of passing data to the kernel at boot time. Rather
* than passing a fixed inflexible structure to the kernel, we pass a list
* of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
* tag for the list to be recognised (to distinguish the tagged list from
* a param_struct). The list is terminated with a zero-length tag (this tag
* is not parsed in any way).
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/root_dev.h>
#include <linux/screen_info.h>
#include <asm/setup.h>
#include <asm/system_info.h>
#include <asm/page.h>
#include <asm/mach/arch.h>
#include "atags.h"
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
#ifndef MEM_SIZE
#define MEM_SIZE (16*1024*1024)
#endif
static struct {
struct tag_header hdr1;
struct tag_core core;
struct tag_header hdr2;
struct tag_mem32 mem;
struct tag_header hdr3;
} default_tags __initdata = {
{ tag_size(tag_core), ATAG_CORE },
{ 1, PAGE_SIZE, 0xff },
{ tag_size(tag_mem32), ATAG_MEM },
{ MEM_SIZE },
{ 0, ATAG_NONE }
};
static int __init parse_tag_core(const struct tag *tag)
{
if (tag->hdr.size > 2) {
if ((tag->u.core.flags & 1) == 0)
root_mountflags &= ~MS_RDONLY;
ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
}
return 0;
}
__tagtable(ATAG_CORE, parse_tag_core);
static int __init parse_tag_mem32(const struct tag *tag)
{
return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
}
__tagtable(ATAG_MEM, parse_tag_mem32);
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
static int __init parse_tag_videotext(const struct tag *tag)
{
screen_info.orig_x = tag->u.videotext.x;
screen_info.orig_y = tag->u.videotext.y;
screen_info.orig_video_page = tag->u.videotext.video_page;
screen_info.orig_video_mode = tag->u.videotext.video_mode;
screen_info.orig_video_cols = tag->u.videotext.video_cols;
screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
screen_info.orig_video_lines = tag->u.videotext.video_lines;
screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
screen_info.orig_video_points = tag->u.videotext.video_points;
return 0;
}
__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
#endif
#ifdef CONFIG_BLK_DEV_RAM
static int __init parse_tag_ramdisk(const struct tag *tag)
{
extern int rd_size, rd_image_start, rd_prompt, rd_doload;
rd_image_start = tag->u.ramdisk.start;
rd_doload = (tag->u.ramdisk.flags & 1) == 0;
rd_prompt = (tag->u.ramdisk.flags & 2) == 0;
if (tag->u.ramdisk.size)
rd_size = tag->u.ramdisk.size;
return 0;
}
__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
#endif
static int __init parse_tag_serialnr(const struct tag *tag)
{
system_serial_low = tag->u.serialnr.low;
system_serial_high = tag->u.serialnr.high;
return 0;
}
__tagtable(ATAG_SERIAL, parse_tag_serialnr);
static int __init parse_tag_revision(const struct tag *tag)
{
system_rev = tag->u.revision.rev;
return 0;
}
__tagtable(ATAG_REVISION, parse_tag_revision);
static int __init parse_tag_cmdline(const struct tag *tag)
{
#if defined(CONFIG_CMDLINE_EXTEND)
strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
strlcat(default_command_line, tag->u.cmdline.cmdline,
COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
pr_warning("Ignoring tag cmdline (using the default kernel command line)\n");
#else
strlcpy(default_command_line, tag->u.cmdline.cmdline,
COMMAND_LINE_SIZE);
#endif
return 0;
}
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
/*
* Scan the tag table for this tag, and call its parse function.
* The tag table is built by the linker from all the __tagtable
* declarations.
*/
static int __init parse_tag(const struct tag *tag)
{
extern struct tagtable __tagtable_begin, __tagtable_end;
struct tagtable *t;
for (t = &__tagtable_begin; t < &__tagtable_end; t++)
if (tag->hdr.tag == t->tag) {
t->parse(tag);
break;
}
return t < &__tagtable_end;
}
/*
* Parse all tags in the list, checking both the global and architecture
* specific tag tables.
*/
static void __init parse_tags(const struct tag *t)
{
for (; t->hdr.size; t = tag_next(t))
if (!parse_tag(t))
printk(KERN_WARNING
"Ignoring unrecognised tag 0x%08x\n",
t->hdr.tag);
}
static void __init squash_mem_tags(struct tag *tag)
{
for (; tag->hdr.size; tag = tag_next(tag))
if (tag->hdr.tag == ATAG_MEM)
tag->hdr.tag = ATAG_NONE;
}
struct machine_desc * __init setup_machine_tags(phys_addr_t __atags_pointer,
unsigned int machine_nr)
{
struct tag *tags = (struct tag *)&default_tags;
struct machine_desc *mdesc = NULL, *p;
char *from = default_command_line;
default_tags.mem.start = PHYS_OFFSET;
/*
* locate machine in the list of supported machines.
*/
for_each_machine_desc(p)
if (machine_nr == p->nr) {
printk("Machine: %s\n", p->name);
mdesc = p;
break;
}
if (!mdesc) {
early_print("\nError: unrecognized/unsupported machine ID"
" (r1 = 0x%08x).\n\n", machine_nr);
dump_machine_table(); /* does not return */
}
if (__atags_pointer)
tags = phys_to_virt(__atags_pointer);
else if (mdesc->atag_offset)
tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
/*
* If we have the old style parameters, convert them to
* a tag list.
*/
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
#endif
if (tags->hdr.tag != ATAG_CORE) {
early_print("Warning: Neither atags nor dtb found\n");
tags = (struct tag *)&default_tags;
}
if (mdesc->fixup)
mdesc->fixup(tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
save_atags(tags);
parse_tags(tags);
}
/* parse_early_param needs a boot_command_line */
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
return mdesc;
}
/*
* linux/arch/arm/kernel/compat.h
*
* Copyright (C) 2001 Russell King
*
* 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.
*/
extern void convert_to_tag_list(struct tag *tags);
...@@ -94,6 +94,15 @@ ENDPROC(ret_from_fork) ...@@ -94,6 +94,15 @@ ENDPROC(ret_from_fork)
.equ NR_syscalls,0 .equ NR_syscalls,0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1 #define CALL(x) .equ NR_syscalls,NR_syscalls+1
#include "calls.S" #include "calls.S"
/*
* Ensure that the system call table is equal to __NR_syscalls,
* which is the value the rest of the system sees
*/
.ifne NR_syscalls - __NR_syscalls
.error "__NR_syscalls is not equal to the size of the syscall table"
.endif
#undef CALL #undef CALL
#define CALL(x) .long x #define CALL(x) .long x
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/memblock.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <linux/of_fdt.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -32,6 +34,29 @@ static atomic_t waiting_for_crash_ipi; ...@@ -32,6 +34,29 @@ static atomic_t waiting_for_crash_ipi;
int machine_kexec_prepare(struct kimage *image) int machine_kexec_prepare(struct kimage *image)
{ {
struct kexec_segment *current_segment;
__be32 header;
int i, err;
/*
* No segment at default ATAGs address. try to locate
* a dtb using magic.
*/
for (i = 0; i < image->nr_segments; i++) {
current_segment = &image->segment[i];
err = memblock_is_region_memory(current_segment->mem,
current_segment->memsz);
if (err)
return - EINVAL;
err = get_user(header, (__be32*)current_segment->buf);
if (err)
return err;
if (be32_to_cpu(header) == OF_DT_HEADER)
kexec_boot_atags = current_segment->mem;
}
return 0; return 0;
} }
...@@ -122,8 +147,10 @@ void machine_kexec(struct kimage *image) ...@@ -122,8 +147,10 @@ void machine_kexec(struct kimage *image)
kexec_start_address = image->start; kexec_start_address = image->start;
kexec_indirection_page = page_list; kexec_indirection_page = page_list;
kexec_mach_type = machine_arch_type; kexec_mach_type = machine_arch_type;
if (!kexec_boot_atags)
kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
/* copy our kernel relocation code to the control code page */ /* copy our kernel relocation code to the control code page */
memcpy(reboot_code_buffer, memcpy(reboot_code_buffer,
relocate_new_kernel, relocate_new_kernel_size); relocate_new_kernel, relocate_new_kernel_size);
......
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/traps.h> #include <asm/traps.h>
#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>
#define REG_PC 15 #define REG_PC 15
#define REG_PSR 16 #define REG_PSR 16
/* /*
...@@ -918,11 +921,11 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, ...@@ -918,11 +921,11 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
{ {
unsigned long ip; unsigned long ip;
current_thread_info()->syscall = scno;
if (!test_thread_flag(TIF_SYSCALL_TRACE)) if (!test_thread_flag(TIF_SYSCALL_TRACE))
return scno; return scno;
current_thread_info()->syscall = scno;
/* /*
* IP is used to denote syscall entry/exit: * IP is used to denote syscall entry/exit:
* IP = 0 -> entry, =1 -> exit * IP = 0 -> entry, =1 -> exit
...@@ -941,15 +944,19 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, ...@@ -941,15 +944,19 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
{ {
int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER); scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER);
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, scno);
audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1, audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1,
regs->ARM_r2, regs->ARM_r3); regs->ARM_r2, regs->ARM_r3);
return ret; return scno;
} }
asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno) asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno)
{ {
int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT); scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT);
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_exit(regs, scno);
audit_syscall_exit(regs); audit_syscall_exit(regs);
return ret; return scno;
} }
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -27,6 +28,9 @@ struct clock_data { ...@@ -27,6 +28,9 @@ struct clock_data {
static void sched_clock_poll(unsigned long wrap_ticks); static void sched_clock_poll(unsigned long wrap_ticks);
static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
static int irqtime = -1;
core_param(irqtime, irqtime, int, 0400);
static struct clock_data cd = { static struct clock_data cd = {
.mult = NSEC_PER_SEC / HZ, .mult = NSEC_PER_SEC / HZ,
...@@ -157,6 +161,10 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) ...@@ -157,6 +161,10 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
*/ */
cd.epoch_ns = 0; cd.epoch_ns = 0;
/* Enable IRQ time accounting if we have a fast enough sched_clock */
if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
enable_sched_clock_irqtime();
pr_debug("Registered %pF as sched_clock source\n", read); pr_debug("Registered %pF as sched_clock source\n", read);
} }
......
...@@ -21,11 +21,9 @@ ...@@ -21,11 +21,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/root_dev.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/fs.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/bug.h> #include <linux/bug.h>
...@@ -56,15 +54,9 @@ ...@@ -56,15 +54,9 @@
#include <asm/unwind.h> #include <asm/unwind.h>
#include <asm/memblock.h> #include <asm/memblock.h>
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
#include "compat.h"
#endif
#include "atags.h" #include "atags.h"
#include "tcm.h" #include "tcm.h"
#ifndef MEM_SIZE
#define MEM_SIZE (16*1024*1024)
#endif
#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE) #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
char fpe_type[8]; char fpe_type[8];
...@@ -145,7 +137,6 @@ static const char *machine_name; ...@@ -145,7 +137,6 @@ static const char *machine_name;
static char __initdata cmd_line[COMMAND_LINE_SIZE]; static char __initdata cmd_line[COMMAND_LINE_SIZE];
struct machine_desc *machine_desc __initdata; struct machine_desc *machine_desc __initdata;
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l) #define ENDIANNESS ((char)endian_test.l)
...@@ -583,21 +574,6 @@ static int __init early_mem(char *p) ...@@ -583,21 +574,6 @@ static int __init early_mem(char *p)
} }
early_param("mem", early_mem); early_param("mem", early_mem);
static void __init
setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
{
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_size, rd_image_start, rd_prompt, rd_doload;
rd_image_start = image_start;
rd_prompt = prompt;
rd_doload = doload;
if (rd_sz)
rd_size = rd_sz;
#endif
}
static void __init request_standard_resources(struct machine_desc *mdesc) static void __init request_standard_resources(struct machine_desc *mdesc)
{ {
struct memblock_region *region; struct memblock_region *region;
...@@ -643,35 +619,6 @@ static void __init request_standard_resources(struct machine_desc *mdesc) ...@@ -643,35 +619,6 @@ static void __init request_standard_resources(struct machine_desc *mdesc)
request_resource(&ioport_resource, &lp2); request_resource(&ioport_resource, &lp2);
} }
/*
* Tag parsing.
*
* This is the new way of passing data to the kernel at boot time. Rather
* than passing a fixed inflexible structure to the kernel, we pass a list
* of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
* tag for the list to be recognised (to distinguish the tagged list from
* a param_struct). The list is terminated with a zero-length tag (this tag
* is not parsed in any way).
*/
static int __init parse_tag_core(const struct tag *tag)
{
if (tag->hdr.size > 2) {
if ((tag->u.core.flags & 1) == 0)
root_mountflags &= ~MS_RDONLY;
ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
}
return 0;
}
__tagtable(ATAG_CORE, parse_tag_core);
static int __init parse_tag_mem32(const struct tag *tag)
{
return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
}
__tagtable(ATAG_MEM, parse_tag_mem32);
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
struct screen_info screen_info = { struct screen_info screen_info = {
.orig_video_lines = 30, .orig_video_lines = 30,
...@@ -681,116 +628,7 @@ struct screen_info screen_info = { ...@@ -681,116 +628,7 @@ struct screen_info screen_info = {
.orig_video_isVGA = 1, .orig_video_isVGA = 1,
.orig_video_points = 8 .orig_video_points = 8
}; };
static int __init parse_tag_videotext(const struct tag *tag)
{
screen_info.orig_x = tag->u.videotext.x;
screen_info.orig_y = tag->u.videotext.y;
screen_info.orig_video_page = tag->u.videotext.video_page;
screen_info.orig_video_mode = tag->u.videotext.video_mode;
screen_info.orig_video_cols = tag->u.videotext.video_cols;
screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
screen_info.orig_video_lines = tag->u.videotext.video_lines;
screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
screen_info.orig_video_points = tag->u.videotext.video_points;
return 0;
}
__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
#endif
static int __init parse_tag_ramdisk(const struct tag *tag)
{
setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
(tag->u.ramdisk.flags & 2) == 0,
tag->u.ramdisk.start, tag->u.ramdisk.size);
return 0;
}
__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
static int __init parse_tag_serialnr(const struct tag *tag)
{
system_serial_low = tag->u.serialnr.low;
system_serial_high = tag->u.serialnr.high;
return 0;
}
__tagtable(ATAG_SERIAL, parse_tag_serialnr);
static int __init parse_tag_revision(const struct tag *tag)
{
system_rev = tag->u.revision.rev;
return 0;
}
__tagtable(ATAG_REVISION, parse_tag_revision);
static int __init parse_tag_cmdline(const struct tag *tag)
{
#if defined(CONFIG_CMDLINE_EXTEND)
strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
strlcat(default_command_line, tag->u.cmdline.cmdline,
COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
pr_warning("Ignoring tag cmdline (using the default kernel command line)\n");
#else
strlcpy(default_command_line, tag->u.cmdline.cmdline,
COMMAND_LINE_SIZE);
#endif #endif
return 0;
}
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
/*
* Scan the tag table for this tag, and call its parse function.
* The tag table is built by the linker from all the __tagtable
* declarations.
*/
static int __init parse_tag(const struct tag *tag)
{
extern struct tagtable __tagtable_begin, __tagtable_end;
struct tagtable *t;
for (t = &__tagtable_begin; t < &__tagtable_end; t++)
if (tag->hdr.tag == t->tag) {
t->parse(tag);
break;
}
return t < &__tagtable_end;
}
/*
* Parse all tags in the list, checking both the global and architecture
* specific tag tables.
*/
static void __init parse_tags(const struct tag *t)
{
for (; t->hdr.size; t = tag_next(t))
if (!parse_tag(t))
printk(KERN_WARNING
"Ignoring unrecognised tag 0x%08x\n",
t->hdr.tag);
}
/*
* This holds our defaults.
*/
static struct init_tags {
struct tag_header hdr1;
struct tag_core core;
struct tag_header hdr2;
struct tag_mem32 mem;
struct tag_header hdr3;
} init_tags __initdata = {
{ tag_size(tag_core), ATAG_CORE },
{ 1, PAGE_SIZE, 0xff },
{ tag_size(tag_mem32), ATAG_MEM },
{ MEM_SIZE },
{ 0, ATAG_NONE }
};
static int __init customize_machine(void) static int __init customize_machine(void)
{ {
...@@ -858,78 +696,6 @@ static void __init reserve_crashkernel(void) ...@@ -858,78 +696,6 @@ static void __init reserve_crashkernel(void)
static inline void reserve_crashkernel(void) {} static inline void reserve_crashkernel(void) {}
#endif /* CONFIG_KEXEC */ #endif /* CONFIG_KEXEC */
static void __init squash_mem_tags(struct tag *tag)
{
for (; tag->hdr.size; tag = tag_next(tag))
if (tag->hdr.tag == ATAG_MEM)
tag->hdr.tag = ATAG_NONE;
}
static struct machine_desc * __init setup_machine_tags(unsigned int nr)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc = NULL, *p;
char *from = default_command_line;
init_tags.mem.start = PHYS_OFFSET;
/*
* locate machine in the list of supported machines.
*/
for_each_machine_desc(p)
if (nr == p->nr) {
printk("Machine: %s\n", p->name);
mdesc = p;
break;
}
if (!mdesc) {
early_print("\nError: unrecognized/unsupported machine ID"
" (r1 = 0x%08x).\n\n", nr);
dump_machine_table(); /* does not return */
}
if (__atags_pointer)
tags = phys_to_virt(__atags_pointer);
else if (mdesc->atag_offset)
tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
/*
* If we have the old style parameters, convert them to
* a tag list.
*/
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
#endif
if (tags->hdr.tag != ATAG_CORE) {
#if defined(CONFIG_OF)
/*
* If CONFIG_OF is set, then assume this is a reasonably
* modern system that should pass boot parameters
*/
early_print("Warning: Neither atags nor dtb found\n");
#endif
tags = (struct tag *)&init_tags;
}
if (mdesc->fixup)
mdesc->fixup(tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
save_atags(tags);
parse_tags(tags);
}
/* parse_early_param needs a boot_command_line */
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
return mdesc;
}
static int __init meminfo_cmp(const void *_a, const void *_b) static int __init meminfo_cmp(const void *_a, const void *_b)
{ {
const struct membank *a = _a, *b = _b; const struct membank *a = _a, *b = _b;
...@@ -944,7 +710,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -944,7 +710,7 @@ void __init setup_arch(char **cmdline_p)
setup_processor(); setup_processor();
mdesc = setup_machine_fdt(__atags_pointer); mdesc = setup_machine_fdt(__atags_pointer);
if (!mdesc) if (!mdesc)
mdesc = setup_machine_tags(machine_arch_type); mdesc = setup_machine_tags(__atags_pointer, machine_arch_type);
machine_desc = mdesc; machine_desc = mdesc;
machine_name = mdesc->name; machine_name = mdesc->name;
......
...@@ -59,7 +59,8 @@ struct secondary_data secondary_data; ...@@ -59,7 +59,8 @@ struct secondary_data secondary_data;
volatile int __cpuinitdata pen_release = -1; volatile int __cpuinitdata pen_release = -1;
enum ipi_msg_type { enum ipi_msg_type {
IPI_TIMER = 2, IPI_WAKEUP,
IPI_TIMER,
IPI_RESCHEDULE, IPI_RESCHEDULE,
IPI_CALL_FUNC, IPI_CALL_FUNC,
IPI_CALL_FUNC_SINGLE, IPI_CALL_FUNC_SINGLE,
...@@ -414,7 +415,8 @@ void arch_send_call_function_single_ipi(int cpu) ...@@ -414,7 +415,8 @@ void arch_send_call_function_single_ipi(int cpu)
} }
static const char *ipi_types[NR_IPI] = { static const char *ipi_types[NR_IPI] = {
#define S(x,s) [x - IPI_TIMER] = s #define S(x,s) [x] = s
S(IPI_WAKEUP, "CPU wakeup interrupts"),
S(IPI_TIMER, "Timer broadcast interrupts"), S(IPI_TIMER, "Timer broadcast interrupts"),
S(IPI_RESCHEDULE, "Rescheduling interrupts"), S(IPI_RESCHEDULE, "Rescheduling interrupts"),
S(IPI_CALL_FUNC, "Function call interrupts"), S(IPI_CALL_FUNC, "Function call interrupts"),
...@@ -567,10 +569,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs) ...@@ -567,10 +569,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
struct pt_regs *old_regs = set_irq_regs(regs); struct pt_regs *old_regs = set_irq_regs(regs);
if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI) if (ipinr < NR_IPI)
__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]); __inc_irq_stat(cpu, ipi_irqs[ipinr]);
switch (ipinr) { switch (ipinr) {
case IPI_WAKEUP:
break;
case IPI_TIMER: case IPI_TIMER:
irq_enter(); irq_enter();
ipi_timer(); ipi_timer();
......
...@@ -34,7 +34,18 @@ struct arm_delay_ops arm_delay_ops = { ...@@ -34,7 +34,18 @@ struct arm_delay_ops arm_delay_ops = {
.udelay = __loop_udelay, .udelay = __loop_udelay,
}; };
#ifdef ARCH_HAS_READ_CURRENT_TIMER static const struct delay_timer *delay_timer;
static bool delay_calibrated;
int read_current_timer(unsigned long *timer_val)
{
if (!delay_timer)
return -ENXIO;
*timer_val = delay_timer->read_current_timer();
return 0;
}
static void __timer_delay(unsigned long cycles) static void __timer_delay(unsigned long cycles)
{ {
cycles_t start = get_cycles(); cycles_t start = get_cycles();
...@@ -55,18 +66,24 @@ static void __timer_udelay(unsigned long usecs) ...@@ -55,18 +66,24 @@ static void __timer_udelay(unsigned long usecs)
__timer_const_udelay(usecs * UDELAY_MULT); __timer_const_udelay(usecs * UDELAY_MULT);
} }
void __init init_current_timer_delay(unsigned long freq) void __init register_current_timer_delay(const struct delay_timer *timer)
{ {
if (!delay_calibrated) {
pr_info("Switching to timer-based delay loop\n"); pr_info("Switching to timer-based delay loop\n");
lpj_fine = freq / HZ; delay_timer = timer;
lpj_fine = timer->freq / HZ;
loops_per_jiffy = lpj_fine; loops_per_jiffy = lpj_fine;
arm_delay_ops.delay = __timer_delay; arm_delay_ops.delay = __timer_delay;
arm_delay_ops.const_udelay = __timer_const_udelay; arm_delay_ops.const_udelay = __timer_const_udelay;
arm_delay_ops.udelay = __timer_udelay; arm_delay_ops.udelay = __timer_udelay;
delay_calibrated = true;
} else {
pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
}
} }
unsigned long __cpuinit calibrate_delay_is_known(void) unsigned long __cpuinit calibrate_delay_is_known(void)
{ {
delay_calibrated = true;
return lpj_fine; return lpj_fine;
} }
#endif
...@@ -134,7 +134,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct ...@@ -134,7 +134,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct
__raw_writel(virt_to_phys(exynos4_secondary_startup), __raw_writel(virt_to_phys(exynos4_secondary_startup),
CPU1_BOOT_REG); CPU1_BOOT_REG);
gic_raise_softirq(cpumask_of(cpu), 1); gic_raise_softirq(cpumask_of(cpu), 0);
if (pen_release == -1) if (pen_release == -1)
break; break;
......
#include <linux/amba/serial.h>
extern struct amba_pl010_data integrator_uart_data;
void integrator_init_early(void); void integrator_init_early(void);
int integrator_init(bool is_cp);
void integrator_reserve(void); void integrator_reserve(void);
void integrator_restart(char, const char *); void integrator_restart(char, const char *);
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,9 @@
#include <asm/mach/time.h> #include <asm/mach/time.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
static struct amba_pl010_data integrator_uart_data; #include "common.h"
#ifdef CONFIG_ATAGS
#define INTEGRATOR_RTC_IRQ { IRQ_RTCINT } #define INTEGRATOR_RTC_IRQ { IRQ_RTCINT }
#define INTEGRATOR_UART0_IRQ { IRQ_UARTINT0 } #define INTEGRATOR_UART0_IRQ { IRQ_UARTINT0 }
...@@ -60,7 +62,7 @@ static struct amba_device *amba_devs[] __initdata = { ...@@ -60,7 +62,7 @@ static struct amba_device *amba_devs[] __initdata = {
&kmi1_device, &kmi1_device,
}; };
static int __init integrator_init(void) int __init integrator_init(bool is_cp)
{ {
int i; int i;
...@@ -69,7 +71,7 @@ static int __init integrator_init(void) ...@@ -69,7 +71,7 @@ static int __init integrator_init(void)
* hard-code them. The Integator/CP and forward have proper cell IDs. * hard-code them. The Integator/CP and forward have proper cell IDs.
* Else we leave them undefined to the bus driver can autoprobe them. * Else we leave them undefined to the bus driver can autoprobe them.
*/ */
if (machine_is_integrator()) { if (!is_cp) {
rtc_device.periphid = 0x00041030; rtc_device.periphid = 0x00041030;
uart0_device.periphid = 0x00041010; uart0_device.periphid = 0x00041010;
uart1_device.periphid = 0x00041010; uart1_device.periphid = 0x00041010;
...@@ -85,7 +87,7 @@ static int __init integrator_init(void) ...@@ -85,7 +87,7 @@ static int __init integrator_init(void)
return 0; return 0;
} }
arch_initcall(integrator_init); #endif
/* /*
* On the Integrator platform, the port RTS and DTR are provided by * On the Integrator platform, the port RTS and DTR are provided by
...@@ -100,11 +102,14 @@ arch_initcall(integrator_init); ...@@ -100,11 +102,14 @@ arch_initcall(integrator_init);
static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl) static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
{ {
unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
u32 phybase = dev->res.start;
if (dev == &uart0_device) { if (phybase == INTEGRATOR_UART0_BASE) {
/* UART0 */
rts_mask = 1 << 4; rts_mask = 1 << 4;
dtr_mask = 1 << 5; dtr_mask = 1 << 5;
} else { } else {
/* UART1 */
rts_mask = 1 << 6; rts_mask = 1 << 6;
dtr_mask = 1 << 7; dtr_mask = 1 << 7;
} }
...@@ -123,7 +128,7 @@ static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *bas ...@@ -123,7 +128,7 @@ static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *bas
__raw_writel(ctrlc, SC_CTRLC); __raw_writel(ctrlc, SC_CTRLC);
} }
static struct amba_pl010_data integrator_uart_data = { struct amba_pl010_data integrator_uart_data = {
.set_mctrl = integrator_uart_set_mctrl, .set_mctrl = integrator_uart_set_mctrl,
}; };
......
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/platform_data/clk-integrator.h> #include <linux/platform_data/clk-integrator.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <video/vga.h> #include <video/vga.h>
#include <mach/hardware.h> #include <mach/hardware.h>
...@@ -158,23 +161,6 @@ static void __init ap_map_io(void) ...@@ -158,23 +161,6 @@ static void __init ap_map_io(void)
pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE)); pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE));
} }
#define INTEGRATOR_SC_VALID_INT 0x003fffff
static void __init ap_init_irq(void)
{
/* Disable all interrupts initially. */
/* Do the core module ones */
writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
/* do the header card stuff next */
writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
-1, INTEGRATOR_SC_VALID_INT, NULL);
integrator_clk_init(false);
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static unsigned long ic_irq_enable; static unsigned long ic_irq_enable;
...@@ -267,50 +253,6 @@ static struct physmap_flash_data ap_flash_data = { ...@@ -267,50 +253,6 @@ static struct physmap_flash_data ap_flash_data = {
.set_vpp = ap_flash_set_vpp, .set_vpp = ap_flash_set_vpp,
}; };
static struct resource cfi_flash_resource = {
.start = INTEGRATOR_FLASH_BASE,
.end = INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device cfi_flash_device = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &ap_flash_data,
},
.num_resources = 1,
.resource = &cfi_flash_resource,
};
static void __init ap_init(void)
{
unsigned long sc_dec;
int i;
platform_device_register(&cfi_flash_device);
sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
for (i = 0; i < 4; i++) {
struct lm_device *lmdev;
if ((sc_dec & (16 << i)) == 0)
continue;
lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
if (!lmdev)
continue;
lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
lmdev->resource.flags = IORESOURCE_MEM;
lmdev->irq = IRQ_AP_EXPINT0 + i;
lmdev->id = i;
lm_device_register(lmdev);
}
}
/* /*
* Where is the timer (VA)? * Where is the timer (VA)?
*/ */
...@@ -325,9 +267,9 @@ static u32 notrace integrator_read_sched_clock(void) ...@@ -325,9 +267,9 @@ static u32 notrace integrator_read_sched_clock(void)
return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE); return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
} }
static void integrator_clocksource_init(unsigned long inrate) static void integrator_clocksource_init(unsigned long inrate,
void __iomem *base)
{ {
void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
unsigned long rate = inrate; unsigned long rate = inrate;
...@@ -344,7 +286,7 @@ static void integrator_clocksource_init(unsigned long inrate) ...@@ -344,7 +286,7 @@ static void integrator_clocksource_init(unsigned long inrate)
setup_sched_clock(integrator_read_sched_clock, 16, rate); setup_sched_clock(integrator_read_sched_clock, 16, rate);
} }
static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; static void __iomem * clkevt_base;
/* /*
* IRQ handler for the timer * IRQ handler for the timer
...@@ -416,11 +358,13 @@ static struct irqaction integrator_timer_irq = { ...@@ -416,11 +358,13 @@ static struct irqaction integrator_timer_irq = {
.dev_id = &integrator_clockevent, .dev_id = &integrator_clockevent,
}; };
static void integrator_clockevent_init(unsigned long inrate) static void integrator_clockevent_init(unsigned long inrate,
void __iomem *base, int irq)
{ {
unsigned long rate = inrate; unsigned long rate = inrate;
unsigned int ctrl = 0; unsigned int ctrl = 0;
clkevt_base = base;
/* Calculate and program a divisor */ /* Calculate and program a divisor */
if (rate > 0x100000 * HZ) { if (rate > 0x100000 * HZ) {
rate /= 256; rate /= 256;
...@@ -432,7 +376,7 @@ static void integrator_clockevent_init(unsigned long inrate) ...@@ -432,7 +376,7 @@ static void integrator_clockevent_init(unsigned long inrate)
timer_reload = rate / HZ; timer_reload = rate / HZ;
writel(ctrl, clkevt_base + TIMER_CTRL); writel(ctrl, clkevt_base + TIMER_CTRL);
setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); setup_irq(irq, &integrator_timer_irq);
clockevents_config_and_register(&integrator_clockevent, clockevents_config_and_register(&integrator_clockevent,
rate, rate,
1, 1,
...@@ -443,9 +387,153 @@ void __init ap_init_early(void) ...@@ -443,9 +387,153 @@ void __init ap_init_early(void)
{ {
} }
#ifdef CONFIG_OF
static void __init ap_init_timer_of(void)
{
struct device_node *node;
const char *path;
void __iomem *base;
int err;
int irq;
struct clk *clk;
unsigned long rate;
clk = clk_get_sys("ap_timer", NULL);
BUG_ON(IS_ERR(clk));
clk_prepare_enable(clk);
rate = clk_get_rate(clk);
err = of_property_read_string(of_aliases,
"arm,timer-primary", &path);
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
base = of_iomap(node, 0);
if (WARN_ON(!base))
return;
writel(0, base + TIMER_CTRL);
integrator_clocksource_init(rate, base);
err = of_property_read_string(of_aliases,
"arm,timer-secondary", &path);
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
base = of_iomap(node, 0);
if (WARN_ON(!base))
return;
irq = irq_of_parse_and_map(node, 0);
writel(0, base + TIMER_CTRL);
integrator_clockevent_init(rate, base, irq);
}
static struct sys_timer ap_of_timer = {
.init = ap_init_timer_of,
};
static const struct of_device_id fpga_irq_of_match[] __initconst = {
{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
{ /* Sentinel */ }
};
static void __init ap_init_irq_of(void)
{
/* disable core module IRQs */
writel(0xffffffffU, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
of_irq_init(fpga_irq_of_match);
integrator_clk_init(false);
}
/* For the Device Tree, add in the UART callbacks as AUXDATA */
static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
"rtc", NULL),
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
"uart0", &integrator_uart_data),
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
"uart1", &integrator_uart_data),
OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
"kmi0", NULL),
OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
"kmi1", NULL),
OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE,
"physmap-flash", &ap_flash_data),
{ /* sentinel */ },
};
static void __init ap_init_of(void)
{
unsigned long sc_dec;
int i;
of_platform_populate(NULL, of_default_bus_match_table,
ap_auxdata_lookup, NULL);
sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
for (i = 0; i < 4; i++) {
struct lm_device *lmdev;
if ((sc_dec & (16 << i)) == 0)
continue;
lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
if (!lmdev)
continue;
lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
lmdev->resource.flags = IORESOURCE_MEM;
lmdev->irq = IRQ_AP_EXPINT0 + i;
lmdev->id = i;
lm_device_register(lmdev);
}
}
static const char * ap_dt_board_compat[] = {
"arm,integrator-ap",
NULL,
};
DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
.reserve = integrator_reserve,
.map_io = ap_map_io,
.nr_irqs = NR_IRQS_INTEGRATOR_AP,
.init_early = ap_init_early,
.init_irq = ap_init_irq_of,
.handle_irq = fpga_handle_irq,
.timer = &ap_of_timer,
.init_machine = ap_init_of,
.restart = integrator_restart,
.dt_compat = ap_dt_board_compat,
MACHINE_END
#endif
#ifdef CONFIG_ATAGS
/* /*
* Set up timer(s). * This is where non-devicetree initialization code is collected and stashed
* for eventual deletion.
*/ */
static struct resource cfi_flash_resource = {
.start = INTEGRATOR_FLASH_BASE,
.end = INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device cfi_flash_device = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &ap_flash_data,
},
.num_resources = 1,
.resource = &cfi_flash_resource,
};
static void __init ap_init_timer(void) static void __init ap_init_timer(void)
{ {
struct clk *clk; struct clk *clk;
...@@ -460,14 +548,62 @@ static void __init ap_init_timer(void) ...@@ -460,14 +548,62 @@ static void __init ap_init_timer(void)
writel(0, TIMER1_VA_BASE + TIMER_CTRL); writel(0, TIMER1_VA_BASE + TIMER_CTRL);
writel(0, TIMER2_VA_BASE + TIMER_CTRL); writel(0, TIMER2_VA_BASE + TIMER_CTRL);
integrator_clocksource_init(rate); integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE);
integrator_clockevent_init(rate); integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE,
IRQ_TIMERINT1);
} }
static struct sys_timer ap_timer = { static struct sys_timer ap_timer = {
.init = ap_init_timer, .init = ap_init_timer,
}; };
#define INTEGRATOR_SC_VALID_INT 0x003fffff
static void __init ap_init_irq(void)
{
/* Disable all interrupts initially. */
/* Do the core module ones */
writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
/* do the header card stuff next */
writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
-1, INTEGRATOR_SC_VALID_INT, NULL);
integrator_clk_init(false);
}
static void __init ap_init(void)
{
unsigned long sc_dec;
int i;
platform_device_register(&cfi_flash_device);
sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
for (i = 0; i < 4; i++) {
struct lm_device *lmdev;
if ((sc_dec & (16 << i)) == 0)
continue;
lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
if (!lmdev)
continue;
lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
lmdev->resource.flags = IORESOURCE_MEM;
lmdev->irq = IRQ_AP_EXPINT0 + i;
lmdev->id = i;
lm_device_register(lmdev);
}
integrator_init(false);
}
MACHINE_START(INTEGRATOR, "ARM-Integrator") MACHINE_START(INTEGRATOR, "ARM-Integrator")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
.atag_offset = 0x100, .atag_offset = 0x100,
...@@ -481,3 +617,5 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator") ...@@ -481,3 +617,5 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
.init_machine = ap_init, .init_machine = ap_init,
.restart = integrator_restart, .restart = integrator_restart,
MACHINE_END MACHINE_END
#endif
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/platform_data/clk-integrator.h> #include <linux/platform_data/clk-integrator.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/platform.h> #include <mach/platform.h>
...@@ -49,16 +52,9 @@ ...@@ -49,16 +52,9 @@
#include "common.h" #include "common.h"
#define INTCP_PA_FLASH_BASE 0x24000000 #define INTCP_PA_FLASH_BASE 0x24000000
#define INTCP_FLASH_SIZE SZ_32M
#define INTCP_PA_CLCD_BASE 0xc0000000 #define INTCP_PA_CLCD_BASE 0xc0000000
#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40)
#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE)
#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE)
#define INTCP_ETH_SIZE 0x10
#define INTCP_VA_CTRL_BASE __io_address(INTEGRATOR_CP_CTL_BASE) #define INTCP_VA_CTRL_BASE __io_address(INTEGRATOR_CP_CTL_BASE)
#define INTCP_FLASHPROG 0x04 #define INTCP_FLASHPROG 0x04
#define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0) #define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0)
...@@ -143,37 +139,6 @@ static void __init intcp_map_io(void) ...@@ -143,37 +139,6 @@ static void __init intcp_map_io(void)
iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc)); iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
} }
static void __init intcp_init_irq(void)
{
u32 pic_mask, cic_mask, sic_mask;
/* These masks are for the HW IRQ registers */
pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
pic_mask |= (~((~0u) << (29 - 22))) << 22;
cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START));
sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
/*
* Disable all interrupt sources
*/
writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START,
-1, pic_mask, NULL);
fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START,
-1, cic_mask, NULL);
fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
IRQ_CP_CPPLDINT, sic_mask, NULL);
integrator_clk_init(true);
}
/* /*
* Flash handling. * Flash handling.
*/ */
...@@ -216,47 +181,6 @@ static struct physmap_flash_data intcp_flash_data = { ...@@ -216,47 +181,6 @@ static struct physmap_flash_data intcp_flash_data = {
.set_vpp = intcp_flash_set_vpp, .set_vpp = intcp_flash_set_vpp,
}; };
static struct resource intcp_flash_resource = {
.start = INTCP_PA_FLASH_BASE,
.end = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device intcp_flash_device = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &intcp_flash_data,
},
.num_resources = 1,
.resource = &intcp_flash_resource,
};
static struct resource smc91x_resources[] = {
[0] = {
.start = INTEGRATOR_CP_ETH_BASE,
.end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_CP_ETHINT,
.end = IRQ_CP_ETHINT,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
};
static struct platform_device *intcp_devs[] __initdata = {
&intcp_flash_device,
&smc91x_device,
};
/* /*
* It seems that the card insertion interrupt remains active after * It seems that the card insertion interrupt remains active after
* we've acknowledged it. We therefore ignore the interrupt, and * we've acknowledged it. We therefore ignore the interrupt, and
...@@ -278,16 +202,6 @@ static struct mmci_platform_data mmc_data = { ...@@ -278,16 +202,6 @@ static struct mmci_platform_data mmc_data = {
.gpio_cd = -1, .gpio_cd = -1,
}; };
#define INTEGRATOR_CP_MMC_IRQS { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
#define INTEGRATOR_CP_AACI_IRQS { IRQ_CP_AACIINT }
static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE,
INTEGRATOR_CP_MMC_IRQS, &mmc_data);
static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE,
INTEGRATOR_CP_AACI_IRQS, NULL);
/* /*
* CLCD support * CLCD support
*/ */
...@@ -338,15 +252,6 @@ static struct clcd_board clcd_data = { ...@@ -338,15 +252,6 @@ static struct clcd_board clcd_data = {
.remove = versatile_clcd_remove_dma, .remove = versatile_clcd_remove_dma,
}; };
static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE,
{ IRQ_CP_CLCDCINT }, &clcd_data);
static struct amba_device *amba_devs[] __initdata = {
&mmc_device,
&aaci_device,
&clcd_device,
};
#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28) #define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
static void __init intcp_init_early(void) static void __init intcp_init_early(void)
...@@ -356,16 +261,193 @@ static void __init intcp_init_early(void) ...@@ -356,16 +261,193 @@ static void __init intcp_init_early(void)
#endif #endif
} }
static void __init intcp_init(void) static void __init intcp_timer_init_of(void)
{ {
int i; struct device_node *node;
const char *path;
void __iomem *base;
int err;
int irq;
err = of_property_read_string(of_aliases,
"arm,timer-primary", &path);
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
base = of_iomap(node, 0);
if (WARN_ON(!base))
return;
writel(0, base + TIMER_CTRL);
sp804_clocksource_init(base, node->name);
err = of_property_read_string(of_aliases,
"arm,timer-secondary", &path);
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
base = of_iomap(node, 0);
if (WARN_ON(!base))
return;
irq = irq_of_parse_and_map(node, 0);
writel(0, base + TIMER_CTRL);
sp804_clockevents_init(base, irq, node->name);
}
platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); static struct sys_timer cp_of_timer = {
.init = intcp_timer_init_of,
};
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { #ifdef CONFIG_OF
struct amba_device *d = amba_devs[i];
amba_device_register(d, &iomem_resource); static const struct of_device_id fpga_irq_of_match[] __initconst = {
} { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
{ /* Sentinel */ }
};
static void __init intcp_init_irq_of(void)
{
of_irq_init(fpga_irq_of_match);
integrator_clk_init(true);
}
/*
* For the Device Tree, add in the UART, MMC and CLCD specifics as AUXDATA
* and enforce the bus names since these are used for clock lookups.
*/
static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
"rtc", NULL),
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
"uart0", &integrator_uart_data),
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
"uart1", &integrator_uart_data),
OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
"kmi0", NULL),
OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
"kmi1", NULL),
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_MMC_BASE,
"mmci", &mmc_data),
OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_AACI_BASE,
"aaci", &mmc_data),
OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE,
"clcd", &clcd_data),
OF_DEV_AUXDATA("cfi-flash", INTCP_PA_FLASH_BASE,
"physmap-flash", &intcp_flash_data),
{ /* sentinel */ },
};
static void __init intcp_init_of(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
intcp_auxdata_lookup, NULL);
}
static const char * intcp_dt_board_compat[] = {
"arm,integrator-cp",
NULL,
};
DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
.reserve = integrator_reserve,
.map_io = intcp_map_io,
.nr_irqs = NR_IRQS_INTEGRATOR_CP,
.init_early = intcp_init_early,
.init_irq = intcp_init_irq_of,
.handle_irq = fpga_handle_irq,
.timer = &cp_of_timer,
.init_machine = intcp_init_of,
.restart = integrator_restart,
.dt_compat = intcp_dt_board_compat,
MACHINE_END
#endif
#ifdef CONFIG_ATAGS
/*
* This is where non-devicetree initialization code is collected and stashed
* for eventual deletion.
*/
#define INTCP_FLASH_SIZE SZ_32M
static struct resource intcp_flash_resource = {
.start = INTCP_PA_FLASH_BASE,
.end = INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device intcp_flash_device = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &intcp_flash_data,
},
.num_resources = 1,
.resource = &intcp_flash_resource,
};
#define INTCP_ETH_SIZE 0x10
static struct resource smc91x_resources[] = {
[0] = {
.start = INTEGRATOR_CP_ETH_BASE,
.end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_CP_ETHINT,
.end = IRQ_CP_ETHINT,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
};
static struct platform_device *intcp_devs[] __initdata = {
&intcp_flash_device,
&smc91x_device,
};
#define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40)
#define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE)
#define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE)
static void __init intcp_init_irq(void)
{
u32 pic_mask, cic_mask, sic_mask;
/* These masks are for the HW IRQ registers */
pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
pic_mask |= (~((~0u) << (29 - 22))) << 22;
cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START));
sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
/*
* Disable all interrupt sources
*/
writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START,
-1, pic_mask, NULL);
fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START,
-1, cic_mask, NULL);
fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
IRQ_CP_CPPLDINT, sic_mask, NULL);
integrator_clk_init(true);
} }
#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE) #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
...@@ -386,6 +468,37 @@ static struct sys_timer cp_timer = { ...@@ -386,6 +468,37 @@ static struct sys_timer cp_timer = {
.init = intcp_timer_init, .init = intcp_timer_init,
}; };
#define INTEGRATOR_CP_MMC_IRQS { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
#define INTEGRATOR_CP_AACI_IRQS { IRQ_CP_AACIINT }
static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE,
INTEGRATOR_CP_MMC_IRQS, &mmc_data);
static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE,
INTEGRATOR_CP_AACI_IRQS, NULL);
static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE,
{ IRQ_CP_CLCDCINT }, &clcd_data);
static struct amba_device *amba_devs[] __initdata = {
&mmc_device,
&aaci_device,
&clcd_device,
};
static void __init intcp_init(void)
{
int i;
platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
struct amba_device *d = amba_devs[i];
amba_device_register(d, &iomem_resource);
}
integrator_init(true);
}
MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
.atag_offset = 0x100, .atag_offset = 0x100,
...@@ -399,3 +512,5 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") ...@@ -399,3 +512,5 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
.init_machine = intcp_init, .init_machine = intcp_init,
.restart = integrator_restart, .restart = integrator_restart,
MACHINE_END MACHINE_END
#endif
/*
* Moved to new location
*/
#warning using old SA-1111.h - update to <asm/hardware/sa1111.h>
#include <asm/hardware/sa1111.h>
#ifndef _INCLUDE_LART_H
#define _INCLUDE_LART_H
#define LART_GPIO_ETH0 GPIO_GPIO0
#define LART_IRQ_ETH0 IRQ_GPIO0
#define LART_GPIO_IDE GPIO_GPIO1
#define LART_IRQ_IDE IRQ_GPIO1
#define LART_GPIO_UCB1200 GPIO_GPIO18
#define LART_IRQ_UCB1200 IRQ_GPIO18
#endif
...@@ -100,7 +100,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct * ...@@ -100,7 +100,7 @@ static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *
/* Tell ROM loader about our vector (in headsmp.S) */ /* Tell ROM loader about our vector (in headsmp.S) */
emev2_set_boot_vector(__pa(shmobile_secondary_vector)); emev2_set_boot_vector(__pa(shmobile_secondary_vector));
gic_raise_softirq(cpumask_of(cpu), 1); gic_raise_softirq(cpumask_of(cpu), 0);
return 0; return 0;
} }
......
...@@ -699,7 +699,6 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs, ...@@ -699,7 +699,6 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
unsigned long instr = *pinstr; unsigned long instr = *pinstr;
u16 tinst1 = (instr >> 16) & 0xffff; u16 tinst1 = (instr >> 16) & 0xffff;
u16 tinst2 = instr & 0xffff; u16 tinst2 = instr & 0xffff;
poffset->un = 0;
switch (tinst1 & 0xffe0) { switch (tinst1 & 0xffe0) {
/* A6.3.5 Load/Store multiple */ /* A6.3.5 Load/Store multiple */
...@@ -854,9 +853,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -854,9 +853,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
break; break;
case 0x08000000: /* ldm or stm, or thumb-2 32bit instruction */ case 0x08000000: /* ldm or stm, or thumb-2 32bit instruction */
if (thumb2_32b) if (thumb2_32b) {
offset.un = 0;
handler = do_alignment_t32_to_handler(&instr, regs, &offset); handler = do_alignment_t32_to_handler(&instr, regs, &offset);
else } else
handler = do_alignment_ldmstm; handler = do_alignment_ldmstm;
break; break;
......
...@@ -368,14 +368,18 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) ...@@ -368,14 +368,18 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
/* l2x0 controller is disabled */ /* l2x0 controller is disabled */
writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
l2x0_saved_regs.aux_ctrl = aux;
l2x0_inv_all(); l2x0_inv_all();
/* enable L2X0 */ /* enable L2X0 */
writel_relaxed(1, l2x0_base + L2X0_CTRL); writel_relaxed(1, l2x0_base + L2X0_CTRL);
} }
/* Re-read it in case some bits are reserved. */
aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
/* Save the value for resuming. */
l2x0_saved_regs.aux_ctrl = aux;
outer_cache.inv_range = l2x0_inv_range; outer_cache.inv_range = l2x0_inv_range;
outer_cache.clean_range = l2x0_clean_range; outer_cache.clean_range = l2x0_clean_range;
outer_cache.flush_range = l2x0_flush_range; outer_cache.flush_range = l2x0_flush_range;
......
...@@ -211,6 +211,9 @@ ENTRY(v7_coherent_user_range) ...@@ -211,6 +211,9 @@ ENTRY(v7_coherent_user_range)
* isn't mapped, fail with -EFAULT. * isn't mapped, fail with -EFAULT.
*/ */
9001: 9001:
#ifdef CONFIG_ARM_ERRATA_775420
dsb
#endif
mov r0, #-EFAULT mov r0, #-EFAULT
mov pc, lr mov pc, lr
UNWIND(.fnend ) UNWIND(.fnend )
......
...@@ -324,7 +324,7 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align) ...@@ -324,7 +324,7 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
BUG_ON(!arm_memblock_steal_permitted); BUG_ON(!arm_memblock_steal_permitted);
phys = memblock_alloc(size, align); phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
memblock_free(phys, size); memblock_free(phys, size);
memblock_remove(phys, size); memblock_remove(phys, size);
......
...@@ -248,6 +248,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, ...@@ -248,6 +248,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
if (!area) if (!area)
return NULL; return NULL;
addr = (unsigned long)area->addr; addr = (unsigned long)area->addr;
area->phys_addr = __pfn_to_phys(pfn);
#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE) #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
if (DOMAIN_IO == 0 && if (DOMAIN_IO == 0 &&
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/exception.h> #include <asm/exception.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
...@@ -14,11 +16,17 @@ ...@@ -14,11 +16,17 @@
#define IRQ_RAW_STATUS 0x04 #define IRQ_RAW_STATUS 0x04
#define IRQ_ENABLE_SET 0x08 #define IRQ_ENABLE_SET 0x08
#define IRQ_ENABLE_CLEAR 0x0c #define IRQ_ENABLE_CLEAR 0x0c
#define INT_SOFT_SET 0x10
#define INT_SOFT_CLEAR 0x14
#define FIQ_STATUS 0x20
#define FIQ_RAW_STATUS 0x24
#define FIQ_ENABLE 0x28
#define FIQ_ENABLE_SET 0x28
#define FIQ_ENABLE_CLEAR 0x2C
/** /**
* struct fpga_irq_data - irq data container for the FPGA IRQ controller * struct fpga_irq_data - irq data container for the FPGA IRQ controller
* @base: memory offset in virtual memory * @base: memory offset in virtual memory
* @irq_start: first IRQ number handled by this instance
* @chip: chip container for this instance * @chip: chip container for this instance
* @domain: IRQ domain for this instance * @domain: IRQ domain for this instance
* @valid: mask for valid IRQs on this controller * @valid: mask for valid IRQs on this controller
...@@ -26,7 +34,6 @@ ...@@ -26,7 +34,6 @@
*/ */
struct fpga_irq_data { struct fpga_irq_data {
void __iomem *base; void __iomem *base;
unsigned int irq_start;
struct irq_chip chip; struct irq_chip chip;
u32 valid; u32 valid;
struct irq_domain *domain; struct irq_domain *domain;
...@@ -125,34 +132,79 @@ static struct irq_domain_ops fpga_irqdomain_ops = { ...@@ -125,34 +132,79 @@ static struct irq_domain_ops fpga_irqdomain_ops = {
.xlate = irq_domain_xlate_onetwocell, .xlate = irq_domain_xlate_onetwocell,
}; };
void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start, static __init struct fpga_irq_data *
int parent_irq, u32 valid, struct device_node *node) fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
{
struct fpga_irq_data *f; struct fpga_irq_data *f;
if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) { if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__); printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
return; return NULL;
} }
f = &fpga_irq_devices[fpga_irq_id]; f = &fpga_irq_devices[fpga_irq_id];
f->base = base; f->base = base;
f->irq_start = irq_start;
f->chip.name = name; f->chip.name = name;
f->chip.irq_ack = fpga_irq_mask; f->chip.irq_ack = fpga_irq_mask;
f->chip.irq_mask = fpga_irq_mask; f->chip.irq_mask = fpga_irq_mask;
f->chip.irq_unmask = fpga_irq_unmask; f->chip.irq_unmask = fpga_irq_unmask;
f->valid = valid; f->valid = valid;
fpga_irq_id++;
return f;
}
void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
int parent_irq, u32 valid, struct device_node *node)
{
struct fpga_irq_data *f;
f = fpga_irq_prep_struct(base, name, valid);
if (!f)
return;
if (parent_irq != -1) { if (parent_irq != -1) {
irq_set_handler_data(parent_irq, f); irq_set_handler_data(parent_irq, f);
irq_set_chained_handler(parent_irq, fpga_irq_handle); irq_set_chained_handler(parent_irq, fpga_irq_handle);
} }
f->domain = irq_domain_add_legacy(node, fls(valid), f->irq_start, 0, f->domain = irq_domain_add_legacy(node, fls(valid), irq_start, 0,
&fpga_irqdomain_ops, f); &fpga_irqdomain_ops, f);
pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n", pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
fpga_irq_id, name, base, f->used_irqs); fpga_irq_id, name, base, f->used_irqs);
}
fpga_irq_id++; #ifdef CONFIG_OF
int __init fpga_irq_of_init(struct device_node *node,
struct device_node *parent)
{
struct fpga_irq_data *f;
void __iomem *base;
u32 clear_mask;
u32 valid_mask;
if (WARN_ON(!node))
return -ENODEV;
base = of_iomap(node, 0);
WARN(!base, "unable to map fpga irq registers\n");
if (of_property_read_u32(node, "clear-mask", &clear_mask))
clear_mask = 0;
if (of_property_read_u32(node, "valid-mask", &valid_mask))
valid_mask = 0;
f = fpga_irq_prep_struct(base, node->name, valid_mask);
if (!f)
return -ENOMEM;
writel(clear_mask, base + IRQ_ENABLE_CLEAR);
writel(clear_mask, base + FIQ_ENABLE_CLEAR);
f->domain = irq_domain_add_linear(node, fls(valid_mask), &fpga_irqdomain_ops, f);
f->used_irqs = hweight32(valid_mask);
pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
fpga_irq_id, node->name, base, f->used_irqs);
return 0;
} }
#endif
...@@ -7,5 +7,7 @@ struct pt_regs; ...@@ -7,5 +7,7 @@ struct pt_regs;
void fpga_handle_irq(struct pt_regs *regs); void fpga_handle_irq(struct pt_regs *regs);
void fpga_irq_init(void __iomem *, const char *, int, int, u32, void fpga_irq_init(void __iomem *, const char *, int, int, u32,
struct device_node *node); struct device_node *node);
int fpga_irq_of_init(struct device_node *node,
struct device_node *parent);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment