Commit c9ef7139 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm64-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64

Pull arm64 update from Catalin Marinas:
 "Main features:

   - Versatile Express SoC (model) support - DT files and Kconfig
     entries (there are no arch/arm64/mach-* directories).  The bulk of
     the code has already been moved to drivers/ as part of the ARM SoC
     clean-up.

   - Basic multi-cluster support (CPU logical map initialised from the
     DT)

   - Simple earlyprintk support for UART 8250/16550 and FastModel
     console output

   - Optimised kernel library bitops and string functions.

   - Automatic initialisation of the irqchip and clocks via DT"

* tag 'arm64-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64: (26 commits)
  arm64: Use acquire/release semantics instead of explicit DMB
  arm64: klib: bitops: fix unpredictable stxr usage
  arm64: vexpress: Enable ARMv8 RTSM model (SoC) support
  arm64: vexpress: Add dts files for the ARMv8 RTSM models
  arm64: Survive invalid cpu enable-methods
  arm64: mm: Correct show_pte behaviour
  arm64: Fix compat types affecting struct compat_stat
  arm64: Execute DSB during thread switching for TLB/cache maintenance
  arm64: compiling issue, need add include/asm/vga.h file
  arm64: smp: honour #address-size when parsing CPU reg property
  arm64: Define cmpxchg64 and cmpxchg64_local for outside use
  arm64: Define readq and writeq for driver module using
  arm64: Fix task tracing
  arm64: add explicit symbols to ESR_EL1 decoding
  arm64: Use irqchip_init() for interrupt controller initialisation
  arm64: psci: Use the MPIDR values from cpu_logical_map for cpu ids.
  arm64: klib: Optimised atomic bitops
  arm64: klib: Optimised string functions
  arm64: klib: Optimised memory functions
  arm64: head: match all affinity levels in the pen of the secondaries
  ...
parents 87c1f0f8 16c85a1f
...@@ -99,7 +99,16 @@ source "init/Kconfig" ...@@ -99,7 +99,16 @@ source "init/Kconfig"
source "kernel/Kconfig.freezer" source "kernel/Kconfig.freezer"
menu "System Type" menu "Platform selection"
config ARCH_VEXPRESS
bool "ARMv8 software model (Versatile Express)"
select ARCH_REQUIRE_GPIOLIB
select COMMON_CLK_VERSATILE
select VEXPRESS_CONFIG
help
This enables support for the ARMv8 software model (Versatile
Express).
endmenu endmenu
......
dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb
targets += dtbs targets += dtbs
targets += $(dtb-y) targets += $(dtb-y)
......
/*
* ARM Ltd.
*
* ARMv8 Foundation model DTS
*/
/dts-v1/;
/ {
model = "Foundation-v8A";
compatible = "arm,foundation-aarch64", "arm,vexpress";
interrupt-parent = <&gic>;
#address-cells = <2>;
#size-cells = <2>;
chosen { };
aliases {
serial0 = &v2m_serial0;
serial1 = &v2m_serial1;
serial2 = &v2m_serial2;
serial3 = &v2m_serial3;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x0>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x1>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
cpu@2 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x2>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
cpu@3 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x3>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x00000000 0x80000000 0 0x80000000>,
<0x00000008 0x80000000 0 0x80000000>;
};
gic: interrupt-controller@2c001000 {
compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
#interrupt-cells = <3>;
#address-cells = <0>;
interrupt-controller;
reg = <0x0 0x2c001000 0 0x1000>,
<0x0 0x2c002000 0 0x1000>,
<0x0 0x2c004000 0 0x2000>,
<0x0 0x2c006000 0 0x2000>;
interrupts = <1 9 0xf04>;
};
timer {
compatible = "arm,armv8-timer";
interrupts = <1 13 0xff01>,
<1 14 0xff01>,
<1 11 0xff01>,
<1 10 0xff01>;
clock-frequency = <100000000>;
};
pmu {
compatible = "arm,armv8-pmuv3";
interrupts = <0 60 4>,
<0 61 4>,
<0 62 4>,
<0 63 4>;
};
smb {
compatible = "arm,vexpress,v2m-p1", "simple-bus";
arm,v2m-memory-map = "rs1";
#address-cells = <2>; /* SMB chipselect number and offset */
#size-cells = <1>;
ranges = <0 0 0 0x08000000 0x04000000>,
<1 0 0 0x14000000 0x04000000>,
<2 0 0 0x18000000 0x04000000>,
<3 0 0 0x1c000000 0x04000000>,
<4 0 0 0x0c000000 0x04000000>,
<5 0 0 0x10000000 0x04000000>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 63>;
interrupt-map = <0 0 0 &gic 0 0 4>,
<0 0 1 &gic 0 1 4>,
<0 0 2 &gic 0 2 4>,
<0 0 3 &gic 0 3 4>,
<0 0 4 &gic 0 4 4>,
<0 0 5 &gic 0 5 4>,
<0 0 6 &gic 0 6 4>,
<0 0 7 &gic 0 7 4>,
<0 0 8 &gic 0 8 4>,
<0 0 9 &gic 0 9 4>,
<0 0 10 &gic 0 10 4>,
<0 0 11 &gic 0 11 4>,
<0 0 12 &gic 0 12 4>,
<0 0 13 &gic 0 13 4>,
<0 0 14 &gic 0 14 4>,
<0 0 15 &gic 0 15 4>,
<0 0 16 &gic 0 16 4>,
<0 0 17 &gic 0 17 4>,
<0 0 18 &gic 0 18 4>,
<0 0 19 &gic 0 19 4>,
<0 0 20 &gic 0 20 4>,
<0 0 21 &gic 0 21 4>,
<0 0 22 &gic 0 22 4>,
<0 0 23 &gic 0 23 4>,
<0 0 24 &gic 0 24 4>,
<0 0 25 &gic 0 25 4>,
<0 0 26 &gic 0 26 4>,
<0 0 27 &gic 0 27 4>,
<0 0 28 &gic 0 28 4>,
<0 0 29 &gic 0 29 4>,
<0 0 30 &gic 0 30 4>,
<0 0 31 &gic 0 31 4>,
<0 0 32 &gic 0 32 4>,
<0 0 33 &gic 0 33 4>,
<0 0 34 &gic 0 34 4>,
<0 0 35 &gic 0 35 4>,
<0 0 36 &gic 0 36 4>,
<0 0 37 &gic 0 37 4>,
<0 0 38 &gic 0 38 4>,
<0 0 39 &gic 0 39 4>,
<0 0 40 &gic 0 40 4>,
<0 0 41 &gic 0 41 4>,
<0 0 42 &gic 0 42 4>;
ethernet@2,02000000 {
compatible = "smsc,lan91c111";
reg = <2 0x02000000 0x10000>;
interrupts = <15>;
};
v2m_clk24mhz: clk24mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-output-names = "v2m:clk24mhz";
};
v2m_refclk1mhz: refclk1mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000>;
clock-output-names = "v2m:refclk1mhz";
};
v2m_refclk32khz: refclk32khz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "v2m:refclk32khz";
};
iofpga@3,00000000 {
compatible = "arm,amba-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
v2m_sysreg: sysreg@010000 {
compatible = "arm,vexpress-sysreg";
reg = <0x010000 0x1000>;
};
v2m_serial0: uart@090000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x090000 0x1000>;
interrupts = <5>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
v2m_serial1: uart@0a0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0a0000 0x1000>;
interrupts = <6>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
v2m_serial2: uart@0b0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0b0000 0x1000>;
interrupts = <7>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
v2m_serial3: uart@0c0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0c0000 0x1000>;
interrupts = <8>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
virtio_block@0130000 {
compatible = "virtio,mmio";
reg = <0x130000 0x1000>;
interrupts = <42>;
};
};
};
};
/*
* ARM Ltd. Fast Models
*
* Architecture Envelope Model (AEM) ARMv8-A
* ARMAEMv8AMPCT
*
* RTSM_VE_AEMv8A.lisa
*/
/dts-v1/;
/memreserve/ 0x80000000 0x00010000;
/ {
model = "RTSM_VE_AEMv8A";
compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress";
interrupt-parent = <&gic>;
#address-cells = <2>;
#size-cells = <2>;
chosen { };
aliases {
serial0 = &v2m_serial0;
serial1 = &v2m_serial1;
serial2 = &v2m_serial2;
serial3 = &v2m_serial3;
};
cpus {
#address-cells = <2>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x0>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x1>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
cpu@2 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x2>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
cpu@3 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x3>;
enable-method = "spin-table";
cpu-release-addr = <0x0 0x8000fff8>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x00000000 0x80000000 0 0x80000000>,
<0x00000008 0x80000000 0 0x80000000>;
};
gic: interrupt-controller@2c001000 {
compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
#interrupt-cells = <3>;
#address-cells = <0>;
interrupt-controller;
reg = <0x0 0x2c001000 0 0x1000>,
<0x0 0x2c002000 0 0x1000>,
<0x0 0x2c004000 0 0x2000>,
<0x0 0x2c006000 0 0x2000>;
interrupts = <1 9 0xf04>;
};
timer {
compatible = "arm,armv8-timer";
interrupts = <1 13 0xff01>,
<1 14 0xff01>,
<1 11 0xff01>,
<1 10 0xff01>;
clock-frequency = <100000000>;
};
pmu {
compatible = "arm,armv8-pmuv3";
interrupts = <0 60 4>,
<0 61 4>,
<0 62 4>,
<0 63 4>;
};
smb {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0 0x08000000 0x04000000>,
<1 0 0 0x14000000 0x04000000>,
<2 0 0 0x18000000 0x04000000>,
<3 0 0 0x1c000000 0x04000000>,
<4 0 0 0x0c000000 0x04000000>,
<5 0 0 0x10000000 0x04000000>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 63>;
interrupt-map = <0 0 0 &gic 0 0 4>,
<0 0 1 &gic 0 1 4>,
<0 0 2 &gic 0 2 4>,
<0 0 3 &gic 0 3 4>,
<0 0 4 &gic 0 4 4>,
<0 0 5 &gic 0 5 4>,
<0 0 6 &gic 0 6 4>,
<0 0 7 &gic 0 7 4>,
<0 0 8 &gic 0 8 4>,
<0 0 9 &gic 0 9 4>,
<0 0 10 &gic 0 10 4>,
<0 0 11 &gic 0 11 4>,
<0 0 12 &gic 0 12 4>,
<0 0 13 &gic 0 13 4>,
<0 0 14 &gic 0 14 4>,
<0 0 15 &gic 0 15 4>,
<0 0 16 &gic 0 16 4>,
<0 0 17 &gic 0 17 4>,
<0 0 18 &gic 0 18 4>,
<0 0 19 &gic 0 19 4>,
<0 0 20 &gic 0 20 4>,
<0 0 21 &gic 0 21 4>,
<0 0 22 &gic 0 22 4>,
<0 0 23 &gic 0 23 4>,
<0 0 24 &gic 0 24 4>,
<0 0 25 &gic 0 25 4>,
<0 0 26 &gic 0 26 4>,
<0 0 27 &gic 0 27 4>,
<0 0 28 &gic 0 28 4>,
<0 0 29 &gic 0 29 4>,
<0 0 30 &gic 0 30 4>,
<0 0 31 &gic 0 31 4>,
<0 0 32 &gic 0 32 4>,
<0 0 33 &gic 0 33 4>,
<0 0 34 &gic 0 34 4>,
<0 0 35 &gic 0 35 4>,
<0 0 36 &gic 0 36 4>,
<0 0 37 &gic 0 37 4>,
<0 0 38 &gic 0 38 4>,
<0 0 39 &gic 0 39 4>,
<0 0 40 &gic 0 40 4>,
<0 0 41 &gic 0 41 4>,
<0 0 42 &gic 0 42 4>;
/include/ "rtsm_ve-motherboard.dtsi"
};
};
/*
* ARM Ltd. Fast Models
*
* Versatile Express (VE) system model
* Motherboard component
*
* VEMotherBoard.lisa
*/
motherboard {
arm,v2m-memory-map = "rs1";
compatible = "arm,vexpress,v2m-p1", "simple-bus";
#address-cells = <2>; /* SMB chipselect number and offset */
#size-cells = <1>;
#interrupt-cells = <1>;
ranges;
flash@0,00000000 {
compatible = "arm,vexpress-flash", "cfi-flash";
reg = <0 0x00000000 0x04000000>,
<4 0x00000000 0x04000000>;
bank-width = <4>;
};
vram@2,00000000 {
compatible = "arm,vexpress-vram";
reg = <2 0x00000000 0x00800000>;
};
ethernet@2,02000000 {
compatible = "smsc,lan91c111";
reg = <2 0x02000000 0x10000>;
interrupts = <15>;
};
v2m_clk24mhz: clk24mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-output-names = "v2m:clk24mhz";
};
v2m_refclk1mhz: refclk1mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1000000>;
clock-output-names = "v2m:refclk1mhz";
};
v2m_refclk32khz: refclk32khz {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "v2m:refclk32khz";
};
iofpga@3,00000000 {
compatible = "arm,amba-bus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
v2m_sysreg: sysreg@010000 {
compatible = "arm,vexpress-sysreg";
reg = <0x010000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
};
v2m_sysctl: sysctl@020000 {
compatible = "arm,sp810", "arm,primecell";
reg = <0x020000 0x1000>;
clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
clock-names = "refclk", "timclk", "apb_pclk";
#clock-cells = <1>;
clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
};
aaci@040000 {
compatible = "arm,pl041", "arm,primecell";
reg = <0x040000 0x1000>;
interrupts = <11>;
clocks = <&v2m_clk24mhz>;
clock-names = "apb_pclk";
};
mmci@050000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x050000 0x1000>;
interrupts = <9 10>;
cd-gpios = <&v2m_sysreg 0 0>;
wp-gpios = <&v2m_sysreg 1 0>;
max-frequency = <12000000>;
vmmc-supply = <&v2m_fixed_3v3>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "mclk", "apb_pclk";
};
kmi@060000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x060000 0x1000>;
interrupts = <12>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "KMIREFCLK", "apb_pclk";
};
kmi@070000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x070000 0x1000>;
interrupts = <13>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "KMIREFCLK", "apb_pclk";
};
v2m_serial0: uart@090000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x090000 0x1000>;
interrupts = <5>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
v2m_serial1: uart@0a0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0a0000 0x1000>;
interrupts = <6>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
v2m_serial2: uart@0b0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0b0000 0x1000>;
interrupts = <7>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
v2m_serial3: uart@0c0000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0c0000 0x1000>;
interrupts = <8>;
clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
clock-names = "uartclk", "apb_pclk";
};
wdt@0f0000 {
compatible = "arm,sp805", "arm,primecell";
reg = <0x0f0000 0x1000>;
interrupts = <0>;
clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
clock-names = "wdogclk", "apb_pclk";
};
v2m_timer01: timer@110000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x110000 0x1000>;
interrupts = <2>;
clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
clock-names = "timclken1", "timclken2", "apb_pclk";
};
v2m_timer23: timer@120000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x120000 0x1000>;
interrupts = <3>;
clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
clock-names = "timclken1", "timclken2", "apb_pclk";
};
rtc@170000 {
compatible = "arm,pl031", "arm,primecell";
reg = <0x170000 0x1000>;
interrupts = <4>;
clocks = <&v2m_clk24mhz>;
clock-names = "apb_pclk";
};
clcd@1f0000 {
compatible = "arm,pl111", "arm,primecell";
reg = <0x1f0000 0x1000>;
interrupts = <14>;
clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
clock-names = "clcdclk", "apb_pclk";
};
};
v2m_fixed_3v3: fixedregulator@0 {
compatible = "regulator-fixed";
regulator-name = "3V3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
mcc {
compatible = "arm,vexpress,config-bus", "simple-bus";
arm,vexpress,config-bridge = <&v2m_sysreg>;
v2m_oscclk1: osc@1 {
/* CLCD clock */
compatible = "arm,vexpress-osc";
arm,vexpress-sysreg,func = <1 1>;
freq-range = <23750000 63500000>;
#clock-cells = <0>;
clock-output-names = "v2m:oscclk1";
};
reset@0 {
compatible = "arm,vexpress-reset";
arm,vexpress-sysreg,func = <5 0>;
};
muxfpga@0 {
compatible = "arm,vexpress-muxfpga";
arm,vexpress-sysreg,func = <7 0>;
};
shutdown@0 {
compatible = "arm,vexpress-shutdown";
arm,vexpress-sysreg,func = <8 0>;
};
reboot@0 {
compatible = "arm,vexpress-reboot";
arm,vexpress-sysreg,func = <9 0>;
};
dvimode@0 {
compatible = "arm,vexpress-dvimode";
arm,vexpress-sysreg,func = <11 0>;
};
};
};
/*
* Skeleton device tree; the bare minimum needed to boot; just include and
* add a compatible value. The bootloader will typically populate the memory
* node.
*/
/ {
#address-cells = <2>;
#size-cells = <1>;
chosen { };
aliases { };
memory { device_type = "memory"; reg = <0 0 0>; };
};
...@@ -23,6 +23,7 @@ CONFIG_MODULES=y ...@@ -23,6 +23,7 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set # CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_VEXPRESS=y
CONFIG_SMP=y CONFIG_SMP=y
CONFIG_PREEMPT_VOLUNTARY=y CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_CMDLINE="console=ttyAMA0" CONFIG_CMDLINE="console=ttyAMA0"
...@@ -47,11 +48,14 @@ CONFIG_BLK_DEV_SD=y ...@@ -47,11 +48,14 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
CONFIG_MII=y CONFIG_MII=y
CONFIG_SMC91X=y
# CONFIG_WLAN is not set # CONFIG_WLAN is not set
CONFIG_INPUT_EVDEV=y CONFIG_INPUT_EVDEV=y
# CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_I8042 is not set
# CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_SERPORT is not set
CONFIG_LEGACY_PTY_COUNT=16 CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
# CONFIG_HW_RANDOM is not set # CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set # CONFIG_HWMON is not set
CONFIG_FB=y CONFIG_FB=y
......
...@@ -39,7 +39,6 @@ generic-y += shmbuf.h ...@@ -39,7 +39,6 @@ generic-y += shmbuf.h
generic-y += sizes.h generic-y += sizes.h
generic-y += socket.h generic-y += socket.h
generic-y += sockios.h generic-y += sockios.h
generic-y += string.h
generic-y += switch_to.h generic-y += switch_to.h
generic-y += swab.h generic-y += swab.h
generic-y += termbits.h generic-y += termbits.h
...@@ -49,4 +48,5 @@ generic-y += trace_clock.h ...@@ -49,4 +48,5 @@ generic-y += trace_clock.h
generic-y += types.h generic-y += types.h
generic-y += unaligned.h generic-y += unaligned.h
generic-y += user.h generic-y += user.h
generic-y += vga.h
generic-y += xor.h generic-y += xor.h
...@@ -32,6 +32,16 @@ ...@@ -32,6 +32,16 @@
#error only <linux/bitops.h> can be included directly #error only <linux/bitops.h> can be included directly
#endif #endif
/*
* Little endian assembly atomic bitops.
*/
extern void set_bit(int nr, volatile unsigned long *p);
extern void clear_bit(int nr, volatile unsigned long *p);
extern void change_bit(int nr, volatile unsigned long *p);
extern int test_and_set_bit(int nr, volatile unsigned long *p);
extern int test_and_clear_bit(int nr, volatile unsigned long *p);
extern int test_and_change_bit(int nr, volatile unsigned long *p);
#include <asm-generic/bitops/builtin-__ffs.h> #include <asm-generic/bitops/builtin-__ffs.h>
#include <asm-generic/bitops/builtin-ffs.h> #include <asm-generic/bitops/builtin-ffs.h>
#include <asm-generic/bitops/builtin-__fls.h> #include <asm-generic/bitops/builtin-__fls.h>
...@@ -45,9 +55,13 @@ ...@@ -45,9 +55,13 @@
#include <asm-generic/bitops/hweight.h> #include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h> #include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/atomic.h>
#include <asm-generic/bitops/non-atomic.h> #include <asm-generic/bitops/non-atomic.h>
#include <asm-generic/bitops/le.h> #include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>
/*
* Ext2 is defined to use little-endian byte ordering.
*/
#define ext2_set_bit_atomic(lock, nr, p) test_and_set_bit_le(nr, p)
#define ext2_clear_bit_atomic(lock, nr, p) test_and_clear_bit_le(nr, p)
#endif /* __ASM_BITOPS_H */ #endif /* __ASM_BITOPS_H */
...@@ -170,4 +170,7 @@ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, ...@@ -170,4 +170,7 @@ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
(unsigned long)(n), \ (unsigned long)(n), \
sizeof(*(ptr)))) sizeof(*(ptr))))
#define cmpxchg64(ptr,o,n) cmpxchg((ptr),(o),(n))
#define cmpxchg64_local(ptr,o,n) cmpxchg_local((ptr),(o),(n))
#endif /* __ASM_CMPXCHG_H */ #endif /* __ASM_CMPXCHG_H */
...@@ -35,14 +35,16 @@ typedef s32 compat_clock_t; ...@@ -35,14 +35,16 @@ typedef s32 compat_clock_t;
typedef s32 compat_pid_t; typedef s32 compat_pid_t;
typedef u32 __compat_uid_t; typedef u32 __compat_uid_t;
typedef u32 __compat_gid_t; typedef u32 __compat_gid_t;
typedef u16 __compat_uid16_t;
typedef u16 __compat_gid16_t;
typedef u32 __compat_uid32_t; typedef u32 __compat_uid32_t;
typedef u32 __compat_gid32_t; typedef u32 __compat_gid32_t;
typedef u32 compat_mode_t; typedef u16 compat_mode_t;
typedef u32 compat_ino_t; typedef u32 compat_ino_t;
typedef u32 compat_dev_t; typedef u32 compat_dev_t;
typedef s32 compat_off_t; typedef s32 compat_off_t;
typedef s64 compat_loff_t; typedef s64 compat_loff_t;
typedef s16 compat_nlink_t; typedef s32 compat_nlink_t;
typedef u16 compat_ipc_pid_t; typedef u16 compat_ipc_pid_t;
typedef s32 compat_daddr_t; typedef s32 compat_daddr_t;
typedef u32 compat_caddr_t; typedef u32 compat_caddr_t;
...@@ -50,9 +52,11 @@ typedef __kernel_fsid_t compat_fsid_t; ...@@ -50,9 +52,11 @@ typedef __kernel_fsid_t compat_fsid_t;
typedef s32 compat_key_t; typedef s32 compat_key_t;
typedef s32 compat_timer_t; typedef s32 compat_timer_t;
typedef s16 compat_short_t;
typedef s32 compat_int_t; typedef s32 compat_int_t;
typedef s32 compat_long_t; typedef s32 compat_long_t;
typedef s64 compat_s64; typedef s64 compat_s64;
typedef u16 compat_ushort_t;
typedef u32 compat_uint_t; typedef u32 compat_uint_t;
typedef u32 compat_ulong_t; typedef u32 compat_ulong_t;
typedef u64 compat_u64; typedef u64 compat_u64;
...@@ -72,20 +76,20 @@ struct compat_stat { ...@@ -72,20 +76,20 @@ struct compat_stat {
compat_dev_t st_dev; compat_dev_t st_dev;
compat_ino_t st_ino; compat_ino_t st_ino;
compat_mode_t st_mode; compat_mode_t st_mode;
compat_nlink_t st_nlink; compat_ushort_t st_nlink;
__compat_uid32_t st_uid; __compat_uid16_t st_uid;
__compat_gid32_t st_gid; __compat_gid16_t st_gid;
compat_dev_t st_rdev; compat_dev_t st_rdev;
compat_off_t st_size; compat_off_t st_size;
compat_off_t st_blksize; compat_off_t st_blksize;
compat_off_t st_blocks; compat_off_t st_blocks;
compat_time_t st_atime; compat_time_t st_atime;
u32 st_atime_nsec; compat_ulong_t st_atime_nsec;
compat_time_t st_mtime; compat_time_t st_mtime;
u32 st_mtime_nsec; compat_ulong_t st_mtime_nsec;
compat_time_t st_ctime; compat_time_t st_ctime;
u32 st_ctime_nsec; compat_ulong_t st_ctime_nsec;
u32 __unused4[2]; compat_ulong_t __unused4[2];
}; };
struct compat_flock { struct compat_flock {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define __ASM_CPUTYPE_H #define __ASM_CPUTYPE_H
#define ID_MIDR_EL1 "midr_el1" #define ID_MIDR_EL1 "midr_el1"
#define ID_MPIDR_EL1 "mpidr_el1"
#define ID_CTR_EL0 "ctr_el0" #define ID_CTR_EL0 "ctr_el0"
#define ID_AA64PFR0_EL1 "id_aa64pfr0_el1" #define ID_AA64PFR0_EL1 "id_aa64pfr0_el1"
...@@ -25,12 +26,24 @@ ...@@ -25,12 +26,24 @@
#define ID_AA64ISAR0_EL1 "id_aa64isar0_el1" #define ID_AA64ISAR0_EL1 "id_aa64isar0_el1"
#define ID_AA64MMFR0_EL1 "id_aa64mmfr0_el1" #define ID_AA64MMFR0_EL1 "id_aa64mmfr0_el1"
#define INVALID_HWID ULONG_MAX
#define MPIDR_HWID_BITMASK 0xff00ffffff
#define read_cpuid(reg) ({ \ #define read_cpuid(reg) ({ \
u64 __val; \ u64 __val; \
asm("mrs %0, " reg : "=r" (__val)); \ asm("mrs %0, " reg : "=r" (__val)); \
__val; \ __val; \
}) })
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_PART_AEM_V8 0xD0F0
#define ARM_CPU_PART_FOUNDATION 0xD000
#define ARM_CPU_PART_CORTEX_A57 0xD070
#ifndef __ASSEMBLY__
/* /*
* The CPU ID never changes at run time, so we might as well tell the * The CPU ID never changes at run time, so we might as well tell the
* compiler that it's constant. Use this function to read the CPU ID * compiler that it's constant. Use this function to read the CPU ID
...@@ -41,9 +54,26 @@ static inline u32 __attribute_const__ read_cpuid_id(void) ...@@ -41,9 +54,26 @@ static inline u32 __attribute_const__ read_cpuid_id(void)
return read_cpuid(ID_MIDR_EL1); return read_cpuid(ID_MIDR_EL1);
} }
static inline u64 __attribute_const__ read_cpuid_mpidr(void)
{
return read_cpuid(ID_MPIDR_EL1);
}
static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
{
return (read_cpuid_id() & 0xFF000000) >> 24;
}
static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
{
return (read_cpuid_id() & 0xFFF0);
}
static inline u32 __attribute_const__ read_cpuid_cachetype(void) static inline u32 __attribute_const__ read_cpuid_cachetype(void)
{ {
return read_cpuid(ID_CTR_EL0); return read_cpuid(ID_CTR_EL0);
} }
#endif /* __ASSEMBLY__ */
#endif #endif
/*
* Copyright (C) 2013 - ARM Ltd
* Author: Marc Zyngier <marc.zyngier@arm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_ESR_H
#define __ASM_ESR_H
#define ESR_EL1_EC_SHIFT (26)
#define ESR_EL1_IL (1U << 25)
#define ESR_EL1_EC_UNKNOWN (0x00)
#define ESR_EL1_EC_WFI (0x01)
#define ESR_EL1_EC_CP15_32 (0x03)
#define ESR_EL1_EC_CP15_64 (0x04)
#define ESR_EL1_EC_CP14_MR (0x05)
#define ESR_EL1_EC_CP14_LS (0x06)
#define ESR_EL1_EC_FP_ASIMD (0x07)
#define ESR_EL1_EC_CP10_ID (0x08)
#define ESR_EL1_EC_CP14_64 (0x0C)
#define ESR_EL1_EC_ILL_ISS (0x0E)
#define ESR_EL1_EC_SVC32 (0x11)
#define ESR_EL1_EC_SVC64 (0x15)
#define ESR_EL1_EC_SYS64 (0x18)
#define ESR_EL1_EC_IABT_EL0 (0x20)
#define ESR_EL1_EC_IABT_EL1 (0x21)
#define ESR_EL1_EC_PC_ALIGN (0x22)
#define ESR_EL1_EC_DABT_EL0 (0x24)
#define ESR_EL1_EC_DABT_EL1 (0x25)
#define ESR_EL1_EC_SP_ALIGN (0x26)
#define ESR_EL1_EC_FP_EXC32 (0x28)
#define ESR_EL1_EC_FP_EXC64 (0x2C)
#define ESR_EL1_EC_SERRROR (0x2F)
#define ESR_EL1_EC_BREAKPT_EL0 (0x30)
#define ESR_EL1_EC_BREAKPT_EL1 (0x31)
#define ESR_EL1_EC_SOFTSTP_EL0 (0x32)
#define ESR_EL1_EC_SOFTSTP_EL1 (0x33)
#define ESR_EL1_EC_WATCHPT_EL0 (0x34)
#define ESR_EL1_EC_WATCHPT_EL1 (0x35)
#define ESR_EL1_EC_BKPT32 (0x38)
#define ESR_EL1_EC_BRK64 (0x3C)
#endif /* __ASM_ESR_H */
...@@ -19,5 +19,6 @@ ...@@ -19,5 +19,6 @@
#define __ASM_EXCEPTION_H #define __ASM_EXCEPTION_H
#define __exception __attribute__((section(".exception.text"))) #define __exception __attribute__((section(".exception.text")))
#define __exception_irq_entry __exception
#endif /* __ASM_EXCEPTION_H */ #endif /* __ASM_EXCEPTION_H */
...@@ -49,4 +49,9 @@ static inline void ack_bad_irq(unsigned int irq) ...@@ -49,4 +49,9 @@ static inline void ack_bad_irq(unsigned int irq)
extern void handle_IRQ(unsigned int, struct pt_regs *); extern void handle_IRQ(unsigned int, struct pt_regs *);
/*
* No arch-specific IRQ flags.
*/
#define set_irq_flags(irq, flags)
#endif /* __ASM_HARDIRQ_H */ #endif /* __ASM_HARDIRQ_H */
...@@ -92,10 +92,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) ...@@ -92,10 +92,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
#define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; }) #define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; })
#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; }) #define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; })
#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; }) #define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; })
#define readq_relaxed(c) ({ u64 __v = le64_to_cpu((__force __le64)__raw_readq(c)); __v; })
#define writeb_relaxed(v,c) ((void)__raw_writeb((v),(c))) #define writeb_relaxed(v,c) ((void)__raw_writeb((v),(c)))
#define writew_relaxed(v,c) ((void)__raw_writew((__force u16)cpu_to_le16(v),(c))) #define writew_relaxed(v,c) ((void)__raw_writew((__force u16)cpu_to_le16(v),(c)))
#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) #define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c)))
#define writeq_relaxed(v,c) ((void)__raw_writeq((__force u64)cpu_to_le64(v),(c)))
/* /*
* I/O memory access primitives. Reads are ordered relative to any * I/O memory access primitives. Reads are ordered relative to any
...@@ -105,10 +107,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) ...@@ -105,10 +107,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; })
#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
#define readq(c) ({ u64 __v = readq_relaxed(c); __iormb(); __v; })
#define writeb(v,c) ({ __iowmb(); writeb_relaxed((v),(c)); }) #define writeb(v,c) ({ __iowmb(); writeb_relaxed((v),(c)); })
#define writew(v,c) ({ __iowmb(); writew_relaxed((v),(c)); }) #define writew(v,c) ({ __iowmb(); writew_relaxed((v),(c)); })
#define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); }) #define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); })
#define writeq(v,c) ({ __iowmb(); writeq_relaxed((v),(c)); })
/* /*
* I/O port access primitives. * I/O port access primitives.
......
...@@ -4,5 +4,6 @@ ...@@ -4,5 +4,6 @@
#include <asm-generic/irq.h> #include <asm-generic/irq.h>
extern void (*handle_arch_irq)(struct pt_regs *); extern void (*handle_arch_irq)(struct pt_regs *);
extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
#endif #endif
/* /*
* Copyright (C) 2012 ARM Limited * Definitions specific to SMP platforms.
* *
* This program is free software; you can redistribute it and/or modify * Copyright (C) 2013 ARM Ltd.
*
* 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
...@@ -14,12 +16,15 @@ ...@@ -14,12 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/kernel.h> #ifndef __ASM_SMP_PLAT_H
#include <linux/spinlock.h> #define __ASM_SMP_PLAT_H
#include <linux/atomic.h>
#include <asm/types.h>
/*
* Logical CPU mapping.
*/
extern u64 __cpu_logical_map[NR_CPUS];
#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
#ifdef CONFIG_SMP #endif /* __ASM_SMP_PLAT_H */
arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
[0 ... (ATOMIC_HASH_SIZE-1)] = __ARCH_SPIN_LOCK_UNLOCKED
};
#endif
/*
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_STRING_H
#define __ASM_STRING_H
#define __HAVE_ARCH_STRRCHR
extern char *strrchr(const char *, int c);
#define __HAVE_ARCH_STRCHR
extern char *strchr(const char *, int c);
#define __HAVE_ARCH_MEMCPY
extern void *memcpy(void *, const void *, __kernel_size_t);
#define __HAVE_ARCH_MEMMOVE
extern void *memmove(void *, const void *, __kernel_size_t);
#define __HAVE_ARCH_MEMCHR
extern void *memchr(const void *, int, __kernel_size_t);
#define __HAVE_ARCH_MEMSET
extern void *memset(void *, int, __kernel_size_t);
#endif
...@@ -39,10 +39,21 @@ EXPORT_SYMBOL(__copy_from_user); ...@@ -39,10 +39,21 @@ EXPORT_SYMBOL(__copy_from_user);
EXPORT_SYMBOL(__copy_to_user); EXPORT_SYMBOL(__copy_to_user);
EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(__clear_user);
/* bitops */
#ifdef CONFIG_SMP
EXPORT_SYMBOL(__atomic_hash);
#endif
/* physical memory */ /* physical memory */
EXPORT_SYMBOL(memstart_addr); EXPORT_SYMBOL(memstart_addr);
/* string / mem functions */
EXPORT_SYMBOL(strchr);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memchr);
/* atomic bitops */
EXPORT_SYMBOL(set_bit);
EXPORT_SYMBOL(test_and_set_bit);
EXPORT_SYMBOL(clear_bit);
EXPORT_SYMBOL(test_and_clear_bit);
EXPORT_SYMBOL(change_bit);
EXPORT_SYMBOL(test_and_change_bit);
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/amba/serial.h> #include <linux/amba/serial.h>
#include <linux/serial_reg.h>
static void __iomem *early_base; static void __iomem *early_base;
static void (*printch)(char ch); static void (*printch)(char ch);
...@@ -40,6 +41,37 @@ static void pl011_printch(char ch) ...@@ -40,6 +41,37 @@ static void pl011_printch(char ch)
; ;
} }
/*
* Semihosting-based debug console
*/
static void smh_printch(char ch)
{
asm volatile("mov x1, %0\n"
"mov x0, #3\n"
"hlt 0xf000\n"
: : "r" (&ch) : "x0", "x1", "memory");
}
/*
* 8250/16550 (8-bit aligned registers) single character TX.
*/
static void uart8250_8bit_printch(char ch)
{
while (!(readb_relaxed(early_base + UART_LSR) & UART_LSR_THRE))
;
writeb_relaxed(ch, early_base + UART_TX);
}
/*
* 8250/16550 (32-bit aligned registers) single character TX.
*/
static void uart8250_32bit_printch(char ch)
{
while (!(readl_relaxed(early_base + (UART_LSR << 2)) & UART_LSR_THRE))
;
writel_relaxed(ch, early_base + (UART_TX << 2));
}
struct earlycon_match { struct earlycon_match {
const char *name; const char *name;
void (*printch)(char ch); void (*printch)(char ch);
...@@ -47,6 +79,9 @@ struct earlycon_match { ...@@ -47,6 +79,9 @@ struct earlycon_match {
static const struct earlycon_match earlycon_match[] __initconst = { static const struct earlycon_match earlycon_match[] __initconst = {
{ .name = "pl011", .printch = pl011_printch, }, { .name = "pl011", .printch = pl011_printch, },
{ .name = "smh", .printch = smh_printch, },
{ .name = "uart8250-8bit", .printch = uart8250_8bit_printch, },
{ .name = "uart8250-32bit", .printch = uart8250_32bit_printch, },
{} {}
}; };
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/esr.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/unistd32.h> #include <asm/unistd32.h>
...@@ -239,18 +240,18 @@ ENDPROC(el1_error_invalid) ...@@ -239,18 +240,18 @@ ENDPROC(el1_error_invalid)
el1_sync: el1_sync:
kernel_entry 1 kernel_entry 1
mrs x1, esr_el1 // read the syndrome register mrs x1, esr_el1 // read the syndrome register
lsr x24, x1, #26 // exception class lsr x24, x1, #ESR_EL1_EC_SHIFT // exception class
cmp x24, #0x25 // data abort in EL1 cmp x24, #ESR_EL1_EC_DABT_EL1 // data abort in EL1
b.eq el1_da b.eq el1_da
cmp x24, #0x18 // configurable trap cmp x24, #ESR_EL1_EC_SYS64 // configurable trap
b.eq el1_undef b.eq el1_undef
cmp x24, #0x26 // stack alignment exception cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception
b.eq el1_sp_pc b.eq el1_sp_pc
cmp x24, #0x22 // pc alignment exception cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception
b.eq el1_sp_pc b.eq el1_sp_pc
cmp x24, #0x00 // unknown exception in EL1 cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL1
b.eq el1_undef b.eq el1_undef
cmp x24, #0x30 // debug exception in EL1 cmp x24, #ESR_EL1_EC_BREAKPT_EL1 // debug exception in EL1
b.ge el1_dbg b.ge el1_dbg
b el1_inv b el1_inv
el1_da: el1_da:
...@@ -346,27 +347,27 @@ el1_preempt: ...@@ -346,27 +347,27 @@ el1_preempt:
el0_sync: el0_sync:
kernel_entry 0 kernel_entry 0
mrs x25, esr_el1 // read the syndrome register mrs x25, esr_el1 // read the syndrome register
lsr x24, x25, #26 // exception class lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class
cmp x24, #0x15 // SVC in 64-bit state cmp x24, #ESR_EL1_EC_SVC64 // SVC in 64-bit state
b.eq el0_svc b.eq el0_svc
adr lr, ret_from_exception adr lr, ret_from_exception
cmp x24, #0x24 // data abort in EL0 cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0
b.eq el0_da b.eq el0_da
cmp x24, #0x20 // instruction abort in EL0 cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0
b.eq el0_ia b.eq el0_ia
cmp x24, #0x07 // FP/ASIMD access cmp x24, #ESR_EL1_EC_FP_ASIMD // FP/ASIMD access
b.eq el0_fpsimd_acc b.eq el0_fpsimd_acc
cmp x24, #0x2c // FP/ASIMD exception cmp x24, #ESR_EL1_EC_FP_EXC64 // FP/ASIMD exception
b.eq el0_fpsimd_exc b.eq el0_fpsimd_exc
cmp x24, #0x18 // configurable trap cmp x24, #ESR_EL1_EC_SYS64 // configurable trap
b.eq el0_undef b.eq el0_undef
cmp x24, #0x26 // stack alignment exception cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception
b.eq el0_sp_pc b.eq el0_sp_pc
cmp x24, #0x22 // pc alignment exception cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception
b.eq el0_sp_pc b.eq el0_sp_pc
cmp x24, #0x00 // unknown exception in EL0 cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef b.eq el0_undef
cmp x24, #0x30 // debug exception in EL0 cmp x24, #ESR_EL1_EC_BREAKPT_EL0 // debug exception in EL0
b.ge el0_dbg b.ge el0_dbg
b el0_inv b el0_inv
...@@ -375,21 +376,21 @@ el0_sync: ...@@ -375,21 +376,21 @@ el0_sync:
el0_sync_compat: el0_sync_compat:
kernel_entry 0, 32 kernel_entry 0, 32
mrs x25, esr_el1 // read the syndrome register mrs x25, esr_el1 // read the syndrome register
lsr x24, x25, #26 // exception class lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class
cmp x24, #0x11 // SVC in 32-bit state cmp x24, #ESR_EL1_EC_SVC32 // SVC in 32-bit state
b.eq el0_svc_compat b.eq el0_svc_compat
adr lr, ret_from_exception adr lr, ret_from_exception
cmp x24, #0x24 // data abort in EL0 cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0
b.eq el0_da b.eq el0_da
cmp x24, #0x20 // instruction abort in EL0 cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0
b.eq el0_ia b.eq el0_ia
cmp x24, #0x07 // FP/ASIMD access cmp x24, #ESR_EL1_EC_FP_ASIMD // FP/ASIMD access
b.eq el0_fpsimd_acc b.eq el0_fpsimd_acc
cmp x24, #0x28 // FP/ASIMD exception cmp x24, #ESR_EL1_EC_FP_EXC32 // FP/ASIMD exception
b.eq el0_fpsimd_exc b.eq el0_fpsimd_exc
cmp x24, #0x00 // unknown exception in EL0 cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL0
b.eq el0_undef b.eq el0_undef
cmp x24, #0x30 // debug exception in EL0 cmp x24, #ESR_EL1_EC_BREAKPT_EL0 // debug exception in EL0
b.ge el0_dbg b.ge el0_dbg
b el0_inv b el0_inv
el0_svc_compat: el0_svc_compat:
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/cputype.h>
#include <asm/memory.h> #include <asm/memory.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/pgtable-hwdef.h> #include <asm/pgtable-hwdef.h>
...@@ -229,7 +230,8 @@ ENTRY(secondary_holding_pen) ...@@ -229,7 +230,8 @@ ENTRY(secondary_holding_pen)
bl __calc_phys_offset // x24=phys offset bl __calc_phys_offset // x24=phys offset
bl el2_setup // Drop to EL1 bl el2_setup // Drop to EL1
mrs x0, mpidr_el1 mrs x0, mpidr_el1
and x0, x0, #15 // CPU number ldr x1, =MPIDR_HWID_BITMASK
and x0, x0, x1
adr x1, 1b adr x1, 1b
ldp x2, x3, [x1] ldp x2, x3, [x1]
sub x1, x1, x2 sub x1, x1, x2
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/of_irq.h> #include <linux/irqchip.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
...@@ -67,18 +67,17 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs) ...@@ -67,18 +67,17 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
set_irq_regs(old_regs); set_irq_regs(old_regs);
} }
/* void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
* Interrupt controllers supported by the kernel. {
*/ if (handle_arch_irq)
static const struct of_device_id intctrl_of_match[] __initconst = { return;
/* IRQ controllers { .compatible, .data } info to go here */
{} handle_arch_irq = handle_irq;
}; }
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
of_irq_init(intctrl_of_match); irqchip_init();
if (!handle_arch_irq) if (!handle_arch_irq)
panic("No interrupt controller found."); panic("No interrupt controller found.");
} }
...@@ -278,11 +278,17 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -278,11 +278,17 @@ struct task_struct *__switch_to(struct task_struct *prev,
fpsimd_thread_switch(next); fpsimd_thread_switch(next);
tls_thread_switch(next); tls_thread_switch(next);
hw_breakpoint_thread_switch(next); hw_breakpoint_thread_switch(next);
contextidr_thread_switch(next);
/*
* Complete any pending TLB or cache maintenance on this CPU in case
* the thread migrates to a different CPU.
*/
dsb();
/* the actual thread switch */ /* the actual thread switch */
last = cpu_switch_to(prev, next); last = cpu_switch_to(prev, next);
contextidr_thread_switch(next);
return last; return last;
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/clk-provider.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>
...@@ -46,6 +47,7 @@ ...@@ -46,6 +47,7 @@
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/smp_plat.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/traps.h> #include <asm/traps.h>
...@@ -240,6 +242,8 @@ static void __init request_standard_resources(void) ...@@ -240,6 +242,8 @@ static void __init request_standard_resources(void)
} }
} }
u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
setup_processor(); setup_processor();
...@@ -264,6 +268,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -264,6 +268,7 @@ void __init setup_arch(char **cmdline_p)
psci_init(); psci_init();
cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
smp_init_cpus(); smp_init_cpus();
#endif #endif
...@@ -277,6 +282,13 @@ void __init setup_arch(char **cmdline_p) ...@@ -277,6 +282,13 @@ void __init setup_arch(char **cmdline_p)
#endif #endif
} }
static int __init arm64_of_clk_init(void)
{
of_clk_init(NULL);
return 0;
}
arch_initcall(arm64_of_clk_init);
static DEFINE_PER_CPU(struct cpu, cpu_data); static DEFINE_PER_CPU(struct cpu, cpu_data);
static int __init topology_init(void) static int __init topology_init(void)
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/smp_plat.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
...@@ -53,7 +54,7 @@ ...@@ -53,7 +54,7 @@
* where to place its SVC stack * where to place its SVC stack
*/ */
struct secondary_data secondary_data; struct secondary_data secondary_data;
volatile unsigned long secondary_holding_pen_release = -1; volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
enum ipi_msg_type { enum ipi_msg_type {
IPI_RESCHEDULE, IPI_RESCHEDULE,
...@@ -70,7 +71,7 @@ static DEFINE_RAW_SPINLOCK(boot_lock); ...@@ -70,7 +71,7 @@ static DEFINE_RAW_SPINLOCK(boot_lock);
* in coherency or not. This is necessary for the hotplug code to work * in coherency or not. This is necessary for the hotplug code to work
* reliably. * reliably.
*/ */
static void __cpuinit write_pen_release(int val) static void __cpuinit write_pen_release(u64 val)
{ {
void *start = (void *)&secondary_holding_pen_release; void *start = (void *)&secondary_holding_pen_release;
unsigned long size = sizeof(secondary_holding_pen_release); unsigned long size = sizeof(secondary_holding_pen_release);
...@@ -96,7 +97,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -96,7 +97,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
/* /*
* Update the pen release flag. * Update the pen release flag.
*/ */
write_pen_release(cpu); write_pen_release(cpu_logical_map(cpu));
/* /*
* Send an event, causing the secondaries to read pen_release. * Send an event, causing the secondaries to read pen_release.
...@@ -105,7 +106,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -105,7 +106,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
timeout = jiffies + (1 * HZ); timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) { while (time_before(jiffies, timeout)) {
if (secondary_holding_pen_release == -1UL) if (secondary_holding_pen_release == INVALID_HWID)
break; break;
udelay(10); udelay(10);
} }
...@@ -116,7 +117,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -116,7 +117,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
*/ */
raw_spin_unlock(&boot_lock); raw_spin_unlock(&boot_lock);
return secondary_holding_pen_release != -1 ? -ENOSYS : 0; return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0;
} }
static DECLARE_COMPLETION(cpu_running); static DECLARE_COMPLETION(cpu_running);
...@@ -190,7 +191,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) ...@@ -190,7 +191,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
* Let the primary processor know we're out of the * Let the primary processor know we're out of the
* pen, then head off into the C entry point * pen, then head off into the C entry point
*/ */
write_pen_release(-1); write_pen_release(INVALID_HWID);
/* /*
* Synchronise with the boot thread. * Synchronise with the boot thread.
...@@ -244,11 +245,11 @@ static const struct smp_enable_ops *smp_enable_ops[NR_CPUS]; ...@@ -244,11 +245,11 @@ static const struct smp_enable_ops *smp_enable_ops[NR_CPUS];
static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name) static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
{ {
const struct smp_enable_ops *ops = enable_ops[0]; const struct smp_enable_ops **ops = enable_ops;
while (ops) { while (*ops) {
if (!strcmp(name, ops->name)) if (!strcmp(name, (*ops)->name))
return ops; return *ops;
ops++; ops++;
} }
...@@ -257,15 +258,80 @@ static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name) ...@@ -257,15 +258,80 @@ static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
} }
/* /*
* Enumerate the possible CPU set from the device tree. * Enumerate the possible CPU set from the device tree and build the
* cpu logical map array containing MPIDR values related to logical
* cpus. Assumes that cpu_logical_map(0) has already been initialized.
*/ */
void __init smp_init_cpus(void) void __init smp_init_cpus(void)
{ {
const char *enable_method; const char *enable_method;
struct device_node *dn = NULL; struct device_node *dn = NULL;
int cpu = 0; int i, cpu = 1;
bool bootcpu_valid = false;
while ((dn = of_find_node_by_type(dn, "cpu"))) { while ((dn = of_find_node_by_type(dn, "cpu"))) {
const u32 *cell;
u64 hwid;
/*
* A cpu node with missing "reg" property is
* considered invalid to build a cpu_logical_map
* entry.
*/
cell = of_get_property(dn, "reg", NULL);
if (!cell) {
pr_err("%s: missing reg property\n", dn->full_name);
goto next;
}
hwid = of_read_number(cell, of_n_addr_cells(dn));
/*
* Non affinity bits must be set to 0 in the DT
*/
if (hwid & ~MPIDR_HWID_BITMASK) {
pr_err("%s: invalid reg property\n", dn->full_name);
goto next;
}
/*
* Duplicate MPIDRs are a recipe for disaster. Scan
* all initialized entries and check for
* duplicates. If any is found just ignore the cpu.
* cpu_logical_map was initialized to INVALID_HWID to
* avoid matching valid MPIDR values.
*/
for (i = 1; (i < cpu) && (i < NR_CPUS); i++) {
if (cpu_logical_map(i) == hwid) {
pr_err("%s: duplicate cpu reg properties in the DT\n",
dn->full_name);
goto next;
}
}
/*
* The numbering scheme requires that the boot CPU
* must be assigned logical id 0. Record it so that
* the logical map built from DT is validated and can
* be used.
*/
if (hwid == cpu_logical_map(0)) {
if (bootcpu_valid) {
pr_err("%s: duplicate boot cpu reg property in DT\n",
dn->full_name);
goto next;
}
bootcpu_valid = true;
/*
* cpu_logical_map has already been
* initialized and the boot cpu doesn't need
* the enable-method so continue without
* incrementing cpu.
*/
continue;
}
if (cpu >= NR_CPUS) if (cpu >= NR_CPUS)
goto next; goto next;
...@@ -274,22 +340,24 @@ void __init smp_init_cpus(void) ...@@ -274,22 +340,24 @@ void __init smp_init_cpus(void)
*/ */
enable_method = of_get_property(dn, "enable-method", NULL); enable_method = of_get_property(dn, "enable-method", NULL);
if (!enable_method) { if (!enable_method) {
pr_err("CPU %d: missing enable-method property\n", cpu); pr_err("%s: missing enable-method property\n",
dn->full_name);
goto next; goto next;
} }
smp_enable_ops[cpu] = smp_get_enable_ops(enable_method); smp_enable_ops[cpu] = smp_get_enable_ops(enable_method);
if (!smp_enable_ops[cpu]) { if (!smp_enable_ops[cpu]) {
pr_err("CPU %d: invalid enable-method property: %s\n", pr_err("%s: invalid enable-method property: %s\n",
cpu, enable_method); dn->full_name, enable_method);
goto next; goto next;
} }
if (smp_enable_ops[cpu]->init_cpu(dn, cpu)) if (smp_enable_ops[cpu]->init_cpu(dn, cpu))
goto next; goto next;
set_cpu_possible(cpu, true); pr_debug("cpu logical map 0x%llx\n", hwid);
cpu_logical_map(cpu) = hwid;
next: next:
cpu++; cpu++;
} }
...@@ -298,6 +366,19 @@ void __init smp_init_cpus(void) ...@@ -298,6 +366,19 @@ void __init smp_init_cpus(void)
if (cpu > NR_CPUS) if (cpu > NR_CPUS)
pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n", pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n",
cpu, NR_CPUS); cpu, NR_CPUS);
if (!bootcpu_valid) {
pr_err("DT missing boot CPU MPIDR, not enabling secondaries\n");
return;
}
/*
* All the cpus that made it to the cpu_logical_map have been
* validated so set them as possible cpus.
*/
for (i = 0; i < NR_CPUS; i++)
if (cpu_logical_map(i) != INVALID_HWID)
set_cpu_possible(i, true);
} }
void __init smp_prepare_cpus(unsigned int max_cpus) void __init smp_prepare_cpus(unsigned int max_cpus)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <asm/psci.h> #include <asm/psci.h>
#include <asm/smp_plat.h>
static int __init smp_psci_init_cpu(struct device_node *dn, int cpu) static int __init smp_psci_init_cpu(struct device_node *dn, int cpu)
{ {
...@@ -36,7 +37,7 @@ static int __init smp_psci_prepare_cpu(int cpu) ...@@ -36,7 +37,7 @@ static int __init smp_psci_prepare_cpu(int cpu)
return -ENODEV; return -ENODEV;
} }
err = psci_ops.cpu_on(cpu, __pa(secondary_holding_pen)); err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_holding_pen));
if (err) { if (err) {
pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err); pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err);
return err; return err;
...@@ -47,6 +48,6 @@ static int __init smp_psci_prepare_cpu(int cpu) ...@@ -47,6 +48,6 @@ static int __init smp_psci_prepare_cpu(int cpu)
const struct smp_enable_ops smp_psci_ops __initconst = { const struct smp_enable_ops smp_psci_ops __initconst = {
.name = "psci", .name = "psci",
.init_cpu = smp_psci_init_cpu, .init_cpu = smp_psci_init_cpu,
.prepare_cpu = smp_psci_prepare_cpu, .prepare_cpu = smp_psci_prepare_cpu,
}; };
lib-y := bitops.o delay.o \ lib-y := bitops.o delay.o \
strncpy_from_user.o strnlen_user.o clear_user.o \ strncpy_from_user.o strnlen_user.o clear_user.o \
copy_from_user.o copy_to_user.o copy_in_user.o \ copy_from_user.o copy_to_user.o copy_in_user.o \
copy_page.o clear_page.o copy_page.o clear_page.o \
memchr.o memcpy.o memmove.o memset.o \
strchr.o strrchr.o
/*
* Based on arch/arm/lib/bitops.h
*
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* x0: bits 5:0 bit offset
* bits 63:6 word offset
* x1: address
*/
.macro bitop, name, instr
ENTRY( \name )
and x3, x0, #63 // Get bit offset
eor x0, x0, x3 // Clear low bits
mov x2, #1
add x1, x1, x0, lsr #3 // Get word offset
lsl x3, x2, x3 // Create mask
1: ldxr x2, [x1]
\instr x2, x2, x3
stxr w0, x2, [x1]
cbnz w0, 1b
ret
ENDPROC(\name )
.endm
.macro testop, name, instr
ENTRY( \name )
and x3, x0, #63 // Get bit offset
eor x0, x0, x3 // Clear low bits
mov x2, #1
add x1, x1, x0, lsr #3 // Get word offset
lsl x4, x2, x3 // Create mask
1: ldaxr x2, [x1]
lsr x0, x2, x3 // Save old value of bit
\instr x2, x2, x4 // toggle bit
stlxr w5, x2, [x1]
cbnz w5, 1b
and x0, x0, #1
3: ret
ENDPROC(\name )
.endm
/*
* Atomic bit operations.
*/
bitop change_bit, eor
bitop clear_bit, bic
bitop set_bit, orr
testop test_and_change_bit, eor
testop test_and_clear_bit, bic
testop test_and_set_bit, orr
/*
* Based on arch/arm/lib/memchr.S
*
* Copyright (C) 1995-2000 Russell King
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Find a character in an area of memory.
*
* Parameters:
* x0 - buf
* x1 - c
* x2 - n
* Returns:
* x0 - address of first occurrence of 'c' or 0
*/
ENTRY(memchr)
and w1, w1, #0xff
1: subs x2, x2, #1
b.mi 2f
ldrb w3, [x0], #1
cmp w3, w1
b.ne 1b
sub x0, x0, #1
ret
2: mov x0, #0
ret
ENDPROC(memchr)
/*
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Copy a buffer from src to dest (alignment handled by the hardware)
*
* Parameters:
* x0 - dest
* x1 - src
* x2 - n
* Returns:
* x0 - dest
*/
ENTRY(memcpy)
mov x4, x0
subs x2, x2, #8
b.mi 2f
1: ldr x3, [x1], #8
subs x2, x2, #8
str x3, [x4], #8
b.pl 1b
2: adds x2, x2, #4
b.mi 3f
ldr w3, [x1], #4
sub x2, x2, #4
str w3, [x4], #4
3: adds x2, x2, #2
b.mi 4f
ldrh w3, [x1], #2
sub x2, x2, #2
strh w3, [x4], #2
4: adds x2, x2, #1
b.mi 5f
ldrb w3, [x1]
strb w3, [x4]
5: ret
ENDPROC(memcpy)
/*
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Move a buffer from src to test (alignment handled by the hardware).
* If dest <= src, call memcpy, otherwise copy in reverse order.
*
* Parameters:
* x0 - dest
* x1 - src
* x2 - n
* Returns:
* x0 - dest
*/
ENTRY(memmove)
cmp x0, x1
b.ls memcpy
add x4, x0, x2
add x1, x1, x2
subs x2, x2, #8
b.mi 2f
1: ldr x3, [x1, #-8]!
subs x2, x2, #8
str x3, [x4, #-8]!
b.pl 1b
2: adds x2, x2, #4
b.mi 3f
ldr w3, [x1, #-4]!
sub x2, x2, #4
str w3, [x4, #-4]!
3: adds x2, x2, #2
b.mi 4f
ldrh w3, [x1, #-2]!
sub x2, x2, #2
strh w3, [x4, #-2]!
4: adds x2, x2, #1
b.mi 5f
ldrb w3, [x1, #-1]
strb w3, [x4, #-1]
5: ret
ENDPROC(memmove)
/*
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Fill in the buffer with character c (alignment handled by the hardware)
*
* Parameters:
* x0 - buf
* x1 - c
* x2 - n
* Returns:
* x0 - buf
*/
ENTRY(memset)
mov x4, x0
and w1, w1, #0xff
orr w1, w1, w1, lsl #8
orr w1, w1, w1, lsl #16
orr x1, x1, x1, lsl #32
subs x2, x2, #8
b.mi 2f
1: str x1, [x4], #8
subs x2, x2, #8
b.pl 1b
2: adds x2, x2, #4
b.mi 3f
sub x2, x2, #4
str w1, [x4], #4
3: adds x2, x2, #2
b.mi 4f
sub x2, x2, #2
strh w1, [x4], #2
4: adds x2, x2, #1
b.mi 5f
strb w1, [x4]
5: ret
ENDPROC(memset)
/*
* Based on arch/arm/lib/strchr.S
*
* Copyright (C) 1995-2000 Russell King
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Find the first occurrence of a character in a string.
*
* Parameters:
* x0 - str
* x1 - c
* Returns:
* x0 - address of first occurrence of 'c' or 0
*/
ENTRY(strchr)
and w1, w1, #0xff
1: ldrb w2, [x0], #1
cmp w2, w1
ccmp w2, wzr, #4, ne
b.ne 1b
sub x0, x0, #1
cmp w2, w1
csel x0, x0, xzr, eq
ret
ENDPROC(strchr)
/*
* Based on arch/arm/lib/strrchr.S
*
* Copyright (C) 1995-2000 Russell King
* Copyright (C) 2013 ARM Ltd.
*
* 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 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* Find the last occurrence of a character in a string.
*
* Parameters:
* x0 - str
* x1 - c
* Returns:
* x0 - address of last occurrence of 'c' or 0
*/
ENTRY(strrchr)
mov x3, #0
and w1, w1, #0xff
1: ldrb w2, [x0], #1
cbz w2, 2f
cmp w2, w1
b.ne 1b
sub x3, x0, #1
b 1b
2: mov x0, x3
ret
ENDPROC(strrchr)
...@@ -57,16 +57,16 @@ void show_pte(struct mm_struct *mm, unsigned long addr) ...@@ -57,16 +57,16 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
if (pgd_none_or_clear_bad(pgd)) if (pgd_none(*pgd) || pgd_bad(*pgd))
break; break;
pud = pud_offset(pgd, addr); pud = pud_offset(pgd, addr);
if (pud_none_or_clear_bad(pud)) if (pud_none(*pud) || pud_bad(*pud))
break; break;
pmd = pmd_offset(pud, addr); pmd = pmd_offset(pud, addr);
printk(", *pmd=%016llx", pmd_val(*pmd)); printk(", *pmd=%016llx", pmd_val(*pmd));
if (pmd_none_or_clear_bad(pmd)) if (pmd_none(*pmd) || pmd_bad(*pmd))
break; break;
pte = pte_offset_map(pmd, addr); pte = pte_offset_map(pmd, addr);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
config NET_VENDOR_SMSC config NET_VENDOR_SMSC
bool "SMC (SMSC)/Western Digital devices" bool "SMC (SMSC)/Western Digital devices"
default y default y
depends on ARM || ISA || MAC || ARM || MIPS || M32R || SUPERH || \ depends on ARM || ISA || MAC || ARM64 || MIPS || M32R || SUPERH || \
BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA
---help--- ---help---
If you have a network (Ethernet) card belonging to this class, say Y If you have a network (Ethernet) card belonging to this class, say Y
...@@ -40,7 +40,7 @@ config SMC91X ...@@ -40,7 +40,7 @@ config SMC91X
select NET_CORE select NET_CORE
select MII select MII
depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \ depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \
MN10300 || COLDFIRE) MN10300 || COLDFIRE || ARM64)
---help--- ---help---
This is a driver for SMC's 91x series of Ethernet chipsets, This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it including the SMC91C94 and the SMC91C111. Say Y if you want it
......
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