summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arc/Kconfig40
-rw-r--r--arch/arc/boot/dts/axc001.dtsi2
-rw-r--r--arch/arc/boot/dts/axc003.dtsi2
-rw-r--r--arch/arc/boot/dts/axc003_idu.dtsi2
-rw-r--r--arch/arc/boot/dts/nsim_hs.dts12
-rw-r--r--arch/arc/boot/dts/skeleton.dtsi2
-rw-r--r--arch/arc/boot/dts/vdk_axc003.dtsi2
-rw-r--r--arch/arc/boot/dts/vdk_axc003_idu.dtsi2
-rw-r--r--arch/arc/configs/axs101_defconfig1
-rw-r--r--arch/arc/configs/axs103_defconfig1
-rw-r--r--arch/arc/configs/axs103_smp_defconfig1
-rw-r--r--arch/arc/include/asm/arcregs.h6
-rw-r--r--arch/arc/include/asm/cache.h2
-rw-r--r--arch/arc/include/asm/cacheflush.h8
-rw-r--r--arch/arc/include/asm/entry-compact.h13
-rw-r--r--arch/arc/include/asm/highmem.h61
-rw-r--r--arch/arc/include/asm/hugepage.h81
-rw-r--r--arch/arc/include/asm/irq.h1
-rw-r--r--arch/arc/include/asm/irqflags-compact.h16
-rw-r--r--arch/arc/include/asm/kmap_types.h18
-rw-r--r--arch/arc/include/asm/mach_desc.h10
-rw-r--r--arch/arc/include/asm/mcip.h3
-rw-r--r--arch/arc/include/asm/mmu.h7
-rw-r--r--arch/arc/include/asm/page.h9
-rw-r--r--arch/arc/include/asm/pgalloc.h12
-rw-r--r--arch/arc/include/asm/pgtable.h88
-rw-r--r--arch/arc/include/asm/processor.h7
-rw-r--r--arch/arc/include/asm/setup.h7
-rw-r--r--arch/arc/include/asm/smp.h7
-rw-r--r--arch/arc/include/asm/tlbflush.h5
-rw-r--r--arch/arc/include/uapi/asm/page.h11
-rw-r--r--arch/arc/kernel/entry-arcv2.S2
-rw-r--r--arch/arc/kernel/entry-compact.S43
-rw-r--r--arch/arc/kernel/head.S49
-rw-r--r--arch/arc/kernel/intc-compact.c90
-rw-r--r--arch/arc/kernel/irq.c20
-rw-r--r--arch/arc/kernel/mcip.c46
-rw-r--r--arch/arc/kernel/setup.c7
-rw-r--r--arch/arc/kernel/smp.c66
-rw-r--r--arch/arc/kernel/time.c3
-rw-r--r--arch/arc/kernel/vmlinux.lds.S2
-rw-r--r--arch/arc/mm/Makefile1
-rw-r--r--arch/arc/mm/cache.c91
-rw-r--r--arch/arc/mm/fault.c13
-rw-r--r--arch/arc/mm/highmem.c140
-rw-r--r--arch/arc/mm/init.c104
-rw-r--r--arch/arc/mm/tlb.c234
-rw-r--r--arch/arc/mm/tlbex.S51
-rw-r--r--arch/arc/plat-axs10x/axs10x.c8
-rw-r--r--arch/arc/plat-sim/platform.c4
-rw-r--r--arch/arm/Kconfig8
-rw-r--r--arch/arm/boot/dts/am57xx-beagle-x15.dts3
-rw-r--r--arch/arm/boot/dts/armada-385-db-ap.dts2
-rw-r--r--arch/arm/boot/dts/berlin2q.dtsi6
-rw-r--r--arch/arm/boot/dts/emev2-kzm9d.dts8
-rw-r--r--arch/arm/boot/dts/exynos5420-peach-pit.dts5
-rw-r--r--arch/arm/boot/dts/exynos5800-peach-pi.dts5
-rw-r--r--arch/arm/boot/dts/imx7d.dtsi4
-rw-r--r--arch/arm/boot/dts/kirkwood-net5big.dts60
-rw-r--r--arch/arm/boot/dts/kirkwood-netxbig.dtsi80
-rw-r--r--arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts2
-rw-r--r--arch/arm/boot/dts/meson.dtsi23
-rw-r--r--arch/arm/boot/dts/omap3-evm-37xx.dts2
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi7
-rw-r--r--arch/arm/boot/dts/rk3288-veyron.dtsi6
-rw-r--r--arch/arm/boot/dts/rk3288.dtsi20
-rw-r--r--arch/arm/boot/dts/sama5d2.dtsi14
-rw-r--r--arch/arm/boot/dts/ste-hrefv60plus.dtsi2
-rw-r--r--arch/arm/boot/dts/ste-snowball.dts10
-rw-r--r--arch/arm/boot/dts/tegra114.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra124.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra20.dtsi2
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi2
-rw-r--r--arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts2
-rw-r--r--arch/arm/configs/exynos_defconfig1
-rw-r--r--arch/arm/configs/hisi_defconfig1
-rw-r--r--arch/arm/configs/lpc18xx_defconfig1
-rw-r--r--arch/arm/include/asm/cmpxchg.h12
-rw-r--r--arch/arm/include/asm/irqflags.h10
-rw-r--r--arch/arm/include/asm/mach/arch.h2
-rw-r--r--arch/arm/include/asm/memory.h2
-rw-r--r--arch/arm/include/asm/pgtable.h2
-rw-r--r--arch/arm/include/asm/smp.h4
-rw-r--r--arch/arm/include/asm/unistd.h7
-rw-r--r--arch/arm/kernel/devtree.c12
-rw-r--r--arch/arm/kernel/entry-armv.S33
-rw-r--r--arch/arm/kernel/hw_breakpoint.c1
-rw-r--r--arch/arm/kernel/kgdb.c31
-rw-r--r--arch/arm/kernel/smp.c12
-rw-r--r--arch/arm/kernel/smp_twd.c11
-rw-r--r--arch/arm/kernel/traps.c52
-rw-r--r--arch/arm/kvm/Kconfig1
-rw-r--r--arch/arm/kvm/arm.c2
-rw-r--r--arch/arm/lib/clear_user.S4
-rw-r--r--arch/arm/mach-exynos/pm_domains.c8
-rw-r--r--arch/arm/mach-mvebu/Kconfig7
-rw-r--r--arch/arm/mach-mvebu/Makefile1
-rw-r--r--arch/arm/mach-mvebu/board.h21
-rw-r--r--arch/arm/mach-mvebu/kirkwood.c4
-rw-r--r--arch/arm/mach-mvebu/netxbig.c191
-rw-r--r--arch/arm/mach-omap2/Kconfig2
-rw-r--r--arch/arm/mach-omap2/board-generic.c10
-rw-r--r--arch/arm/mach-omap2/pdata-quirks.c9
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c9
-rw-r--r--arch/arm/mm/Kconfig12
-rw-r--r--arch/arm/mm/dma-mapping.c7
-rw-r--r--arch/arm/mm/fault.c22
-rw-r--r--arch/arm/mm/fault.h1
-rw-r--r--arch/arm/mm/mmu.c4
-rw-r--r--arch/arm/net/bpf_jit_32.c1
-rw-r--r--arch/arm/plat-orion/common.c2
-rw-r--r--arch/arm/vdso/vdsomunge.c17
-rw-r--r--arch/arm64/Makefile2
-rw-r--r--arch/arm64/boot/dts/apm/apm-storm.dtsi10
-rw-r--r--arch/arm64/boot/dts/arm/juno-motherboard.dtsi12
-rw-r--r--arch/arm64/include/asm/unistd.h2
-rw-r--r--arch/arm64/include/asm/unistd32.h9
-rw-r--r--arch/arm64/include/uapi/asm/signal.h3
-rw-r--r--arch/arm64/kernel/armv8_deprecated.c16
-rw-r--r--arch/arm64/kernel/efi-stub.c14
-rw-r--r--arch/arm64/kernel/stacktrace.c6
-rw-r--r--arch/arm64/kernel/suspend.c22
-rw-r--r--arch/avr32/boards/atngw100/mrmt.c1
-rw-r--r--arch/cris/Kconfig1
-rw-r--r--arch/cris/arch-v10/kernel/head.S106
-rw-r--r--arch/cris/arch-v10/kernel/kgdb.c89
-rw-r--r--arch/cris/arch-v10/mm/init.c14
-rw-r--r--arch/cris/arch-v32/Kconfig89
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig167
-rw-r--r--arch/cris/arch-v32/drivers/Makefile1
-rw-r--r--arch/cris/arch-v32/drivers/axisflashmap.c40
-rw-r--r--arch/cris/arch-v32/drivers/i2c.c751
-rw-r--r--arch/cris/arch-v32/drivers/i2c.h16
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/Makefile1
-rw-r--r--arch/cris/arch-v32/drivers/mach-a3/gpio.c999
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/Makefile1
-rw-r--r--arch/cris/arch-v32/drivers/mach-fs/gpio.c978
-rw-r--r--arch/cris/arch-v32/kernel/crisksyms.c3
-rw-r--r--arch/cris/arch-v32/kernel/debugport.c2
-rw-r--r--arch/cris/arch-v32/kernel/head.S4
-rw-r--r--arch/cris/arch-v32/kernel/irq.c6
-rw-r--r--arch/cris/arch-v32/kernel/kgdb.c96
-rw-r--r--arch/cris/arch-v32/kernel/setup.c8
-rw-r--r--arch/cris/arch-v32/mach-a3/Makefile2
-rw-r--r--arch/cris/arch-v32/mach-a3/io.c149
-rw-r--r--arch/cris/arch-v32/mach-fs/Kconfig19
-rw-r--r--arch/cris/arch-v32/mach-fs/Makefile2
-rw-r--r--arch/cris/arch-v32/mach-fs/io.c191
-rw-r--r--arch/cris/boot/dts/artpec3.dtsi46
-rw-r--r--arch/cris/boot/dts/dev88.dts49
-rw-r--r--arch/cris/boot/dts/etraxfs.dtsi8
l---------arch/cris/boot/dts/include/dt-bindings1
-rw-r--r--arch/cris/boot/dts/p1343.dts76
-rw-r--r--arch/cris/boot/rescue/head_v10.S3
-rw-r--r--arch/cris/include/arch-v32/arch/io.h140
-rw-r--r--arch/cris/include/arch-v32/arch/irq.h2
-rw-r--r--arch/cris/include/asm/eshlibld.h3
-rw-r--r--arch/cris/include/asm/io.h2
-rw-r--r--arch/cris/include/uapi/asm/etraxgpio.h157
-rw-r--r--arch/cris/kernel/crisksyms.c2
-rw-r--r--arch/cris/kernel/time.c25
-rw-r--r--arch/ia64/include/asm/unistd.h2
-rw-r--r--arch/ia64/include/uapi/asm/unistd.h1
-rw-r--r--arch/ia64/kernel/entry.S1
-rw-r--r--arch/m68k/sun3/idprom.c5
-rw-r--r--arch/mips/configs/pistachio_defconfig1
-rw-r--r--arch/mips/mti-sead3/Makefile2
-rw-r--r--arch/mips/mti-sead3/leds-sead3.c77
-rw-r--r--arch/powerpc/configs/ppc64_defconfig2
-rw-r--r--arch/powerpc/configs/pseries_defconfig2
-rw-r--r--arch/powerpc/include/asm/cache.h7
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/include/asm/machdep.h9
-rw-r--r--arch/powerpc/include/asm/ppc-opcode.h17
-rw-r--r--arch/powerpc/include/asm/reg.h1
-rw-r--r--arch/powerpc/kernel/dma.c2
-rw-r--r--arch/powerpc/kernel/rtas.c3
-rw-r--r--arch/powerpc/kvm/book3s_hv.c55
-rw-r--r--arch/powerpc/mm/hash_native_64.c23
-rw-r--r--arch/powerpc/platforms/powernv/opal.c7
-rw-r--r--arch/powerpc/platforms/powernv/smp.c29
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c5
-rw-r--r--arch/sh/include/asm/page.h1
-rw-r--r--arch/sparc/crypto/aes_glue.c2
-rw-r--r--arch/sparc/crypto/camellia_glue.c1
-rw-r--r--arch/sparc/crypto/des_glue.c2
-rw-r--r--arch/um/Makefile4
-rw-r--r--arch/um/kernel/trap.c2
-rw-r--r--arch/um/os-Linux/helper.c6
-rw-r--r--arch/x86/boot/compressed/eboot.c8
-rw-r--r--arch/x86/crypto/camellia_aesni_avx_glue.c5
-rw-r--r--arch/x86/include/asm/kvm_host.h6
-rw-r--r--arch/x86/include/asm/string_64.h5
-rw-r--r--arch/x86/kernel/apic/io_apic.c8
-rw-r--r--arch/x86/kernel/pci-dma.c5
-rw-r--r--arch/x86/kernel/process.c9
-rw-r--r--arch/x86/kernel/setup.c8
-rw-r--r--arch/x86/kernel/smpboot.c15
-rw-r--r--arch/x86/kvm/emulate.c10
-rw-r--r--arch/x86/kvm/vmx.c26
-rw-r--r--arch/x86/kvm/x86.c135
-rw-r--r--arch/x86/um/ldt.c5
202 files changed, 1928 insertions, 5153 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 78c0621d5819..2c2ac3f3ff80 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -76,6 +76,10 @@ config STACKTRACE_SUPPORT
config HAVE_LATENCYTOP_SUPPORT
def_bool y
+config HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ def_bool y
+ depends on ARC_MMU_V4
+
source "init/Kconfig"
source "kernel/Kconfig.freezer"
@@ -190,6 +194,16 @@ config NR_CPUS
range 2 4096
default "4"
+config ARC_SMP_HALT_ON_RESET
+ bool "Enable Halt-on-reset boot mode"
+ default y if ARC_UBOOT_SUPPORT
+ help
+ In SMP configuration cores can be configured as Halt-on-reset
+ or they could all start at same time. For Halt-on-reset, non
+ masters are parked until Master kicks them so they can start of
+ at designated entry point. For other case, all jump to common
+ entry point and spin wait for Master's signal.
+
endif #SMP
menuconfig ARC_CACHE
@@ -278,6 +292,8 @@ choice
default ARC_MMU_V2 if ARC_CPU_750D
default ARC_MMU_V4 if ARC_CPU_HS
+if ISA_ARCOMPACT
+
config ARC_MMU_V1
bool "MMU v1"
help
@@ -297,6 +313,8 @@ config ARC_MMU_V3
Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
Shared Address Spaces (SASID)
+endif
+
config ARC_MMU_V4
bool "MMU v4"
depends on ISA_ARCV2
@@ -428,6 +446,28 @@ config LINUX_LINK_BASE
Linux needs to be scooted a bit.
If you don't know what the above means, leave this setting alone.
+config HIGHMEM
+ bool "High Memory Support"
+ help
+ With ARC 2G:2G address split, only upper 2G is directly addressable by
+ kernel. Enable this to potentially allow access to rest of 2G and PAE
+ in future
+
+config ARC_HAS_PAE40
+ bool "Support for the 40-bit Physical Address Extension"
+ default n
+ depends on ISA_ARCV2
+ select HIGHMEM
+ help
+ Enable access to physical memory beyond 4G, only supported on
+ ARC cores with 40 bit Physical Addressing support
+
+config ARCH_PHYS_ADDR_T_64BIT
+ def_bool ARC_HAS_PAE40
+
+config ARCH_DMA_ADDR_T_64BIT
+ bool
+
config ARC_CURR_IN_REG
bool "Dedicate Register r25 for current_task pointer"
default y
diff --git a/arch/arc/boot/dts/axc001.dtsi b/arch/arc/boot/dts/axc001.dtsi
index a5e2726a067e..420dcfde289f 100644
--- a/arch/arc/boot/dts/axc001.dtsi
+++ b/arch/arc/boot/dts/axc001.dtsi
@@ -95,6 +95,6 @@
#size-cells = <1>;
ranges = <0x00000000 0x80000000 0x40000000>;
device_type = "memory";
- reg = <0x00000000 0x20000000>; /* 512MiB */
+ reg = <0x80000000 0x20000000>; /* 512MiB */
};
};
diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi
index 846481f37eef..f90fadf7f94e 100644
--- a/arch/arc/boot/dts/axc003.dtsi
+++ b/arch/arc/boot/dts/axc003.dtsi
@@ -98,6 +98,6 @@
#size-cells = <1>;
ranges = <0x00000000 0x80000000 0x40000000>;
device_type = "memory";
- reg = <0x00000000 0x20000000>; /* 512MiB */
+ reg = <0x80000000 0x20000000>; /* 512MiB */
};
};
diff --git a/arch/arc/boot/dts/axc003_idu.dtsi b/arch/arc/boot/dts/axc003_idu.dtsi
index 2f0b33257db2..06a9f294a2e6 100644
--- a/arch/arc/boot/dts/axc003_idu.dtsi
+++ b/arch/arc/boot/dts/axc003_idu.dtsi
@@ -121,6 +121,6 @@
#size-cells = <1>;
ranges = <0x00000000 0x80000000 0x40000000>;
device_type = "memory";
- reg = <0x00000000 0x20000000>; /* 512MiB */
+ reg = <0x80000000 0x20000000>; /* 512MiB */
};
};
diff --git a/arch/arc/boot/dts/nsim_hs.dts b/arch/arc/boot/dts/nsim_hs.dts
index 911f069e0540..b0eb0e7fe21d 100644
--- a/arch/arc/boot/dts/nsim_hs.dts
+++ b/arch/arc/boot/dts/nsim_hs.dts
@@ -11,8 +11,16 @@
/ {
compatible = "snps,nsim_hs";
+ #address-cells = <2>;
+ #size-cells = <2>;
interrupt-parent = <&core_intc>;
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x40000000 /* 1 GB low mem */
+ 0x1 0x00000000 0x0 0x40000000>; /* 1 GB highmem */
+ };
+
chosen {
bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
};
@@ -26,8 +34,8 @@
#address-cells = <1>;
#size-cells = <1>;
- /* child and parent address space 1:1 mapped */
- ranges;
+ /* only perip space at end of low mem accessible */
+ ranges = <0x80000000 0x0 0x80000000 0x80000000>;
core_intc: core-interrupt-controller {
compatible = "snps,archs-intc";
diff --git a/arch/arc/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
index a870bdd5e404..296d371a335c 100644
--- a/arch/arc/boot/dts/skeleton.dtsi
+++ b/arch/arc/boot/dts/skeleton.dtsi
@@ -32,6 +32,6 @@
memory {
device_type = "memory";
- reg = <0x00000000 0x10000000>; /* 256M */
+ reg = <0x80000000 0x10000000>; /* 256M */
};
};
diff --git a/arch/arc/boot/dts/vdk_axc003.dtsi b/arch/arc/boot/dts/vdk_axc003.dtsi
index 9393fd902f0d..84226bd48baf 100644
--- a/arch/arc/boot/dts/vdk_axc003.dtsi
+++ b/arch/arc/boot/dts/vdk_axc003.dtsi
@@ -56,6 +56,6 @@
#size-cells = <1>;
ranges = <0x00000000 0x80000000 0x40000000>;
device_type = "memory";
- reg = <0x00000000 0x20000000>; /* 512MiB */
+ reg = <0x80000000 0x20000000>; /* 512MiB */
};
};
diff --git a/arch/arc/boot/dts/vdk_axc003_idu.dtsi b/arch/arc/boot/dts/vdk_axc003_idu.dtsi
index 9bee8ed09eb0..31f0fb5fc91d 100644
--- a/arch/arc/boot/dts/vdk_axc003_idu.dtsi
+++ b/arch/arc/boot/dts/vdk_axc003_idu.dtsi
@@ -71,6 +71,6 @@
#size-cells = <1>;
ranges = <0x00000000 0x80000000 0x40000000>;
device_type = "memory";
- reg = <0x00000000 0x20000000>; /* 512MiB */
+ reg = <0x80000000 0x20000000>; /* 512MiB */
};
};
diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig
index 562dac6a7f78..c92c0ef1e9d2 100644
--- a/arch/arc/configs/axs101_defconfig
+++ b/arch/arc/configs/axs101_defconfig
@@ -89,7 +89,6 @@ CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS=y
diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig
index 83a6d8d5cc58..cfac24e0e7b6 100644
--- a/arch/arc/configs/axs103_defconfig
+++ b/arch/arc/configs/axs103_defconfig
@@ -95,7 +95,6 @@ CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS=y
diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig
index f1e1c84e0dda..9922a118a15a 100644
--- a/arch/arc/configs/axs103_smp_defconfig
+++ b/arch/arc/configs/axs103_smp_defconfig
@@ -96,7 +96,6 @@ CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS=y
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index d8023bc8d1ad..7fac7d85ed6a 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -120,7 +120,7 @@
/* gcc builtin sr needs reg param to be long immediate */
#define write_aux_reg(reg_immed, val) \
- __builtin_arc_sr((unsigned int)val, reg_immed)
+ __builtin_arc_sr((unsigned int)(val), reg_immed)
#else
@@ -327,8 +327,8 @@ struct bcr_generic {
*/
struct cpuinfo_arc_mmu {
- unsigned int ver:4, pg_sz_k:8, s_pg_sz_m:8, u_dtlb:6, u_itlb:6;
- unsigned int num_tlb:16, sets:12, ways:4;
+ unsigned int ver:4, pg_sz_k:8, s_pg_sz_m:8, pad:10, sasid:1, pae:1;
+ unsigned int sets:12, ways:4, u_dtlb:8, u_itlb:8;
};
struct cpuinfo_arc_cache {
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index e23ea6e7633a..abf06e81c929 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -65,6 +65,7 @@ extern int ioc_exists;
#if defined(CONFIG_ARC_MMU_V3) || defined(CONFIG_ARC_MMU_V4)
#define ARC_REG_IC_PTAG 0x1E
#endif
+#define ARC_REG_IC_PTAG_HI 0x1F
/* Bit val in IC_CTRL */
#define IC_CTRL_CACHE_DISABLE 0x1
@@ -77,6 +78,7 @@ extern int ioc_exists;
#define ARC_REG_DC_FLSH 0x4B
#define ARC_REG_DC_FLDL 0x4C
#define ARC_REG_DC_PTAG 0x5C
+#define ARC_REG_DC_PTAG_HI 0x5F
/* Bit val in DC_CTRL */
#define DC_CTRL_INV_MODE_FLUSH 0x40
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
index 0992d3dbcc65..fbe3587c4f36 100644
--- a/arch/arc/include/asm/cacheflush.h
+++ b/arch/arc/include/asm/cacheflush.h
@@ -31,10 +31,10 @@
void flush_cache_all(void);
-void flush_icache_range(unsigned long start, unsigned long end);
-void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len);
-void __inv_icache_page(unsigned long paddr, unsigned long vaddr);
-void __flush_dcache_page(unsigned long paddr, unsigned long vaddr);
+void flush_icache_range(unsigned long kstart, unsigned long kend);
+void __sync_icache_dcache(phys_addr_t paddr, unsigned long vaddr, int len);
+void __inv_icache_page(phys_addr_t paddr, unsigned long vaddr);
+void __flush_dcache_page(phys_addr_t paddr, unsigned long vaddr);
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h
index 415443c2a8c4..1aff3be91075 100644
--- a/arch/arc/include/asm/entry-compact.h
+++ b/arch/arc/include/asm/entry-compact.h
@@ -110,13 +110,12 @@
.macro FAKE_RET_FROM_EXCPN
- ld r9, [sp, PT_status32]
- bic r9, r9, (STATUS_U_MASK|STATUS_DE_MASK)
- bset r9, r9, STATUS_L_BIT
- sr r9, [erstatus]
- mov r9, 55f
- sr r9, [eret]
-
+ lr r9, [status32]
+ bclr r9, r9, STATUS_AE_BIT
+ or r9, r9, (STATUS_E1_MASK|STATUS_E2_MASK)
+ sr r9, [erstatus]
+ mov r9, 55f
+ sr r9, [eret]
rtie
55:
.endm
diff --git a/arch/arc/include/asm/highmem.h b/arch/arc/include/asm/highmem.h
new file mode 100644
index 000000000000..b1585c96324a
--- /dev/null
+++ b/arch/arc/include/asm/highmem.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.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.
+ *
+ */
+
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#ifdef CONFIG_HIGHMEM
+
+#include <uapi/asm/page.h>
+#include <asm/kmap_types.h>
+
+/* start after vmalloc area */
+#define FIXMAP_BASE (PAGE_OFFSET - FIXMAP_SIZE - PKMAP_SIZE)
+#define FIXMAP_SIZE PGDIR_SIZE /* only 1 PGD worth */
+#define KM_TYPE_NR ((FIXMAP_SIZE >> PAGE_SHIFT)/NR_CPUS)
+#define FIXMAP_ADDR(nr) (FIXMAP_BASE + ((nr) << PAGE_SHIFT))
+
+/* start after fixmap area */
+#define PKMAP_BASE (FIXMAP_BASE + FIXMAP_SIZE)
+#define PKMAP_SIZE PGDIR_SIZE
+#define LAST_PKMAP (PKMAP_SIZE >> PAGE_SHIFT)
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+#define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT)
+
+#define kmap_prot PAGE_KERNEL
+
+
+#include <asm/cacheflush.h>
+
+extern void *kmap(struct page *page);
+extern void *kmap_high(struct page *page);
+extern void *kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
+extern void kunmap_high(struct page *page);
+
+extern void kmap_init(void);
+
+static inline void flush_cache_kmaps(void)
+{
+ flush_cache_all();
+}
+
+static inline void kunmap(struct page *page)
+{
+ BUG_ON(in_interrupt());
+ if (!PageHighMem(page))
+ return;
+ kunmap_high(page);
+}
+
+
+#endif
+
+#endif
diff --git a/arch/arc/include/asm/hugepage.h b/arch/arc/include/asm/hugepage.h
new file mode 100644
index 000000000000..c5094de86403
--- /dev/null
+++ b/arch/arc/include/asm/hugepage.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013-15 Synopsys, Inc. (www.synopsys.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.
+ */
+
+
+#ifndef _ASM_ARC_HUGEPAGE_H
+#define _ASM_ARC_HUGEPAGE_H
+
+#include <linux/types.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+static inline pte_t pmd_pte(pmd_t pmd)
+{
+ return __pte(pmd_val(pmd));
+}
+
+static inline pmd_t pte_pmd(pte_t pte)
+{
+ return __pmd(pte_val(pte));
+}
+
+#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
+#define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd)))
+#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))
+#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
+#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
+#define pmd_mkhuge(pmd) pte_pmd(pte_mkhuge(pmd_pte(pmd)))
+#define pmd_mknotpresent(pmd) pte_pmd(pte_mknotpresent(pmd_pte(pmd)))
+#define pmd_mksplitting(pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd)))
+#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))
+
+#define pmd_write(pmd) pte_write(pmd_pte(pmd))
+#define pmd_young(pmd) pte_young(pmd_pte(pmd))
+#define pmd_pfn(pmd) pte_pfn(pmd_pte(pmd))
+#define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
+#define pmd_special(pmd) pte_special(pmd_pte(pmd))
+
+#define mk_pmd(page, prot) pte_pmd(mk_pte(page, prot))
+
+#define pmd_trans_huge(pmd) (pmd_val(pmd) & _PAGE_HW_SZ)
+#define pmd_trans_splitting(pmd) (pmd_trans_huge(pmd) && pmd_special(pmd))
+
+#define pfn_pmd(pfn, prot) (__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+ /*
+ * open-coded pte_modify() with additional retaining of HW_SZ bit
+ * so that pmd_trans_huge() remains true for this PMD
+ */
+ return __pmd((pmd_val(pmd) & (_PAGE_CHG_MASK | _PAGE_HW_SZ)) | pgprot_val(newprot));
+}
+
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd)
+{
+ *pmdp = pmd;
+}
+
+extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
+ pmd_t *pmd);
+
+#define has_transparent_hugepage() 1
+
+/* Generic variants assume pgtable_t is struct page *, hence need for these */
+#define __HAVE_ARCH_PGTABLE_DEPOSIT
+extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+ pgtable_t pgtable);
+
+#define __HAVE_ARCH_PGTABLE_WITHDRAW
+extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+
+#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
+extern void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end);
+
+#endif
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index bc5103637326..4fd7d62a6e30 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -16,6 +16,7 @@
#ifdef CONFIG_ISA_ARCOMPACT
#define TIMER0_IRQ 3
#define TIMER1_IRQ 4
+#define IPI_IRQ (NR_CPU_IRQS-1) /* dummy to enable SMP build for up hardware */
#else
#define TIMER0_IRQ 16
#define TIMER1_IRQ 17
diff --git a/arch/arc/include/asm/irqflags-compact.h b/arch/arc/include/asm/irqflags-compact.h
index aa805575c320..d8c608174617 100644
--- a/arch/arc/include/asm/irqflags-compact.h
+++ b/arch/arc/include/asm/irqflags-compact.h
@@ -23,11 +23,13 @@
#define STATUS_E2_BIT 2 /* Int 2 enable */
#define STATUS_A1_BIT 3 /* Int 1 active */
#define STATUS_A2_BIT 4 /* Int 2 active */
+#define STATUS_AE_BIT 5 /* Exception active */
#define STATUS_E1_MASK (1<<STATUS_E1_BIT)
#define STATUS_E2_MASK (1<<STATUS_E2_BIT)
#define STATUS_A1_MASK (1<<STATUS_A1_BIT)
#define STATUS_A2_MASK (1<<STATUS_A2_BIT)
+#define STATUS_AE_MASK (1<<STATUS_AE_BIT)
#define STATUS_IE_MASK (STATUS_E1_MASK | STATUS_E2_MASK)
/* Other Interrupt Handling related Aux regs */
@@ -91,7 +93,19 @@ static inline void arch_local_irq_restore(unsigned long flags)
/*
* Unconditionally Enable IRQs
*/
-extern void arch_local_irq_enable(void);
+static inline void arch_local_irq_enable(void)
+{
+ unsigned long temp;
+
+ __asm__ __volatile__(
+ " lr %0, [status32] \n"
+ " or %0, %0, %1 \n"
+ " flag %0 \n"
+ : "=&r"(temp)
+ : "n"((STATUS_E1_MASK | STATUS_E2_MASK))
+ : "cc", "memory");
+}
+
/*
* Unconditionally Disable IRQs
diff --git a/arch/arc/include/asm/kmap_types.h b/arch/arc/include/asm/kmap_types.h
new file mode 100644
index 000000000000..f0d7f6acea4e
--- /dev/null
+++ b/arch/arc/include/asm/kmap_types.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.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.
+ *
+ */
+
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+/*
+ * We primarily need to define KM_TYPE_NR here but that in turn
+ * is a function of PGDIR_SIZE etc.
+ * To avoid circular deps issue, put everything in asm/highmem.h
+ */
+#endif
diff --git a/arch/arc/include/asm/mach_desc.h b/arch/arc/include/asm/mach_desc.h
index e8993a2be6c2..6ff657a904b6 100644
--- a/arch/arc/include/asm/mach_desc.h
+++ b/arch/arc/include/asm/mach_desc.h
@@ -23,11 +23,8 @@
* @dt_compat: Array of device tree 'compatible' strings
* (XXX: although only 1st entry is looked at)
* @init_early: Very early callback [called from setup_arch()]
- * @init_irq: setup external IRQ controllers [called from init_IRQ()]
- * @init_smp: for each CPU (e.g. setup IPI)
+ * @init_cpu_smp: for each CPU as it is coming up (SMP as well as UP)
* [(M):init_IRQ(), (o):start_kernel_secondary()]
- * @init_time: platform specific clocksource/clockevent registration
- * [called from time_init()]
* @init_machine: arch initcall level callback (e.g. populate static
* platform devices or parse Devicetree)
* @init_late: Late initcall level callback
@@ -36,13 +33,10 @@
struct machine_desc {
const char *name;
const char **dt_compat;
-
void (*init_early)(void);
- void (*init_irq)(void);
#ifdef CONFIG_SMP
- void (*init_smp)(unsigned int);
+ void (*init_cpu_smp)(unsigned int);
#endif
- void (*init_time)(void);
void (*init_machine)(void);
void (*init_late)(void);
diff --git a/arch/arc/include/asm/mcip.h b/arch/arc/include/asm/mcip.h
index 52c11f0bb0e5..46f4e5351b2a 100644
--- a/arch/arc/include/asm/mcip.h
+++ b/arch/arc/include/asm/mcip.h
@@ -86,9 +86,6 @@ static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param,
__mcip_cmd(cmd, param);
}
-extern void mcip_init_early_smp(void);
-extern void mcip_init_smp(unsigned int cpu);
-
#endif
#endif
diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h
index 0f9c3eb5327e..b144d7ca7d20 100644
--- a/arch/arc/include/asm/mmu.h
+++ b/arch/arc/include/asm/mmu.h
@@ -24,6 +24,7 @@
#if (CONFIG_ARC_MMU_VER < 4)
#define ARC_REG_TLBPD0 0x405
#define ARC_REG_TLBPD1 0x406
+#define ARC_REG_TLBPD1HI 0 /* Dummy: allows code sharing with ARC700 */
#define ARC_REG_TLBINDEX 0x407
#define ARC_REG_TLBCOMMAND 0x408
#define ARC_REG_PID 0x409
@@ -31,6 +32,7 @@
#else
#define ARC_REG_TLBPD0 0x460
#define ARC_REG_TLBPD1 0x461
+#define ARC_REG_TLBPD1HI 0x463
#define ARC_REG_TLBINDEX 0x464
#define ARC_REG_TLBCOMMAND 0x465
#define ARC_REG_PID 0x468
@@ -83,6 +85,11 @@ void arc_mmu_init(void);
extern char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len);
void read_decode_mmu_bcr(void);
+static inline int is_pae40_enabled(void)
+{
+ return IS_ENABLED(CONFIG_ARC_HAS_PAE40);
+}
+
#endif /* !__ASSEMBLY__ */
#endif
diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
index 9c8aa41e45c2..429957f1c236 100644
--- a/arch/arc/include/asm/page.h
+++ b/arch/arc/include/asm/page.h
@@ -43,7 +43,6 @@ typedef struct {
typedef struct {
unsigned long pgprot;
} pgprot_t;
-typedef unsigned long pgtable_t;
#define pte_val(x) ((x).pte)
#define pgd_val(x) ((x).pgd)
@@ -57,20 +56,26 @@ typedef unsigned long pgtable_t;
#else /* !STRICT_MM_TYPECHECKS */
+#ifdef CONFIG_ARC_HAS_PAE40
+typedef unsigned long long pte_t;
+#else
typedef unsigned long pte_t;
+#endif
typedef unsigned long pgd_t;
typedef unsigned long pgprot_t;
-typedef unsigned long pgtable_t;
#define pte_val(x) (x)
#define pgd_val(x) (x)
#define pgprot_val(x) (x)
#define __pte(x) (x)
+#define __pgd(x) (x)
#define __pgprot(x) (x)
#define pte_pgprot(x) (x)
#endif
+typedef pte_t * pgtable_t;
+
#define ARCH_PFN_OFFSET (CONFIG_LINUX_LINK_BASE >> PAGE_SHIFT)
#define pfn_valid(pfn) (((pfn) - ARCH_PFN_OFFSET) < max_mapnr)
diff --git a/arch/arc/include/asm/pgalloc.h b/arch/arc/include/asm/pgalloc.h
index 81208bfd9dcb..86ed671286df 100644
--- a/arch/arc/include/asm/pgalloc.h
+++ b/arch/arc/include/asm/pgalloc.h
@@ -49,7 +49,7 @@ pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t ptep)
static inline int __get_order_pgd(void)
{
- return get_order(PTRS_PER_PGD * 4);
+ return get_order(PTRS_PER_PGD * sizeof(pgd_t));
}
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
@@ -87,7 +87,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
static inline int __get_order_pte(void)
{
- return get_order(PTRS_PER_PTE * 4);
+ return get_order(PTRS_PER_PTE * sizeof(pte_t));
}
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
@@ -107,10 +107,10 @@ pte_alloc_one(struct mm_struct *mm, unsigned long address)
pgtable_t pte_pg;
struct page *page;
- pte_pg = __get_free_pages(GFP_KERNEL | __GFP_REPEAT, __get_order_pte());
+ pte_pg = (pgtable_t)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, __get_order_pte());
if (!pte_pg)
return 0;
- memzero((void *)pte_pg, PTRS_PER_PTE * 4);
+ memzero((void *)pte_pg, PTRS_PER_PTE * sizeof(pte_t));
page = virt_to_page(pte_pg);
if (!pgtable_page_ctor(page)) {
__free_page(page);
@@ -128,12 +128,12 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
static inline void pte_free(struct mm_struct *mm, pgtable_t ptep)
{
pgtable_page_dtor(virt_to_page(ptep));
- free_pages(ptep, __get_order_pte());
+ free_pages((unsigned long)ptep, __get_order_pte());
}
#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
#define check_pgt_cache() do { } while (0)
-#define pmd_pgtable(pmd) pmd_page_vaddr(pmd)
+#define pmd_pgtable(pmd) ((pgtable_t) pmd_page_vaddr(pmd))
#endif /* _ASM_ARC_PGALLOC_H */
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index 1281718802f7..57af2f05ae84 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -38,6 +38,7 @@
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm-generic/pgtable-nopmd.h>
+#include <linux/const.h>
/**************************************************************************
* Page Table Flags
@@ -60,7 +61,8 @@
#define _PAGE_EXECUTE (1<<3) /* Page has user execute perm (H) */
#define _PAGE_WRITE (1<<4) /* Page has user write perm (H) */
#define _PAGE_READ (1<<5) /* Page has user read perm (H) */
-#define _PAGE_MODIFIED (1<<6) /* Page modified (dirty) (S) */
+#define _PAGE_DIRTY (1<<6) /* Page modified (dirty) (S) */
+#define _PAGE_SPECIAL (1<<7)
#define _PAGE_GLOBAL (1<<8) /* Page is global (H) */
#define _PAGE_PRESENT (1<<10) /* TLB entry is valid (H) */
@@ -71,7 +73,8 @@
#define _PAGE_WRITE (1<<2) /* Page has user write perm (H) */
#define _PAGE_READ (1<<3) /* Page has user read perm (H) */
#define _PAGE_ACCESSED (1<<4) /* Page is accessed (S) */
-#define _PAGE_MODIFIED (1<<5) /* Page modified (dirty) (S) */
+#define _PAGE_DIRTY (1<<5) /* Page modified (dirty) (S) */
+#define _PAGE_SPECIAL (1<<6)
#if (CONFIG_ARC_MMU_VER >= 4)
#define _PAGE_WTHRU (1<<7) /* Page cache mode write-thru (H) */
@@ -81,32 +84,33 @@
#define _PAGE_PRESENT (1<<9) /* TLB entry is valid (H) */
#if (CONFIG_ARC_MMU_VER >= 4)
-#define _PAGE_SZ (1<<10) /* Page Size indicator (H) */
+#define _PAGE_HW_SZ (1<<10) /* Page Size indicator (H): 0 normal, 1 super */
#endif
#define _PAGE_SHARED_CODE (1<<11) /* Shared Code page with cmn vaddr
usable for shared TLB entries (H) */
+
+#define _PAGE_UNUSED_BIT (1<<12)
#endif
/* vmalloc permissions */
#define _K_PAGE_PERMS (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ | \
_PAGE_GLOBAL | _PAGE_PRESENT)
-#ifdef CONFIG_ARC_CACHE_PAGES
-#define _PAGE_DEF_CACHEABLE _PAGE_CACHEABLE
-#else
-#define _PAGE_DEF_CACHEABLE (0)
+#ifndef CONFIG_ARC_CACHE_PAGES
+#undef _PAGE_CACHEABLE
+#define _PAGE_CACHEABLE 0
#endif
-/* Helper for every "user" page
- * -kernel can R/W/X
- * -by default cached, unless config otherwise
- * -present in memory
- */
-#define ___DEF (_PAGE_PRESENT | _PAGE_DEF_CACHEABLE)
+#ifndef _PAGE_HW_SZ
+#define _PAGE_HW_SZ 0
+#endif
+
+/* Defaults for every user page */
+#define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
/* Set of bits not changed in pte_modify */
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED)
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
/* More Abbrevaited helpers */
#define PAGE_U_NONE __pgprot(___DEF)
@@ -122,15 +126,20 @@
* user vaddr space - visible in all addr spaces, but kernel mode only
* Thus Global, all-kernel-access, no-user-access, cached
*/
-#define PAGE_KERNEL __pgprot(_K_PAGE_PERMS | _PAGE_DEF_CACHEABLE)
+#define PAGE_KERNEL __pgprot(_K_PAGE_PERMS | _PAGE_CACHEABLE)
/* ioremap */
#define PAGE_KERNEL_NO_CACHE __pgprot(_K_PAGE_PERMS)
/* Masks for actual TLB "PD"s */
-#define PTE_BITS_IN_PD0 (_PAGE_GLOBAL | _PAGE_PRESENT)
+#define PTE_BITS_IN_PD0 (_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_HW_SZ)
#define PTE_BITS_RWX (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)
+
+#ifdef CONFIG_ARC_HAS_PAE40
+#define PTE_BITS_NON_RWX_IN_PD1 (0xff00000000 | PAGE_MASK | _PAGE_CACHEABLE)
+#else
#define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK | _PAGE_CACHEABLE)
+#endif
/**************************************************************************
* Mapping of vm_flags (Generic VM) to PTE flags (arch specific)
@@ -191,26 +200,22 @@
/* Optimal Sizing of Pg Tbl - based on MMU page size */
#if defined(CONFIG_ARC_PAGE_SIZE_8K)
-#define BITS_FOR_PTE 8
+#define BITS_FOR_PTE 8 /* 11:8:13 */
#elif defined(CONFIG_ARC_PAGE_SIZE_16K)
-#define BITS_FOR_PTE 8
+#define BITS_FOR_PTE 8 /* 10:8:14 */
#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
-#define BITS_FOR_PTE 9
+#define BITS_FOR_PTE 9 /* 11:9:12 */
#endif
#define BITS_FOR_PGD (32 - BITS_FOR_PTE - BITS_IN_PAGE)
-#define PGDIR_SHIFT (BITS_FOR_PTE + BITS_IN_PAGE)
+#define PGDIR_SHIFT (32 - BITS_FOR_PGD)
#define PGDIR_SIZE (1UL << PGDIR_SHIFT) /* vaddr span, not PDG sz */
#define PGDIR_MASK (~(PGDIR_SIZE-1))
-#ifdef __ASSEMBLY__
-#define PTRS_PER_PTE (1 << BITS_FOR_PTE)
-#define PTRS_PER_PGD (1 << BITS_FOR_PGD)
-#else
-#define PTRS_PER_PTE (1UL << BITS_FOR_PTE)
-#define PTRS_PER_PGD (1UL << BITS_FOR_PGD)
-#endif
+#define PTRS_PER_PTE _BITUL(BITS_FOR_PTE)
+#define PTRS_PER_PGD _BITUL(BITS_FOR_PGD)
+
/*
* Number of entries a user land program use.
* TASK_SIZE is the maximum vaddr that can be used by a userland program.
@@ -270,15 +275,10 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
(unsigned long)(((pte_val(x) - CONFIG_LINUX_LINK_BASE) >> \
PAGE_SHIFT)))
-#define mk_pte(page, pgprot) \
-({ \
- pte_t pte; \
- pte_val(pte) = __pa(page_address(page)) + pgprot_val(pgprot); \
- pte; \
-})
-
+#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
-#define pfn_pte(pfn, prot) (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+#define pfn_pte(pfn, prot) (__pte(((pte_t)(pfn) << PAGE_SHIFT) | \
+ pgprot_val(prot)))
#define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
/*
@@ -295,23 +295,26 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
/* Zoo of pte_xxx function */
#define pte_read(pte) (pte_val(pte) & _PAGE_READ)
#define pte_write(pte) (pte_val(pte) & _PAGE_WRITE)
-#define pte_dirty(pte) (pte_val(pte) & _PAGE_MODIFIED)
+#define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY)
#define pte_young(pte) (pte_val(pte) & _PAGE_ACCESSED)
-#define pte_special(pte) (0)
+#define pte_special(pte) (pte_val(pte) & _PAGE_SPECIAL)
#define PTE_BIT_FUNC(fn, op) \
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
+PTE_BIT_FUNC(mknotpresent, &= ~(_PAGE_PRESENT));
PTE_BIT_FUNC(wrprotect, &= ~(_PAGE_WRITE));
PTE_BIT_FUNC(mkwrite, |= (_PAGE_WRITE));
-PTE_BIT_FUNC(mkclean, &= ~(_PAGE_MODIFIED));
-PTE_BIT_FUNC(mkdirty, |= (_PAGE_MODIFIED));
+PTE_BIT_FUNC(mkclean, &= ~(_PAGE_DIRTY));
+PTE_BIT_FUNC(mkdirty, |= (_PAGE_DIRTY));
PTE_BIT_FUNC(mkold, &= ~(_PAGE_ACCESSED));
PTE_BIT_FUNC(mkyoung, |= (_PAGE_ACCESSED));
PTE_BIT_FUNC(exprotect, &= ~(_PAGE_EXECUTE));
PTE_BIT_FUNC(mkexec, |= (_PAGE_EXECUTE));
+PTE_BIT_FUNC(mkspecial, |= (_PAGE_SPECIAL));
+PTE_BIT_FUNC(mkhuge, |= (_PAGE_HW_SZ));
-static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+#define __HAVE_ARCH_PTE_SPECIAL
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
@@ -357,7 +360,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
#define pgd_offset_fast(mm, addr) pgd_offset(mm, addr)
#endif
-extern void paging_init(void);
extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE);
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
pte_t *ptep);
@@ -383,6 +385,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#include <asm/hugepage.h>
+#endif
+
#include <asm-generic/pgtable.h>
/* to cope with aliasing VIPT cache */
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index ee682d8e0213..44545354e9e8 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -114,7 +114,12 @@ extern unsigned int get_wchan(struct task_struct *p);
* -----------------------------------------------------------------------------
*/
#define VMALLOC_START 0x70000000
-#define VMALLOC_SIZE (PAGE_OFFSET - VMALLOC_START)
+
+/*
+ * 1 PGDIR_SIZE each for fixmap/pkmap, 2 PGDIR_SIZE gutter
+ * See asm/highmem.h for details
+ */
+#define VMALLOC_SIZE (PAGE_OFFSET - VMALLOC_START - PGDIR_SIZE * 4)
#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
#define USER_KERNEL_GUTTER 0x10000000
diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
index 6e3ef5ba4f74..307846691be6 100644
--- a/arch/arc/include/asm/setup.h
+++ b/arch/arc/include/asm/setup.h
@@ -33,4 +33,11 @@ extern int root_mountflags, end_mem;
void setup_processor(void);
void __init setup_arch_memory(void);
+/* Helpers used in arc_*_mumbojumbo routines */
+#define IS_AVAIL1(v, s) ((v) ? s : "")
+#define IS_DISABLED_RUN(v) ((v) ? "" : "(disabled) ")
+#define IS_USED_RUN(v) ((v) ? "" : "(not used) ")
+#define IS_USED_CFG(cfg) IS_USED_RUN(IS_ENABLED(cfg))
+#define IS_AVAIL2(v, s, cfg) IS_AVAIL1(v, s), IS_AVAIL1(v, IS_USED_CFG(cfg))
+
#endif /* __ASMARC_SETUP_H */
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index 3845b9e94f69..133c867d15af 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -45,12 +45,19 @@ extern int smp_ipi_irq_setup(int cpu, int irq);
* struct plat_smp_ops - SMP callbacks provided by platform to ARC SMP
*
* @info: SoC SMP specific info for /proc/cpuinfo etc
+ * @init_early_smp: A SMP specific h/w block can init itself
+ * Could be common across platforms so not covered by
+ * mach_desc->init_early()
+ * @init_irq_cpu: Called for each core so SMP h/w block driver can do
+ * any needed setup per cpu (e.g. IPI request)
* @cpu_kick: For Master to kickstart a cpu (optionally at a PC)
* @ipi_send: To send IPI to a @cpu
* @ips_clear: To clear IPI received at @irq
*/
struct plat_smp_ops {
const char *info;
+ void (*init_early_smp)(void);
+ void (*init_irq_cpu)(int cpu);
void (*cpu_kick)(int cpu, unsigned long pc);
void (*ipi_send)(int cpu);
void (*ipi_clear)(int irq);
diff --git a/arch/arc/include/asm/tlbflush.h b/arch/arc/include/asm/tlbflush.h
index 71c7b2e4b874..1fe9c8c80280 100644
--- a/arch/arc/include/asm/tlbflush.h
+++ b/arch/arc/include/asm/tlbflush.h
@@ -17,6 +17,8 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
void local_flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
+void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end);
#ifndef CONFIG_SMP
#define flush_tlb_range(vma, s, e) local_flush_tlb_range(vma, s, e)
@@ -24,6 +26,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma,
#define flush_tlb_kernel_range(s, e) local_flush_tlb_kernel_range(s, e)
#define flush_tlb_all() local_flush_tlb_all()
#define flush_tlb_mm(mm) local_flush_tlb_mm(mm)
+#define flush_pmd_tlb_range(vma, s, e) local_flush_pmd_tlb_range(vma, s, e)
#else
extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
@@ -31,5 +34,7 @@ extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
extern void flush_tlb_all(void);
extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
+
#endif /* CONFIG_SMP */
#endif
diff --git a/arch/arc/include/uapi/asm/page.h b/arch/arc/include/uapi/asm/page.h
index 9d129a2a1351..059aff38f10a 100644
--- a/arch/arc/include/uapi/asm/page.h
+++ b/arch/arc/include/uapi/asm/page.h
@@ -9,6 +9,8 @@
#ifndef _UAPI__ASM_ARC_PAGE_H
#define _UAPI__ASM_ARC_PAGE_H
+#include <linux/const.h>
+
/* PAGE_SHIFT determines the page size */
#if defined(CONFIG_ARC_PAGE_SIZE_16K)
#define PAGE_SHIFT 14
@@ -25,13 +27,8 @@
#define PAGE_SHIFT 13
#endif
-#ifdef __ASSEMBLY__
-#define PAGE_SIZE (1 << PAGE_SHIFT)
-#define PAGE_OFFSET (0x80000000)
-#else
-#define PAGE_SIZE (1UL << PAGE_SHIFT) /* Default 8K */
-#define PAGE_OFFSET (0x80000000UL) /* Kernel starts at 2G onwards */
-#endif
+#define PAGE_SIZE _BITUL(PAGE_SHIFT) /* Default 8K */
+#define PAGE_OFFSET _AC(0x80000000, UL) /* Kernel starts at 2G onwrds */
#define PAGE_MASK (~(PAGE_SIZE-1))
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index 8fa76567e402..445e63a10754 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -24,7 +24,7 @@
.align 4
# Initial 16 slots are Exception Vectors
-VECTOR stext ; Restart Vector (jump to entry point)
+VECTOR res_service ; Reset Vector
VECTOR mem_service ; Mem exception
VECTOR instr_service ; Instrn Error
VECTOR EV_MachineCheck ; Fatal Machine check
diff --git a/arch/arc/kernel/entry-compact.S b/arch/arc/kernel/entry-compact.S
index 15d457b4403a..59f52035b4ea 100644
--- a/arch/arc/kernel/entry-compact.S
+++ b/arch/arc/kernel/entry-compact.S
@@ -86,7 +86,7 @@
*/
; ********* Critical System Events **********************
-VECTOR res_service ; 0x0, Restart Vector (0x0)
+VECTOR res_service ; 0x0, Reset Vector (0x0)
VECTOR mem_service ; 0x8, Mem exception (0x1)
VECTOR instr_service ; 0x10, Instrn Error (0x2)
@@ -155,13 +155,9 @@ int2_saved_reg:
; ---------------------------------------------
.section .text, "ax",@progbits
-res_service: ; processor restart
- flag 0x1 ; not implemented
- nop
- nop
-reserved: ; processor restart
- rtie ; jump to processor initializations
+reserved:
+ flag 1 ; Unexpected event, halt
;##################### Interrupt Handling ##############################
@@ -175,12 +171,25 @@ ENTRY(handle_interrupt_level2)
;------------------------------------------------------
; if L2 IRQ interrupted a L1 ISR, disable preemption
+ ;
+ ; This is to avoid a potential L1-L2-L1 scenario
+ ; -L1 IRQ taken
+ ; -L2 interrupts L1 (before L1 ISR could run)
+ ; -preemption off IRQ, user task in syscall picked to run
+ ; -RTIE to userspace
+ ; Returns from L2 context fine
+ ; But both L1 and L2 re-enabled, so another L1 can be taken
+ ; while prev L1 is still unserviced
+ ;
;------------------------------------------------------
+ ; L2 interrupting L1 implies both L2 and L1 active
+ ; However both A2 and A1 are NOT set in STATUS32, thus
+ ; need to check STATUS32_L2 to determine if L1 was active
+
ld r9, [sp, PT_status32] ; get statu32_l2 (saved in pt_regs)
bbit0 r9, STATUS_A1_BIT, 1f ; L1 not active when L2 IRQ, so normal
- ; A1 is set in status32_l2
; bump thread_info->preempt_count (Disable preemption)
GET_CURR_THR_INFO_FROM_SP r10
ld r9, [r10, THREAD_INFO_PREEMPT_COUNT]
@@ -320,11 +329,10 @@ END(call_do_page_fault)
; Note that we use realtime STATUS32 (not pt_regs->status32) to
; decide that.
- ; if Returning from Exception
- btst r10, STATUS_AE_BIT
- bnz .Lexcep_ret
+ and.f 0, r10, (STATUS_A1_MASK|STATUS_A2_MASK)
+ bz .Lexcep_or_pure_K_ret
- ; Not Exception so maybe Interrupts (Level 1 or 2)
+ ; Returning from Interrupts (Level 1 or 2)
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
@@ -365,8 +373,7 @@ END(call_do_page_fault)
st r9, [r10, THREAD_INFO_PREEMPT_COUNT]
149:
- ;return from level 2
- INTERRUPT_EPILOGUE 2
+ INTERRUPT_EPILOGUE 2 ; return from level 2 interrupt
debug_marker_l2:
rtie
@@ -374,15 +381,11 @@ not_level2_interrupt:
#endif
- bbit0 r10, STATUS_A1_BIT, .Lpure_k_mode_ret
-
- ;return from level 1
- INTERRUPT_EPILOGUE 1
+ INTERRUPT_EPILOGUE 1 ; return from level 1 interrupt
debug_marker_l1:
rtie
-.Lexcep_ret:
-.Lpure_k_mode_ret:
+.Lexcep_or_pure_K_ret:
;this case is for syscalls or Exceptions or pure kernel mode
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index 812f95e6ae69..689dd867fdff 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -50,28 +50,37 @@
.endm
.section .init.text, "ax",@progbits
- .type stext, @function
- .globl stext
-stext:
- ;-------------------------------------------------------------------
- ; Don't clobber r0-r2 yet. It might have bootloader provided info
- ;-------------------------------------------------------------------
+
+;----------------------------------------------------------------
+; Default Reset Handler (jumped into from Reset vector)
+; - Don't clobber r0,r1,r2 as they might have u-boot provided args
+; - Platforms can override this weak version if needed
+;----------------------------------------------------------------
+WEAK(res_service)
+ j stext
+END(res_service)
+
+;----------------------------------------------------------------
+; Kernel Entry point
+;----------------------------------------------------------------
+ENTRY(stext)
CPU_EARLY_SETUP
#ifdef CONFIG_SMP
- ; Ensure Boot (Master) proceeds. Others wait in platform dependent way
- ; IDENTITY Reg [ 3 2 1 0 ]
- ; (cpu-id) ^^^ => Zero for UP ARC700
- ; => #Core-ID if SMP (Master 0)
- ; Note that non-boot CPUs might not land here if halt-on-reset and
- ; instead breath life from @first_lines_of_secondary, but we still
- ; need to make sure only boot cpu takes this path.
GET_CPU_ID r5
cmp r5, 0
- mov.ne r0, r5
- jne arc_platform_smp_wait_to_boot
+ mov.nz r0, r5
+#ifdef CONFIG_ARC_SMP_HALT_ON_RESET
+ ; Non-Master can proceed as system would be booted sufficiently
+ jnz first_lines_of_secondary
+#else
+ ; Non-Masters wait for Master to boot enough and bring them up
+ jnz arc_platform_smp_wait_to_boot
#endif
+ ; Master falls thru
+#endif
+
; Clear BSS before updating any globals
; XXX: use ZOL here
mov r5, __bss_start
@@ -102,18 +111,14 @@ stext:
GET_TSK_STACK_BASE r9, sp ; r9 = tsk, sp = stack base(output)
j start_kernel ; "C" entry point
+END(stext)
#ifdef CONFIG_SMP
;----------------------------------------------------------------
; First lines of code run by secondary before jumping to 'C'
;----------------------------------------------------------------
.section .text, "ax",@progbits
- .type first_lines_of_secondary, @function
- .globl first_lines_of_secondary
-
-first_lines_of_secondary:
-
- CPU_EARLY_SETUP
+ENTRY(first_lines_of_secondary)
; setup per-cpu idle task as "current" on this CPU
ld r0, [@secondary_idle_tsk]
@@ -126,5 +131,5 @@ first_lines_of_secondary:
GET_TSK_STACK_BASE r0, sp
j start_kernel_secondary
-
+END(first_lines_of_secondary)
#endif
diff --git a/arch/arc/kernel/intc-compact.c b/arch/arc/kernel/intc-compact.c
index 039fac30b5c1..06bcedf19b62 100644
--- a/arch/arc/kernel/intc-compact.c
+++ b/arch/arc/kernel/intc-compact.c
@@ -79,17 +79,16 @@ static struct irq_chip onchip_intc = {
static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
- /*
- * XXX: the IPI IRQ needs to be handled like TIMER too. However ARC core
- * code doesn't own it (like TIMER0). ISS IDU / ezchip define it
- * in platform header which can't be included here as it goes
- * against multi-platform image philisophy
- */
- if (irq == TIMER0_IRQ)
+ switch (irq) {
+ case TIMER0_IRQ:
+#ifdef CONFIG_SMP
+ case IPI_IRQ:
+#endif
irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
- else
+ break;
+ default:
irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq);
-
+ }
return 0;
}
@@ -148,78 +147,15 @@ IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ);
void arch_local_irq_enable(void)
{
-
unsigned long flags = arch_local_save_flags();
- /* Allow both L1 and L2 at the onset */
- flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
-
- /* Called from hard ISR (between irq_enter and irq_exit) */
- if (in_irq()) {
-
- /* If in L2 ISR, don't re-enable any further IRQs as this can
- * cause IRQ priorities to get upside down. e.g. it could allow
- * L1 be taken while in L2 hard ISR which is wrong not only in
- * theory, it can also cause the dreaded L1-L2-L1 scenario
- */
- if (flags & STATUS_A2_MASK)
- flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK);
-
- /* Even if in L1 ISR, allowe Higher prio L2 IRQs */
- else if (flags & STATUS_A1_MASK)
- flags &= ~(STATUS_E1_MASK);
- }
-
- /* called from soft IRQ, ideally we want to re-enable all levels */
-
- else if (in_softirq()) {
-
- /* However if this is case of L1 interrupted by L2,
- * re-enabling both may cause whaco L1-L2-L1 scenario
- * because ARC700 allows level 1 to interrupt an active L2 ISR
- * Thus we disable both
- * However some code, executing in soft ISR wants some IRQs
- * to be enabled so we re-enable L2 only
- *
- * How do we determine L1 intr by L2
- * -A2 is set (means in L2 ISR)
- * -E1 is set in this ISR's pt_regs->status32 which is
- * saved copy of status32_l2 when l2 ISR happened
- */
- struct pt_regs *pt = get_irq_regs();
-
- if ((flags & STATUS_A2_MASK) && pt &&
- (pt->status32 & STATUS_A1_MASK)) {
- /*flags &= ~(STATUS_E1_MASK | STATUS_E2_MASK); */
- flags &= ~(STATUS_E1_MASK);
- }
- }
+ if (flags & STATUS_A2_MASK)
+ flags |= STATUS_E2_MASK;
+ else if (flags & STATUS_A1_MASK)
+ flags |= STATUS_E1_MASK;
arch_local_irq_restore(flags);
}
-#else /* ! CONFIG_ARC_COMPACT_IRQ_LEVELS */
-
-/*
- * Simpler version for only 1 level of interrupt
- * Here we only Worry about Level 1 Bits
- */
-void arch_local_irq_enable(void)
-{
- unsigned long flags;
-
- /*
- * ARC IDE Drivers tries to re-enable interrupts from hard-isr
- * context which is simply wrong
- */
- if (in_irq()) {
- WARN_ONCE(1, "IRQ enabled from hard-isr");
- return;
- }
-
- flags = arch_local_save_flags();
- flags |= (STATUS_E1_MASK | STATUS_E2_MASK);
- arch_local_irq_restore(flags);
-}
-#endif
EXPORT_SYMBOL(arch_local_irq_enable);
+#endif
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 2989a7bcf8a8..2ee226546c6a 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/irqchip.h>
#include <asm/mach_desc.h>
+#include <asm/smp.h>
/*
* Late Interrupt system init called from start_kernel for Boot CPU only
@@ -19,17 +20,20 @@
*/
void __init init_IRQ(void)
{
- /* Any external intc can be setup here */
- if (machine_desc->init_irq)
- machine_desc->init_irq();
-
- /* process the entire interrupt tree in one go */
+ /*
+ * process the entire interrupt tree in one go
+ * Any external intc will be setup provided DT chains them
+ * properly
+ */
irqchip_init();
#ifdef CONFIG_SMP
- /* Master CPU can initialize it's side of IPI */
- if (machine_desc->init_smp)
- machine_desc->init_smp(smp_processor_id());
+ /* a SMP H/w block could do IPI IRQ request here */
+ if (plat_smp_ops.init_irq_cpu)
+ plat_smp_ops.init_irq_cpu(smp_processor_id());
+
+ if (machine_desc->init_cpu_smp)
+ machine_desc->init_cpu_smp(smp_processor_id());
#endif
}
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 4ffd1855f1bd..74a9b074ac3e 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -12,20 +12,14 @@
#include <linux/irq.h>
#include <linux/spinlock.h>
#include <asm/mcip.h>
+#include <asm/setup.h>
static char smp_cpuinfo_buf[128];
static int idu_detected;
static DEFINE_RAW_SPINLOCK(mcip_lock);
-/*
- * Any SMP specific init any CPU does when it comes up.
- * Here we setup the CPU to enable Inter-Processor-Interrupts
- * Called for each CPU
- * -Master : init_IRQ()
- * -Other(s) : start_kernel_secondary()
- */
-void mcip_init_smp(unsigned int cpu)
+static void mcip_setup_per_cpu(int cpu)
{
smp_ipi_irq_setup(cpu, IPI_IRQ);
}
@@ -96,34 +90,8 @@ static void mcip_ipi_clear(int irq)
#endif
}
-volatile int wake_flag;
-
-static void mcip_wakeup_cpu(int cpu, unsigned long pc)
-{
- BUG_ON(cpu == 0);
- wake_flag = cpu;
-}
-
-void arc_platform_smp_wait_to_boot(int cpu)
+static void mcip_probe_n_setup(void)
{
- while (wake_flag != cpu)
- ;
-
- wake_flag = 0;
- __asm__ __volatile__("j @first_lines_of_secondary \n");
-}
-
-struct plat_smp_ops plat_smp_ops = {
- .info = smp_cpuinfo_buf,
- .cpu_kick = mcip_wakeup_cpu,
- .ipi_send = mcip_ipi_send,
- .ipi_clear = mcip_ipi_clear,
-};
-
-void mcip_init_early_smp(void)
-{
-#define IS_AVAIL1(var, str) ((var) ? str : "")
-
struct mcip_bcr {
#ifdef CONFIG_CPU_BIG_ENDIAN
unsigned int pad3:8,
@@ -161,6 +129,14 @@ void mcip_init_early_smp(void)
panic("kernel trying to use non-existent GRTC\n");
}
+struct plat_smp_ops plat_smp_ops = {
+ .info = smp_cpuinfo_buf,
+ .init_early_smp = mcip_probe_n_setup,
+ .init_irq_cpu = mcip_setup_per_cpu,
+ .ipi_send = mcip_ipi_send,
+ .ipi_clear = mcip_ipi_clear,
+};
+
/***************************************************************************
* ARCv2 Interrupt Distribution Unit (IDU)
*
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index cabde9dc0696..c33e77c0ad3e 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -160,10 +160,6 @@ static const struct cpuinfo_data arc_cpu_tbl[] = {
{ {0x00, NULL } }
};
-#define IS_AVAIL1(v, s) ((v) ? s : "")
-#define IS_USED_RUN(v) ((v) ? "" : "(not used) ")
-#define IS_USED_CFG(cfg) IS_USED_RUN(IS_ENABLED(cfg))
-#define IS_AVAIL2(v, s, cfg) IS_AVAIL1(v, s), IS_AVAIL1(v, IS_USED_CFG(cfg))
static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
{
@@ -415,8 +411,9 @@ void __init setup_arch(char **cmdline_p)
if (machine_desc->init_early)
machine_desc->init_early();
- setup_processor();
smp_init_cpus();
+
+ setup_processor();
setup_arch_memory();
/* copy flat DT out of .init and then unflatten it */
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index be13d12420ba..580587805fa3 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -42,8 +42,13 @@ void __init smp_prepare_boot_cpu(void)
}
/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
+ * Called from setup_arch() before calling setup_processor()
+ *
+ * - Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ * - Call early smp init hook. This can initialize a specific multi-core
+ * IP which is say common to several platforms (hence not part of
+ * platform specific int_early() hook)
*/
void __init smp_init_cpus(void)
{
@@ -51,6 +56,9 @@ void __init smp_init_cpus(void)
for (i = 0; i < NR_CPUS; i++)
set_cpu_possible(i, true);
+
+ if (plat_smp_ops.init_early_smp)
+ plat_smp_ops.init_early_smp();
}
/* called from init ( ) => process 1 */
@@ -72,35 +80,29 @@ void __init smp_cpus_done(unsigned int max_cpus)
}
/*
- * After power-up, a non Master CPU needs to wait for Master to kick start it
- *
- * The default implementation halts
- *
- * This relies on platform specific support allowing Master to directly set
- * this CPU's PC (to be @first_lines_of_secondary() and kick start it.
- *
- * In lack of such h/w assist, platforms can override this function
- * - make this function busy-spin on a token, eventually set by Master
- * (from arc_platform_smp_wakeup_cpu())
- * - Once token is available, jump to @first_lines_of_secondary
- * (using inline asm).
- *
- * Alert: can NOT use stack here as it has not been determined/setup for CPU.
- * If it turns out to be elaborate, it's better to code it in assembly
- *
+ * Default smp boot helper for Run-on-reset case where all cores start off
+ * together. Non-masters need to wait for Master to start running.
+ * This is implemented using a flag in memory, which Non-masters spin-wait on.
+ * Master sets it to cpu-id of core to "ungate" it.
*/
-void __weak arc_platform_smp_wait_to_boot(int cpu)
+static volatile int wake_flag;
+
+static void arc_default_smp_cpu_kick(int cpu, unsigned long pc)
{
- /*
- * As a hack for debugging - since debugger will single-step over the
- * FLAG insn - wrap the halt itself it in a self loop
- */
- __asm__ __volatile__(
- "1: \n"
- " flag 1 \n"
- " b 1b \n");
+ BUG_ON(cpu == 0);
+ wake_flag = cpu;
+}
+
+void arc_platform_smp_wait_to_boot(int cpu)
+{
+ while (wake_flag != cpu)
+ ;
+
+ wake_flag = 0;
+ __asm__ __volatile__("j @first_lines_of_secondary \n");
}
+
const char *arc_platform_smp_cpuinfo(void)
{
return plat_smp_ops.info ? : "";
@@ -129,8 +131,12 @@ void start_kernel_secondary(void)
pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
- if (machine_desc->init_smp)
- machine_desc->init_smp(cpu);
+ /* Some SMP H/w setup - for each cpu */
+ if (plat_smp_ops.init_irq_cpu)
+ plat_smp_ops.init_irq_cpu(cpu);
+
+ if (machine_desc->init_cpu_smp)
+ machine_desc->init_cpu_smp(cpu);
arc_local_timer_setup();
@@ -161,6 +167,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
if (plat_smp_ops.cpu_kick)
plat_smp_ops.cpu_kick(cpu,
(unsigned long)first_lines_of_secondary);
+ else
+ arc_default_smp_cpu_kick(cpu, (unsigned long)NULL);
/* wait for 1 sec after kicking the secondary */
wait_till = jiffies + HZ;
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 4294761a2b3e..dfad287f1db1 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -285,7 +285,4 @@ void __init time_init(void)
/* sets up the periodic event timer */
arc_local_timer_setup();
-
- if (machine_desc->init_time)
- machine_desc->init_time();
}
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index dd35bde39f69..894e696bddaa 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -12,7 +12,7 @@
#include <asm/thread_info.h>
OUTPUT_ARCH(arc)
-ENTRY(_stext)
+ENTRY(res_service)
#ifdef CONFIG_CPU_BIG_ENDIAN
jiffies = jiffies_64 + 4;
diff --git a/arch/arc/mm/Makefile b/arch/arc/mm/Makefile
index 7beb941556c3..3703a4969349 100644
--- a/arch/arc/mm/Makefile
+++ b/arch/arc/mm/Makefile
@@ -8,3 +8,4 @@
obj-y := extable.o ioremap.o dma.o fault.o init.o
obj-y += tlb.o tlbex.o cache.o mmap.o
+obj-$(CONFIG_HIGHMEM) += highmem.o
diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c
index 0d1a6e96839f..ff7ff6cbb811 100644
--- a/arch/arc/mm/cache.c
+++ b/arch/arc/mm/cache.c
@@ -25,7 +25,7 @@ static int l2_line_sz;
int ioc_exists;
volatile int slc_enable = 1, ioc_enable = 1;
-void (*_cache_line_loop_ic_fn)(unsigned long paddr, unsigned long vaddr,
+void (*_cache_line_loop_ic_fn)(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz, const int cacheop);
void (*__dma_cache_wback_inv)(unsigned long start, unsigned long sz);
@@ -37,7 +37,6 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
int n = 0;
struct cpuinfo_arc_cache *p;
-#define IS_USED_RUN(v) ((v) ? "" : "(disabled) ")
#define PR_CACHE(p, cfg, str) \
if (!(p)->ver) \
n += scnprintf(buf + n, len - n, str"\t\t: N/A\n"); \
@@ -47,7 +46,7 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
(p)->sz_k, (p)->assoc, (p)->line_len, \
(p)->vipt ? "VIPT" : "PIPT", \
(p)->alias ? " aliasing" : "", \
- IS_ENABLED(cfg) ? "" : " (not used)");
+ IS_USED_CFG(cfg));
PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache");
PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
@@ -63,7 +62,7 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
if (ioc_exists)
n += scnprintf(buf + n, len - n, "IOC\t\t:%s\n",
- IS_USED_RUN(ioc_enable));
+ IS_DISABLED_RUN(ioc_enable));
return buf;
}
@@ -217,7 +216,7 @@ slc_chk:
*/
static inline
-void __cache_line_loop_v2(unsigned long paddr, unsigned long vaddr,
+void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz, const int op)
{
unsigned int aux_cmd;
@@ -254,8 +253,12 @@ void __cache_line_loop_v2(unsigned long paddr, unsigned long vaddr,
}
}
+/*
+ * For ARC700 MMUv3 I-cache and D-cache flushes
+ * Also reused for HS38 aliasing I-cache configuration
+ */
static inline
-void __cache_line_loop_v3(unsigned long paddr, unsigned long vaddr,
+void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz, const int op)
{
unsigned int aux_cmd, aux_tag;
@@ -290,6 +293,16 @@ void __cache_line_loop_v3(unsigned long paddr, unsigned long vaddr,
if (full_page)
write_aux_reg(aux_tag, paddr);
+ /*
+ * This is technically for MMU v4, using the MMU v3 programming model
+ * Special work for HS38 aliasing I-cache configuratino with PAE40
+ * - upper 8 bits of paddr need to be written into PTAG_HI
+ * - (and needs to be written before the lower 32 bits)
+ * Note that PTAG_HI is hoisted outside the line loop
+ */
+ if (is_pae40_enabled() && op == OP_INV_IC)
+ write_aux_reg(ARC_REG_IC_PTAG_HI, (u64)paddr >> 32);
+
while (num_lines-- > 0) {
if (!full_page) {
write_aux_reg(aux_tag, paddr);
@@ -302,14 +315,20 @@ void __cache_line_loop_v3(unsigned long paddr, unsigned long vaddr,
}
/*
- * In HS38x (MMU v4), although icache is VIPT, only paddr is needed for cache
- * maintenance ops (in IVIL reg), as long as icache doesn't alias.
+ * In HS38x (MMU v4), I-cache is VIPT (can alias), D-cache is PIPT
+ * Here's how cache ops are implemented
+ *
+ * - D-cache: only paddr needed (in DC_IVDL/DC_FLDL)
+ * - I-cache Non Aliasing: Despite VIPT, only paddr needed (in IC_IVIL)
+ * - I-cache Aliasing: Both vaddr and paddr needed (in IC_IVIL, IC_PTAG
+ * respectively, similar to MMU v3 programming model, hence
+ * __cache_line_loop_v3() is used)
*
- * For Aliasing icache, vaddr is also needed (in IVIL), while paddr is
- * specified in PTAG (similar to MMU v3)
+ * If PAE40 is enabled, independent of aliasing considerations, the higher bits
+ * needs to be written into PTAG_HI
*/
static inline
-void __cache_line_loop_v4(unsigned long paddr, unsigned long vaddr,
+void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz, const int cacheop)
{
unsigned int aux_cmd;
@@ -336,6 +355,22 @@ void __cache_line_loop_v4(unsigned long paddr, unsigned long vaddr,
num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
+ /*
+ * For HS38 PAE40 configuration
+ * - upper 8 bits of paddr need to be written into PTAG_HI
+ * - (and needs to be written before the lower 32 bits)
+ */
+ if (is_pae40_enabled()) {
+ if (cacheop == OP_INV_IC)
+ /*
+ * Non aliasing I-cache in HS38,
+ * aliasing I-cache handled in __cache_line_loop_v3()
+ */
+ write_aux_reg(ARC_REG_IC_PTAG_HI, (u64)paddr >> 32);
+ else
+ write_aux_reg(ARC_REG_DC_PTAG_HI, (u64)paddr >> 32);
+ }
+
while (num_lines-- > 0) {
write_aux_reg(aux_cmd, paddr);
paddr += L1_CACHE_BYTES;
@@ -413,7 +448,7 @@ static inline void __dc_entire_op(const int op)
/*
* D-Cache Line ops: Per Line INV (discard or wback+discard) or FLUSH (wback)
*/
-static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr,
+static inline void __dc_line_op(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz, const int op)
{
unsigned long flags;
@@ -446,7 +481,7 @@ static inline void __ic_entire_inv(void)
}
static inline void
-__ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
+__ic_line_inv_vaddr_local(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz)
{
unsigned long flags;
@@ -463,7 +498,7 @@ __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr,
#else
struct ic_inv_args {
- unsigned long paddr, vaddr;
+ phys_addr_t paddr, vaddr;
int sz;
};
@@ -474,7 +509,7 @@ static void __ic_line_inv_vaddr_helper(void *info)
__ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz);
}
-static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
+static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr,
unsigned long sz)
{
struct ic_inv_args ic_inv = {
@@ -495,7 +530,7 @@ static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr,
#endif /* CONFIG_ARC_HAS_ICACHE */
-noinline void slc_op(unsigned long paddr, unsigned long sz, const int op)
+noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op)
{
#ifdef CONFIG_ISA_ARCV2
/*
@@ -585,7 +620,7 @@ void flush_dcache_page(struct page *page)
} else if (page_mapped(page)) {
/* kernel reading from page with U-mapping */
- unsigned long paddr = (unsigned long)page_address(page);
+ phys_addr_t paddr = (unsigned long)page_address(page);
unsigned long vaddr = page->index << PAGE_CACHE_SHIFT;
if (addr_not_cache_congruent(paddr, vaddr))
@@ -733,14 +768,14 @@ EXPORT_SYMBOL(flush_icache_range);
* builtin kernel page will not have any virtual mappings.
* kprobe on loadable module will be kernel vaddr.
*/
-void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len)
+void __sync_icache_dcache(phys_addr_t paddr, unsigned long vaddr, int len)
{
__dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV);
__ic_line_inv_vaddr(paddr, vaddr, len);
}
/* wrapper to compile time eliminate alignment checks in flush loop */
-void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
+void __inv_icache_page(phys_addr_t paddr, unsigned long vaddr)
{
__ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE);
}
@@ -749,7 +784,7 @@ void __inv_icache_page(unsigned long paddr, unsigned long vaddr)
* wrapper to clearout kernel or userspace mappings of a page
* For kernel mappings @vaddr == @paddr
*/
-void __flush_dcache_page(unsigned long paddr, unsigned long vaddr)
+void __flush_dcache_page(phys_addr_t paddr, unsigned long vaddr)
{
__dc_line_op(paddr, vaddr & PAGE_MASK, PAGE_SIZE, OP_FLUSH_N_INV);
}
@@ -807,8 +842,8 @@ void flush_anon_page(struct vm_area_struct *vma, struct page *page,
void copy_user_highpage(struct page *to, struct page *from,
unsigned long u_vaddr, struct vm_area_struct *vma)
{
- unsigned long kfrom = (unsigned long)page_address(from);
- unsigned long kto = (unsigned long)page_address(to);
+ void *kfrom = kmap_atomic(from);
+ void *kto = kmap_atomic(to);
int clean_src_k_mappings = 0;
/*
@@ -818,13 +853,16 @@ void copy_user_highpage(struct page *to, struct page *from,
*
* Note that while @u_vaddr refers to DST page's userspace vaddr, it is
* equally valid for SRC page as well
+ *
+ * For !VIPT cache, all of this gets compiled out as
+ * addr_not_cache_congruent() is 0
*/
if (page_mapped(from) && addr_not_cache_congruent(kfrom, u_vaddr)) {
- __flush_dcache_page(kfrom, u_vaddr);
+ __flush_dcache_page((unsigned long)kfrom, u_vaddr);
clean_src_k_mappings = 1;
}
- copy_page((void *)kto, (void *)kfrom);
+ copy_page(kto, kfrom);
/*
* Mark DST page K-mapping as dirty for a later finalization by
@@ -841,11 +879,14 @@ void copy_user_highpage(struct page *to, struct page *from,
* sync the kernel mapping back to physical page
*/
if (clean_src_k_mappings) {
- __flush_dcache_page(kfrom, kfrom);
+ __flush_dcache_page((unsigned long)kfrom, (unsigned long)kfrom);
set_bit(PG_dc_clean, &from->flags);
} else {
clear_bit(PG_dc_clean, &from->flags);
}
+
+ kunmap_atomic(kto);
+ kunmap_atomic(kfrom);
}
void clear_user_page(void *to, unsigned long u_vaddr, struct page *page)
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index d948e4e9d89c..af63f4a13e60 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -18,7 +18,14 @@
#include <asm/pgalloc.h>
#include <asm/mmu.h>
-static int handle_vmalloc_fault(unsigned long address)
+/*
+ * kernel virtual address is required to implement vmalloc/pkmap/fixmap
+ * Refer to asm/processor.h for System Memory Map
+ *
+ * It simply copies the PMD entry (pointer to 2nd level page table or hugepage)
+ * from swapper pgdir to task pgdir. The 2nd level table/page is thus shared
+ */
+noinline static int handle_kernel_vaddr_fault(unsigned long address)
{
/*
* Synchronize this task's top level page-table
@@ -72,8 +79,8 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
* only copy the information from the master page table,
* nothing more.
*/
- if (address >= VMALLOC_START && address <= VMALLOC_END) {
- ret = handle_vmalloc_fault(address);
+ if (address >= VMALLOC_START) {
+ ret = handle_kernel_vaddr_fault(address);
if (unlikely(ret))
goto bad_area_nosemaphore;
else
diff --git a/arch/arc/mm/highmem.c b/arch/arc/mm/highmem.c
new file mode 100644
index 000000000000..065ee6bfa82a
--- /dev/null
+++ b/arch/arc/mm/highmem.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.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.
+ *
+ */
+
+#include <linux/bootmem.h>
+#include <linux/export.h>
+#include <linux/highmem.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+/*
+ * HIGHMEM API:
+ *
+ * kmap() API provides sleep semantics hence refered to as "permanent maps"
+ * It allows mapping LAST_PKMAP pages, using @last_pkmap_nr as the cursor
+ * for book-keeping
+ *
+ * kmap_atomic() can't sleep (calls pagefault_disable()), thus it provides
+ * shortlived ala "temporary mappings" which historically were implemented as
+ * fixmaps (compile time addr etc). Their book-keeping is done per cpu.
+ *
+ * Both these facts combined (preemption disabled and per-cpu allocation)
+ * means the total number of concurrent fixmaps will be limited to max
+ * such allocations in a single control path. Thus KM_TYPE_NR (another
+ * historic relic) is a small'ish number which caps max percpu fixmaps
+ *
+ * ARC HIGHMEM Details
+ *
+ * - the kernel vaddr space from 0x7z to 0x8z (currently used by vmalloc/module)
+ * is now shared between vmalloc and kmap (non overlapping though)
+ *
+ * - Both fixmap/pkmap use a dedicated page table each, hooked up to swapper PGD
+ * This means each only has 1 PGDIR_SIZE worth of kvaddr mappings, which means
+ * 2M of kvaddr space for typical config (8K page and 11:8:13 traversal split)
+ *
+ * - fixmap anyhow needs a limited number of mappings. So 2M kvaddr == 256 PTE
+ * slots across NR_CPUS would be more than sufficient (generic code defines
+ * KM_TYPE_NR as 20).
+ *
+ * - pkmap being preemptible, in theory could do with more than 256 concurrent
+ * mappings. However, generic pkmap code: map_new_virtual(), doesn't traverse
+ * the PGD and only works with a single page table @pkmap_page_table, hence
+ * sets the limit
+ */
+
+extern pte_t * pkmap_page_table;
+static pte_t * fixmap_page_table;
+
+void *kmap(struct page *page)
+{
+ BUG_ON(in_interrupt());
+ if (!PageHighMem(page))
+ return page_address(page);
+
+ return kmap_high(page);
+}
+
+void *kmap_atomic(struct page *page)
+{
+ int idx, cpu_idx;
+ unsigned long vaddr;
+
+ preempt_disable();
+ pagefault_disable();
+ if (!PageHighMem(page))
+ return page_address(page);
+
+ cpu_idx = kmap_atomic_idx_push();
+ idx = cpu_idx + KM_TYPE_NR * smp_processor_id();
+ vaddr = FIXMAP_ADDR(idx);
+
+ set_pte_at(&init_mm, vaddr, fixmap_page_table + idx,
+ mk_pte(page, kmap_prot));
+
+ return (void *)vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic);
+
+void __kunmap_atomic(void *kv)
+{
+ unsigned long kvaddr = (unsigned long)kv;
+
+ if (kvaddr >= FIXMAP_BASE && kvaddr < (FIXMAP_BASE + FIXMAP_SIZE)) {
+
+ /*
+ * Because preemption is disabled, this vaddr can be associated
+ * with the current allocated index.
+ * But in case of multiple live kmap_atomic(), it still relies on
+ * callers to unmap in right order.
+ */
+ int cpu_idx = kmap_atomic_idx();
+ int idx = cpu_idx + KM_TYPE_NR * smp_processor_id();
+
+ WARN_ON(kvaddr != FIXMAP_ADDR(idx));
+
+ pte_clear(&init_mm, kvaddr, fixmap_page_table + idx);
+ local_flush_tlb_kernel_range(kvaddr, kvaddr + PAGE_SIZE);
+
+ kmap_atomic_idx_pop();
+ }
+
+ pagefault_enable();
+ preempt_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
+
+noinline pte_t *alloc_kmap_pgtable(unsigned long kvaddr)
+{
+ pgd_t *pgd_k;
+ pud_t *pud_k;
+ pmd_t *pmd_k;
+ pte_t *pte_k;
+
+ pgd_k = pgd_offset_k(kvaddr);
+ pud_k = pud_offset(pgd_k, kvaddr);
+ pmd_k = pmd_offset(pud_k, kvaddr);
+
+ pte_k = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
+ pmd_populate_kernel(&init_mm, pmd_k, pte_k);
+ return pte_k;
+}
+
+void kmap_init(void)
+{
+ /* Due to recursive include hell, we can't do this in processor.h */
+ BUILD_BUG_ON(PAGE_OFFSET < (VMALLOC_END + FIXMAP_SIZE + PKMAP_SIZE));
+
+ BUILD_BUG_ON(KM_TYPE_NR > PTRS_PER_PTE);
+ pkmap_page_table = alloc_kmap_pgtable(PKMAP_BASE);
+
+ BUILD_BUG_ON(LAST_PKMAP > PTRS_PER_PTE);
+ fixmap_page_table = alloc_kmap_pgtable(FIXMAP_BASE);
+}
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index d44eedd8c322..a9305b5a2cd4 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -15,6 +15,7 @@
#endif
#include <linux/swap.h>
#include <linux/module.h>
+#include <linux/highmem.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/sections.h>
@@ -24,16 +25,22 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE);
char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE);
EXPORT_SYMBOL(empty_zero_page);
-/* Default tot mem from .config */
-static unsigned long arc_mem_sz = 0x20000000; /* some default */
+static const unsigned long low_mem_start = CONFIG_LINUX_LINK_BASE;
+static unsigned long low_mem_sz;
+
+#ifdef CONFIG_HIGHMEM
+static unsigned long min_high_pfn;
+static u64 high_mem_start;
+static u64 high_mem_sz;
+#endif
/* User can over-ride above with "mem=nnn[KkMm]" in cmdline */
static int __init setup_mem_sz(char *str)
{
- arc_mem_sz = memparse(str, NULL) & PAGE_MASK;
+ low_mem_sz = memparse(str, NULL) & PAGE_MASK;
/* early console might not be setup yet - it will show up later */
- pr_info("\"mem=%s\": mem sz set to %ldM\n", str, TO_MB(arc_mem_sz));
+ pr_info("\"mem=%s\": mem sz set to %ldM\n", str, TO_MB(low_mem_sz));
return 0;
}
@@ -41,8 +48,22 @@ early_param("mem", setup_mem_sz);
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
- arc_mem_sz = size & PAGE_MASK;
- pr_info("Memory size set via devicetree %ldM\n", TO_MB(arc_mem_sz));
+ int in_use = 0;
+
+ if (!low_mem_sz) {
+ BUG_ON(base != low_mem_start);
+ low_mem_sz = size;
+ in_use = 1;
+ } else {
+#ifdef CONFIG_HIGHMEM
+ high_mem_start = base;
+ high_mem_sz = size;
+ in_use = 1;
+#endif
+ }
+
+ pr_info("Memory @ %llx [%lldM] %s\n",
+ base, TO_MB(size), !in_use ? "Not used":"");
}
#ifdef CONFIG_BLK_DEV_INITRD
@@ -72,46 +93,62 @@ early_param("initrd", early_initrd);
void __init setup_arch_memory(void)
{
unsigned long zones_size[MAX_NR_ZONES];
- unsigned long end_mem = CONFIG_LINUX_LINK_BASE + arc_mem_sz;
+ unsigned long zones_holes[MAX_NR_ZONES];
init_mm.start_code = (unsigned long)_text;
init_mm.end_code = (unsigned long)_etext;
init_mm.end_data = (unsigned long)_edata;
init_mm.brk = (unsigned long)_end;
- /*
- * We do it here, so that memory is correctly instantiated
- * even if "mem=xxx" cmline over-ride is given and/or
- * DT has memory node. Each causes an update to @arc_mem_sz
- * and we finally add memory one here
- */
- memblock_add(CONFIG_LINUX_LINK_BASE, arc_mem_sz);
-
- /*------------- externs in mm need setting up ---------------*/
-
/* first page of system - kernel .vector starts here */
min_low_pfn = ARCH_PFN_OFFSET;
- /* Last usable page of low mem (no HIGHMEM yet for ARC port) */
- max_low_pfn = max_pfn = PFN_DOWN(end_mem);
+ /* Last usable page of low mem */
+ max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz);
- max_mapnr = max_low_pfn - min_low_pfn;
+#ifdef CONFIG_HIGHMEM
+ min_high_pfn = PFN_DOWN(high_mem_start);
+ max_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
+#endif
+
+ max_mapnr = max_pfn - min_low_pfn;
- /*------------- reserve kernel image -----------------------*/
- memblock_reserve(CONFIG_LINUX_LINK_BASE,
- __pa(_end) - CONFIG_LINUX_LINK_BASE);
+ /*------------- bootmem allocator setup -----------------------*/
+
+ /*
+ * seed the bootmem allocator after any DT memory node parsing or
+ * "mem=xxx" cmdline overrides have potentially updated @arc_mem_sz
+ *
+ * Only low mem is added, otherwise we have crashes when allocating
+ * mem_map[] itself. NO_BOOTMEM allocates mem_map[] at the end of
+ * avail memory, ending in highmem with a > 32-bit address. However
+ * it then tries to memset it with a truncaed 32-bit handle, causing
+ * the crash
+ */
+
+ memblock_add(low_mem_start, low_mem_sz);
+ memblock_reserve(low_mem_start, __pa(_end) - low_mem_start);
#ifdef CONFIG_BLK_DEV_INITRD
- /*------------- reserve initrd image -----------------------*/
if (initrd_start)
memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
#endif
memblock_dump_all();
- /*-------------- node setup --------------------------------*/
+ /*----------------- node/zones setup --------------------------*/
memset(zones_size, 0, sizeof(zones_size));
- zones_size[ZONE_NORMAL] = max_mapnr;
+ memset(zones_holes, 0, sizeof(zones_holes));
+
+ zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn;
+ zones_holes[ZONE_NORMAL] = 0;
+
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
+
+ /* This handles the peripheral address space hole */
+ zones_holes[ZONE_HIGHMEM] = min_high_pfn - max_low_pfn;
+#endif
/*
* We can't use the helper free_area_init(zones[]) because it uses
@@ -122,9 +159,12 @@ void __init setup_arch_memory(void)
free_area_init_node(0, /* node-id */
zones_size, /* num pages per zone */
min_low_pfn, /* first pfn of node */
- NULL); /* NO holes */
+ zones_holes); /* holes */
- high_memory = (void *)end_mem;
+#ifdef CONFIG_HIGHMEM
+ high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
+ kmap_init();
+#endif
}
/*
@@ -135,6 +175,14 @@ void __init setup_arch_memory(void)
*/
void __init mem_init(void)
{
+#ifdef CONFIG_HIGHMEM
+ unsigned long tmp;
+
+ reset_all_zones_managed_pages();
+ for (tmp = min_high_pfn; tmp < max_pfn; tmp++)
+ free_highmem_page(pfn_to_page(tmp));
+#endif
+
free_all_bootmem();
mem_init_print_info(NULL);
}
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 2c7ce8bb7475..0ee739846847 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -109,6 +109,10 @@ DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE;
static inline void __tlb_entry_erase(void)
{
write_aux_reg(ARC_REG_TLBPD1, 0);
+
+ if (is_pae40_enabled())
+ write_aux_reg(ARC_REG_TLBPD1HI, 0);
+
write_aux_reg(ARC_REG_TLBPD0, 0);
write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
}
@@ -182,7 +186,7 @@ static void utlb_invalidate(void)
}
-static void tlb_entry_insert(unsigned int pd0, unsigned int pd1)
+static void tlb_entry_insert(unsigned int pd0, pte_t pd1)
{
unsigned int idx;
@@ -225,10 +229,14 @@ static void tlb_entry_erase(unsigned int vaddr_n_asid)
write_aux_reg(ARC_REG_TLBCOMMAND, TLBDeleteEntry);
}
-static void tlb_entry_insert(unsigned int pd0, unsigned int pd1)
+static void tlb_entry_insert(unsigned int pd0, pte_t pd1)
{
write_aux_reg(ARC_REG_TLBPD0, pd0);
write_aux_reg(ARC_REG_TLBPD1, pd1);
+
+ if (is_pae40_enabled())
+ write_aux_reg(ARC_REG_TLBPD1HI, (u64)pd1 >> 32);
+
write_aux_reg(ARC_REG_TLBCOMMAND, TLBInsertEntry);
}
@@ -240,22 +248,39 @@ static void tlb_entry_insert(unsigned int pd0, unsigned int pd1)
noinline void local_flush_tlb_all(void)
{
+ struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
unsigned long flags;
unsigned int entry;
- struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
+ int num_tlb = mmu->sets * mmu->ways;
local_irq_save(flags);
/* Load PD0 and PD1 with template for a Blank Entry */
write_aux_reg(ARC_REG_TLBPD1, 0);
+
+ if (is_pae40_enabled())
+ write_aux_reg(ARC_REG_TLBPD1HI, 0);
+
write_aux_reg(ARC_REG_TLBPD0, 0);
- for (entry = 0; entry < mmu->num_tlb; entry++) {
+ for (entry = 0; entry < num_tlb; entry++) {
/* write this entry to the TLB */
write_aux_reg(ARC_REG_TLBINDEX, entry);
write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
}
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
+ const int stlb_idx = 0x800;
+
+ /* Blank sTLB entry */
+ write_aux_reg(ARC_REG_TLBPD0, _PAGE_HW_SZ);
+
+ for (entry = stlb_idx; entry < stlb_idx + 16; entry++) {
+ write_aux_reg(ARC_REG_TLBINDEX, entry);
+ write_aux_reg(ARC_REG_TLBCOMMAND, TLBWrite);
+ }
+ }
+
utlb_invalidate();
local_irq_restore(flags);
@@ -409,6 +434,15 @@ static inline void ipi_flush_tlb_range(void *arg)
local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
}
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline void ipi_flush_pmd_tlb_range(void *arg)
+{
+ struct tlb_args *ta = arg;
+
+ local_flush_pmd_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+}
+#endif
+
static inline void ipi_flush_tlb_kernel_range(void *arg)
{
struct tlb_args *ta = (struct tlb_args *)arg;
@@ -449,6 +483,20 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range, &ta, 1);
}
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct tlb_args ta = {
+ .ta_vma = vma,
+ .ta_start = start,
+ .ta_end = end
+ };
+
+ on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_pmd_tlb_range, &ta, 1);
+}
+#endif
+
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
struct tlb_args ta = {
@@ -463,11 +511,12 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
/*
* Routine to create a TLB entry
*/
-void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
+void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep)
{
unsigned long flags;
unsigned int asid_or_sasid, rwx;
- unsigned long pd0, pd1;
+ unsigned long pd0;
+ pte_t pd1;
/*
* create_tlb() assumes that current->mm == vma->mm, since
@@ -499,9 +548,9 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
local_irq_save(flags);
- tlb_paranoid_check(asid_mm(vma->vm_mm, smp_processor_id()), address);
+ tlb_paranoid_check(asid_mm(vma->vm_mm, smp_processor_id()), vaddr);
- address &= PAGE_MASK;
+ vaddr &= PAGE_MASK;
/* update this PTE credentials */
pte_val(*ptep) |= (_PAGE_PRESENT | _PAGE_ACCESSED);
@@ -511,7 +560,7 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
/* ASID for this task */
asid_or_sasid = read_aux_reg(ARC_REG_PID) & 0xff;
- pd0 = address | asid_or_sasid | (pte_val(*ptep) & PTE_BITS_IN_PD0);
+ pd0 = vaddr | asid_or_sasid | (pte_val(*ptep) & PTE_BITS_IN_PD0);
/*
* ARC MMU provides fully orthogonal access bits for K/U mode,
@@ -547,7 +596,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
pte_t *ptep)
{
unsigned long vaddr = vaddr_unaligned & PAGE_MASK;
- unsigned long paddr = pte_val(*ptep) & PAGE_MASK;
+ phys_addr_t paddr = pte_val(*ptep) & PAGE_MASK;
struct page *page = pfn_to_page(pte_pfn(*ptep));
create_tlb(vma, vaddr, ptep);
@@ -580,6 +629,95 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
}
}
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+/*
+ * MMUv4 in HS38x cores supports Super Pages which are basis for Linux THP
+ * support.
+ *
+ * Normal and Super pages can co-exist (ofcourse not overlap) in TLB with a
+ * new bit "SZ" in TLB page desciptor to distinguish between them.
+ * Super Page size is configurable in hardware (4K to 16M), but fixed once
+ * RTL builds.
+ *
+ * The exact THP size a Linx configuration will support is a function of:
+ * - MMU page size (typical 8K, RTL fixed)
+ * - software page walker address split between PGD:PTE:PFN (typical
+ * 11:8:13, but can be changed with 1 line)
+ * So for above default, THP size supported is 8K * (2^8) = 2M
+ *
+ * Default Page Walker is 2 levels, PGD:PTE:PFN, which in THP regime
+ * reduces to 1 level (as PTE is folded into PGD and canonically referred
+ * to as PMD).
+ * Thus THP PMD accessors are implemented in terms of PTE (just like sparc)
+ */
+
+void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
+ pmd_t *pmd)
+{
+ pte_t pte = __pte(pmd_val(*pmd));
+ update_mmu_cache(vma, addr, &pte);
+}
+
+void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+ pgtable_t pgtable)
+{
+ struct list_head *lh = (struct list_head *) pgtable;
+
+ assert_spin_locked(&mm->page_table_lock);
+
+ /* FIFO */
+ if (!pmd_huge_pte(mm, pmdp))
+ INIT_LIST_HEAD(lh);
+ else
+ list_add(lh, (struct list_head *) pmd_huge_pte(mm, pmdp));
+ pmd_huge_pte(mm, pmdp) = pgtable;
+}
+
+pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
+{
+ struct list_head *lh;
+ pgtable_t pgtable;
+
+ assert_spin_locked(&mm->page_table_lock);
+
+ pgtable = pmd_huge_pte(mm, pmdp);
+ lh = (struct list_head *) pgtable;
+ if (list_empty(lh))
+ pmd_huge_pte(mm, pmdp) = NULL;
+ else {
+ pmd_huge_pte(mm, pmdp) = (pgtable_t) lh->next;
+ list_del(lh);
+ }
+
+ pte_val(pgtable[0]) = 0;
+ pte_val(pgtable[1]) = 0;
+
+ return pgtable;
+}
+
+void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ unsigned int cpu;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ cpu = smp_processor_id();
+
+ if (likely(asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID)) {
+ unsigned int asid = hw_pid(vma->vm_mm, cpu);
+
+ /* No need to loop here: this will always be for 1 Huge Page */
+ tlb_entry_erase(start | _PAGE_HW_SZ | asid);
+ }
+
+ local_irq_restore(flags);
+}
+
+#endif
+
/* Read the Cache Build Confuration Registers, Decode them and save into
* the cpuinfo structure for later use.
* No Validation is done here, simply read/convert the BCRs
@@ -598,10 +736,10 @@ void read_decode_mmu_bcr(void)
struct bcr_mmu_3 {
#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int ver:8, ways:4, sets:4, osm:1, reserv:3, pg_sz:4,
+ unsigned int ver:8, ways:4, sets:4, res:3, sasid:1, pg_sz:4,
u_itlb:4, u_dtlb:4;
#else
- unsigned int u_dtlb:4, u_itlb:4, pg_sz:4, reserv:3, osm:1, sets:4,
+ unsigned int u_dtlb:4, u_itlb:4, pg_sz:4, sasid:1, res:3, sets:4,
ways:4, ver:8;
#endif
} *mmu3;
@@ -622,7 +760,7 @@ void read_decode_mmu_bcr(void)
if (mmu->ver <= 2) {
mmu2 = (struct bcr_mmu_1_2 *)&tmp;
- mmu->pg_sz_k = TO_KB(PAGE_SIZE);
+ mmu->pg_sz_k = TO_KB(0x2000);
mmu->sets = 1 << mmu2->sets;
mmu->ways = 1 << mmu2->ways;
mmu->u_dtlb = mmu2->u_dtlb;
@@ -634,6 +772,7 @@ void read_decode_mmu_bcr(void)
mmu->ways = 1 << mmu3->ways;
mmu->u_dtlb = mmu3->u_dtlb;
mmu->u_itlb = mmu3->u_itlb;
+ mmu->sasid = mmu3->sasid;
} else {
mmu4 = (struct bcr_mmu_4 *)&tmp;
mmu->pg_sz_k = 1 << (mmu4->sz0 - 1);
@@ -642,9 +781,9 @@ void read_decode_mmu_bcr(void)
mmu->ways = mmu4->n_ways * 2;
mmu->u_dtlb = mmu4->u_dtlb * 4;
mmu->u_itlb = mmu4->u_itlb * 4;
+ mmu->sasid = mmu4->sasid;
+ mmu->pae = mmu4->pae;
}
-
- mmu->num_tlb = mmu->sets * mmu->ways;
}
char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
@@ -655,14 +794,15 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
if (p_mmu->s_pg_sz_m)
scnprintf(super_pg, 64, "%dM Super Page%s, ",
- p_mmu->s_pg_sz_m, " (not used)");
+ p_mmu->s_pg_sz_m,
+ IS_USED_CFG(CONFIG_TRANSPARENT_HUGEPAGE));
n += scnprintf(buf + n, len - n,
- "MMU [v%x]\t: %dk PAGE, %sJTLB %d (%dx%d), uDTLB %d, uITLB %d %s\n",
+ "MMU [v%x]\t: %dk PAGE, %sJTLB %d (%dx%d), uDTLB %d, uITLB %d %s%s\n",
p_mmu->ver, p_mmu->pg_sz_k, super_pg,
- p_mmu->num_tlb, p_mmu->sets, p_mmu->ways,
+ p_mmu->sets * p_mmu->ways, p_mmu->sets, p_mmu->ways,
p_mmu->u_dtlb, p_mmu->u_itlb,
- IS_ENABLED(CONFIG_ARC_MMU_SASID) ? ",SASID" : "");
+ IS_AVAIL2(p_mmu->pae, "PAE40 ", CONFIG_ARC_HAS_PAE40));
return buf;
}
@@ -690,6 +830,14 @@ void arc_mmu_init(void)
if (mmu->pg_sz_k != TO_KB(PAGE_SIZE))
panic("MMU pg size != PAGE_SIZE (%luk)\n", TO_KB(PAGE_SIZE));
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
+ mmu->s_pg_sz_m != TO_MB(HPAGE_PMD_SIZE))
+ panic("MMU Super pg size != Linux HPAGE_PMD_SIZE (%luM)\n",
+ (unsigned long)TO_MB(HPAGE_PMD_SIZE));
+
+ if (IS_ENABLED(CONFIG_ARC_HAS_PAE40) && !mmu->pae)
+ panic("Hardware doesn't support PAE40\n");
+
/* Enable the MMU */
write_aux_reg(ARC_REG_PID, MMU_ENABLE);
@@ -725,15 +873,15 @@ void arc_mmu_init(void)
* the duplicate one.
* -Knob to be verbose abt it.(TODO: hook them up to debugfs)
*/
-volatile int dup_pd_verbose = 1;/* Be slient abt it or complain (default) */
+volatile int dup_pd_silent; /* Be slient abt it or complain (default) */
void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
struct pt_regs *regs)
{
- int set, way, n;
- unsigned long flags, is_valid;
struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
- unsigned int pd0[mmu->ways], pd1[mmu->ways];
+ unsigned int pd0[mmu->ways];
+ unsigned long flags;
+ int set;
local_irq_save(flags);
@@ -743,14 +891,16 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
/* loop thru all sets of TLB */
for (set = 0; set < mmu->sets; set++) {
+ int is_valid, way;
+
/* read out all the ways of current set */
for (way = 0, is_valid = 0; way < mmu->ways; way++) {
write_aux_reg(ARC_REG_TLBINDEX,
SET_WAY_TO_IDX(mmu, set, way));
write_aux_reg(ARC_REG_TLBCOMMAND, TLBRead);
pd0[way] = read_aux_reg(ARC_REG_TLBPD0);
- pd1[way] = read_aux_reg(ARC_REG_TLBPD1);
is_valid |= pd0[way] & _PAGE_PRESENT;
+ pd0[way] &= PAGE_MASK;
}
/* If all the WAYS in SET are empty, skip to next SET */
@@ -759,30 +909,28 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
/* Scan the set for duplicate ways: needs a nested loop */
for (way = 0; way < mmu->ways - 1; way++) {
+
+ int n;
+
if (!pd0[way])
continue;
for (n = way + 1; n < mmu->ways; n++) {
- if ((pd0[way] & PAGE_MASK) ==
- (pd0[n] & PAGE_MASK)) {
-
- if (dup_pd_verbose) {
- pr_info("Duplicate PD's @"
- "[%d:%d]/[%d:%d]\n",
- set, way, set, n);
- pr_info("TLBPD0[%u]: %08x\n",
- way, pd0[way]);
- }
-
- /*
- * clear entry @way and not @n. This is
- * critical to our optimised loop
- */
- pd0[way] = pd1[way] = 0;
- write_aux_reg(ARC_REG_TLBINDEX,
+ if (pd0[way] != pd0[n])
+ continue;
+
+ if (!dup_pd_silent)
+ pr_info("Dup TLB PD0 %08x @ set %d ways %d,%d\n",
+ pd0[way], set, way, n);
+
+ /*
+ * clear entry @way and not @n.
+ * This is critical to our optimised loop
+ */
+ pd0[way] = 0;
+ write_aux_reg(ARC_REG_TLBINDEX,
SET_WAY_TO_IDX(mmu, set, way));
- __tlb_entry_erase();
- }
+ __tlb_entry_erase();
}
}
}
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index f6f4c3cb505d..63860adc4814 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -205,20 +205,38 @@ ex_saved_reg1:
#endif
lsr r0, r2, PGDIR_SHIFT ; Bits for indexing into PGD
- ld.as r1, [r1, r0] ; PGD entry corresp to faulting addr
- and.f r1, r1, PAGE_MASK ; Ignoring protection and other flags
- ; contains Ptr to Page Table
- bz.d do_slow_path_pf ; if no Page Table, do page fault
+ ld.as r3, [r1, r0] ; PGD entry corresp to faulting addr
+ tst r3, r3
+ bz do_slow_path_pf ; if no Page Table, do page fault
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ and.f 0, r3, _PAGE_HW_SZ ; Is this Huge PMD (thp)
+ add2.nz r1, r1, r0
+ bnz.d 2f ; YES: PGD == PMD has THP PTE: stop pgd walk
+ mov.nz r0, r3
+
+#endif
+ and r1, r3, PAGE_MASK
; Get the PTE entry: The idea is
; (1) x = addr >> PAGE_SHIFT -> masks page-off bits from @fault-addr
; (2) y = x & (PTRS_PER_PTE - 1) -> to get index
- ; (3) z = pgtbl[y]
- ; To avoid the multiply by in end, we do the -2, <<2 below
+ ; (3) z = (pgtbl + y * 4)
+
+#ifdef CONFIG_ARC_HAS_PAE40
+#define PTE_SIZE_LOG 3 /* 8 == 2 ^ 3 */
+#else
+#define PTE_SIZE_LOG 2 /* 4 == 2 ^ 2 */
+#endif
+
+ ; multiply in step (3) above avoided by shifting lesser in step (1)
+ lsr r0, r2, ( PAGE_SHIFT - PTE_SIZE_LOG )
+ and r0, r0, ( (PTRS_PER_PTE - 1) << PTE_SIZE_LOG )
+ ld.aw r0, [r1, r0] ; r0: PTE (lower word only for PAE40)
+ ; r1: PTE ptr
+
+2:
- lsr r0, r2, (PAGE_SHIFT - 2)
- and r0, r0, ( (PTRS_PER_PTE - 1) << 2)
- ld.aw r0, [r1, r0] ; get PTE and PTE ptr for fault addr
#ifdef CONFIG_ARC_DBG_TLB_MISS_COUNT
and.f 0, r0, _PAGE_PRESENT
bz 1f
@@ -233,18 +251,23 @@ ex_saved_reg1:
;-----------------------------------------------------------------
; Convert Linux PTE entry into TLB entry
; A one-word PTE entry is programmed as two-word TLB Entry [PD0:PD1] in mmu
+; (for PAE40, two-words PTE, while three-word TLB Entry [PD0:PD1:PD1HI])
; IN: r0 = PTE, r1 = ptr to PTE
.macro CONV_PTE_TO_TLB
- and r3, r0, PTE_BITS_RWX ; r w x
- lsl r2, r3, 3 ; r w x 0 0 0 (GLOBAL, kernel only)
+ and r3, r0, PTE_BITS_RWX ; r w x
+ lsl r2, r3, 3 ; Kr Kw Kx 0 0 0 (GLOBAL, kernel only)
and.f 0, r0, _PAGE_GLOBAL
- or.z r2, r2, r3 ; r w x r w x (!GLOBAL, user page)
+ or.z r2, r2, r3 ; Kr Kw Kx Ur Uw Ux (!GLOBAL, user page)
and r3, r0, PTE_BITS_NON_RWX_IN_PD1 ; Extract PFN+cache bits from PTE
or r3, r3, r2
- sr r3, [ARC_REG_TLBPD1] ; these go in PD1
+ sr r3, [ARC_REG_TLBPD1] ; paddr[31..13] | Kr Kw Kx Ur Uw Ux | C
+#ifdef CONFIG_ARC_HAS_PAE40
+ ld r3, [r1, 4] ; paddr[39..32]
+ sr r3, [ARC_REG_TLBPD1HI]
+#endif
and r2, r0, PTE_BITS_IN_PD0 ; Extract other PTE flags: (V)alid, (G)lb
@@ -365,7 +388,7 @@ ENTRY(EV_TLBMissD)
lr r3, [ecr]
or r0, r0, _PAGE_ACCESSED ; Accessed bit always
btst_s r3, ECR_C_BIT_DTLB_ST_MISS ; See if it was a Write Access ?
- or.nz r0, r0, _PAGE_MODIFIED ; if Write, set Dirty bit as well
+ or.nz r0, r0, _PAGE_DIRTY ; if Write, set Dirty bit as well
st_s r0, [r1] ; Write back PTE
CONV_PTE_TO_TLB
diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c
index 0a77b19e1df8..1b0f0f458a2b 100644
--- a/arch/arc/plat-axs10x/axs10x.c
+++ b/arch/arc/plat-axs10x/axs10x.c
@@ -455,11 +455,6 @@ static void __init axs103_early_init(void)
axs10x_print_board_ver(AXC003_CREG + 4088, "AXC003 CPU Card");
axs10x_early_init();
-
-#ifdef CONFIG_ARC_MCIP
- /* No Hardware init, but filling the smp ops callbacks */
- mcip_init_early_smp();
-#endif
}
#endif
@@ -487,9 +482,6 @@ static const char *axs103_compat[] __initconst = {
MACHINE_START(AXS103, "axs103")
.dt_compat = axs103_compat,
.init_early = axs103_early_init,
-#ifdef CONFIG_ARC_MCIP
- .init_smp = mcip_init_smp,
-#endif
MACHINE_END
/*
diff --git a/arch/arc/plat-sim/platform.c b/arch/arc/plat-sim/platform.c
index d9e35b4a2f08..dde692812bc1 100644
--- a/arch/arc/plat-sim/platform.c
+++ b/arch/arc/plat-sim/platform.c
@@ -30,8 +30,4 @@ static const char *simulation_compat[] __initconst = {
MACHINE_START(SIMULATION, "simulation")
.dt_compat = simulation_compat,
-#ifdef CONFIG_ARC_MCIP
- .init_early = mcip_init_early_smp,
- .init_smp = mcip_init_smp,
-#endif
MACHINE_END
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 72ad724c67ae..823f90ea65c4 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -645,6 +645,7 @@ config ARCH_SHMOBILE_LEGACY
config ARCH_RPC
bool "RiscPC"
+ depends on MMU
select ARCH_ACORN
select ARCH_MAY_HAVE_PC_FDC
select ARCH_SPARSEMEM_ENABLE
@@ -1410,7 +1411,6 @@ config HAVE_ARM_ARCH_TIMER
config HAVE_ARM_TWD
bool
- depends on SMP
select CLKSRC_OF if OF
help
This options enables support for the ARM timer and watchdog unit
@@ -1470,6 +1470,8 @@ choice
config VMSPLIT_3G
bool "3G/1G user/kernel split"
+ config VMSPLIT_3G_OPT
+ bool "3G/1G user/kernel split (for full 1G low memory)"
config VMSPLIT_2G
bool "2G/2G user/kernel split"
config VMSPLIT_1G
@@ -1481,6 +1483,7 @@ config PAGE_OFFSET
default PHYS_OFFSET if !MMU
default 0x40000000 if VMSPLIT_1G
default 0x80000000 if VMSPLIT_2G
+ default 0xB0000000 if VMSPLIT_3G_OPT
default 0xC0000000
config NR_CPUS
@@ -1695,8 +1698,9 @@ config HIGHMEM
If unsure, say n.
config HIGHPTE
- bool "Allocate 2nd-level pagetables from highmem"
+ bool "Allocate 2nd-level pagetables from highmem" if EXPERT
depends on HIGHMEM
+ default y
help
The VM uses one page of physical memory for each page table.
For systems with a lot of processes, this can use a lot of
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
index 568adf5efde0..d55e3ea89fda 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
@@ -402,11 +402,12 @@
/* SMPS9 unused */
ldo1_reg: ldo1 {
- /* VDD_SD */
+ /* VDD_SD / VDDSHV8 */
regulator-name = "ldo1";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
+ regulator-always-on;
};
ldo2_reg: ldo2 {
diff --git a/arch/arm/boot/dts/armada-385-db-ap.dts b/arch/arm/boot/dts/armada-385-db-ap.dts
index 89f5a95954ed..4047621b137e 100644
--- a/arch/arm/boot/dts/armada-385-db-ap.dts
+++ b/arch/arm/boot/dts/armada-385-db-ap.dts
@@ -46,7 +46,7 @@
/ {
model = "Marvell Armada 385 Access Point Development Board";
- compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada38x";
+ compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada380";
chosen {
stdout-path = "serial1:115200n8";
diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index 63a48490e2f9..d4dbd28d348c 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -152,7 +152,7 @@
};
usb_phy2: phy@a2f400 {
- compatible = "marvell,berlin2-usb-phy";
+ compatible = "marvell,berlin2cd-usb-phy";
reg = <0xa2f400 0x128>;
#phy-cells = <0>;
resets = <&chip_rst 0x104 14>;
@@ -170,7 +170,7 @@
};
usb_phy0: phy@b74000 {
- compatible = "marvell,berlin2-usb-phy";
+ compatible = "marvell,berlin2cd-usb-phy";
reg = <0xb74000 0x128>;
#phy-cells = <0>;
resets = <&chip_rst 0x104 12>;
@@ -178,7 +178,7 @@
};
usb_phy1: phy@b78000 {
- compatible = "marvell,berlin2-usb-phy";
+ compatible = "marvell,berlin2cd-usb-phy";
reg = <0xb78000 0x128>;
#phy-cells = <0>;
resets = <&chip_rst 0x104 13>;
diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts
index 955c24ee4a8c..8c24975e8f9d 100644
--- a/arch/arm/boot/dts/emev2-kzm9d.dts
+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
@@ -35,28 +35,28 @@
button@1 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-1";
linux,code = <KEY_1>;
gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
};
button@2 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-2";
linux,code = <KEY_2>;
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
};
button@3 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-3";
linux,code = <KEY_3>;
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
};
button@4 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
label = "DSW2-4";
linux,code = <KEY_4>;
gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 8f4d76c5e11c..1b95da79293c 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -915,6 +915,11 @@
};
};
+&pmu_system_controller {
+ assigned-clocks = <&pmu_system_controller 0>;
+ assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
&rtc {
status = "okay";
clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index 7d5b386b5ae6..8f40c7e549bd 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -878,6 +878,11 @@
};
};
+&pmu_system_controller {
+ assigned-clocks = <&pmu_system_controller 0>;
+ assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
&rtc {
status = "okay";
clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index b738ce0f9d9b..6e444bb873f9 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -588,10 +588,10 @@
status = "disabled";
};
- uart2: serial@30870000 {
+ uart2: serial@30890000 {
compatible = "fsl,imx7d-uart",
"fsl,imx6q-uart";
- reg = <0x30870000 0x10000>;
+ reg = <0x30890000 0x10000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_UART2_ROOT_CLK>,
<&clks IMX7D_UART2_ROOT_CLK>;
diff --git a/arch/arm/boot/dts/kirkwood-net5big.dts b/arch/arm/boot/dts/kirkwood-net5big.dts
index 36155b749d9f..d2d44df9c8c0 100644
--- a/arch/arm/boot/dts/kirkwood-net5big.dts
+++ b/arch/arm/boot/dts/kirkwood-net5big.dts
@@ -86,6 +86,66 @@
clock-frequency = <32768>;
};
};
+
+ netxbig-leds {
+ blue-sata2 {
+ label = "netxbig:blue:sata2";
+ mode-addr = <5>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 7
+ NETXBIG_LED_SATA 1
+ NETXBIG_LED_TIMER1 3>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ red-sata2 {
+ label = "netxbig:red:sata2";
+ mode-addr = <5>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 2
+ NETXBIG_LED_TIMER1 4>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ blue-sata3 {
+ label = "netxbig:blue:sata3";
+ mode-addr = <6>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 7
+ NETXBIG_LED_SATA 1
+ NETXBIG_LED_TIMER1 3>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ red-sata3 {
+ label = "netxbig:red:sata3";
+ mode-addr = <6>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 2
+ NETXBIG_LED_TIMER1 4>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ blue-sata4 {
+ label = "netxbig:blue:sata4";
+ mode-addr = <7>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 7
+ NETXBIG_LED_SATA 1
+ NETXBIG_LED_TIMER1 3>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ red-sata4 {
+ label = "netxbig:red:sata4";
+ mode-addr = <7>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 2
+ NETXBIG_LED_TIMER1 4>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ };
};
&mdio {
diff --git a/arch/arm/boot/dts/kirkwood-netxbig.dtsi b/arch/arm/boot/dts/kirkwood-netxbig.dtsi
index 1508b12147df..62515a8b99b9 100644
--- a/arch/arm/boot/dts/kirkwood-netxbig.dtsi
+++ b/arch/arm/boot/dts/kirkwood-netxbig.dtsi
@@ -13,6 +13,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <dt-bindings/leds/leds-netxbig.h>
#include "kirkwood.dtsi"
#include "kirkwood-6281.dtsi"
@@ -105,6 +106,85 @@
gpio = <&gpio0 16 GPIO_ACTIVE_HIGH>;
};
};
+
+ netxbig_gpio_ext: netxbig-gpio-ext {
+ compatible = "lacie,netxbig-gpio-ext";
+
+ addr-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH
+ &gpio1 16 GPIO_ACTIVE_HIGH
+ &gpio1 17 GPIO_ACTIVE_HIGH>;
+ data-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH
+ &gpio1 13 GPIO_ACTIVE_HIGH
+ &gpio1 14 GPIO_ACTIVE_HIGH>;
+ enable-gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
+ };
+
+ netxbig-leds {
+ compatible = "lacie,netxbig-leds";
+
+ gpio-ext = <&netxbig_gpio_ext>;
+
+ timers = <NETXBIG_LED_TIMER1 500 500
+ NETXBIG_LED_TIMER2 500 1000>;
+
+ blue-power {
+ label = "netxbig:blue:power";
+ mode-addr = <0>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 1
+ NETXBIG_LED_TIMER1 3
+ NETXBIG_LED_TIMER2 7>;
+ bright-addr = <1>;
+ max-brightness = <7>;
+ };
+ red-power {
+ label = "netxbig:red:power";
+ mode-addr = <0>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 2
+ NETXBIG_LED_TIMER1 4>;
+ bright-addr = <1>;
+ max-brightness = <7>;
+ };
+ blue-sata0 {
+ label = "netxbig:blue:sata0";
+ mode-addr = <3>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 7
+ NETXBIG_LED_SATA 1
+ NETXBIG_LED_TIMER1 3>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ red-sata0 {
+ label = "netxbig:red:sata0";
+ mode-addr = <3>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 2
+ NETXBIG_LED_TIMER1 4>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ blue-sata1 {
+ label = "netxbig:blue:sata1";
+ mode-addr = <4>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 7
+ NETXBIG_LED_SATA 1
+ NETXBIG_LED_TIMER1 3>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ red-sata1 {
+ label = "netxbig:red:sata1";
+ mode-addr = <4>;
+ mode-val = <NETXBIG_LED_OFF 0
+ NETXBIG_LED_ON 2
+ NETXBIG_LED_TIMER1 4>;
+ bright-addr = <2>;
+ max-brightness = <7>;
+ };
+ };
};
&mdio {
diff --git a/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts b/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
index 91146c318798..5b0430041ec6 100644
--- a/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
+++ b/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
@@ -12,7 +12,7 @@
/ {
model = "LogicPD Zoom DM3730 Torpedo Development Kit";
- compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap36xx";
+ compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap3630", "ti,omap3";
gpio_keys {
compatible = "gpio-keys";
diff --git a/arch/arm/boot/dts/meson.dtsi b/arch/arm/boot/dts/meson.dtsi
index 548441384d2a..8c77c87660cd 100644
--- a/arch/arm/boot/dts/meson.dtsi
+++ b/arch/arm/boot/dts/meson.dtsi
@@ -67,7 +67,7 @@
timer@c1109940 {
compatible = "amlogic,meson6-timer";
- reg = <0xc1109940 0x14>;
+ reg = <0xc1109940 0x18>;
interrupts = <0 10 1>;
};
@@ -80,36 +80,37 @@
wdt: watchdog@c1109900 {
compatible = "amlogic,meson6-wdt";
reg = <0xc1109900 0x8>;
+ interrupts = <0 0 1>;
};
uart_AO: serial@c81004c0 {
compatible = "amlogic,meson-uart";
- reg = <0xc81004c0 0x14>;
+ reg = <0xc81004c0 0x18>;
interrupts = <0 90 1>;
clocks = <&clk81>;
status = "disabled";
};
- uart_A: serial@c81084c0 {
+ uart_A: serial@c11084c0 {
compatible = "amlogic,meson-uart";
- reg = <0xc81084c0 0x14>;
- interrupts = <0 90 1>;
+ reg = <0xc11084c0 0x18>;
+ interrupts = <0 26 1>;
clocks = <&clk81>;
status = "disabled";
};
- uart_B: serial@c81084dc {
+ uart_B: serial@c11084dc {
compatible = "amlogic,meson-uart";
- reg = <0xc81084dc 0x14>;
- interrupts = <0 90 1>;
+ reg = <0xc11084dc 0x18>;
+ interrupts = <0 75 1>;
clocks = <&clk81>;
status = "disabled";
};
- uart_C: serial@c8108700 {
+ uart_C: serial@c1108700 {
compatible = "amlogic,meson-uart";
- reg = <0xc8108700 0x14>;
- interrupts = <0 90 1>;
+ reg = <0xc1108700 0x18>;
+ interrupts = <0 93 1>;
clocks = <&clk81>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/omap3-evm-37xx.dts b/arch/arm/boot/dts/omap3-evm-37xx.dts
index 16e8ce350dda..bb339d1648e0 100644
--- a/arch/arm/boot/dts/omap3-evm-37xx.dts
+++ b/arch/arm/boot/dts/omap3-evm-37xx.dts
@@ -13,7 +13,7 @@
/ {
model = "TI OMAP37XX EVM (TMDSEVM3730)";
- compatible = "ti,omap3-evm-37xx", "ti,omap36xx";
+ compatible = "ti,omap3-evm-37xx", "ti,omap3630", "ti,omap3";
memory {
device_type = "memory";
diff --git a/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi b/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi
index b5334ecff13c..fec076eb7aef 100644
--- a/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-sdmmc.dtsi
@@ -90,7 +90,7 @@
regulators {
vccio_sd: LDO_REG4 {
regulator-name = "vccio_sd";
- regulator-min-microvolt = <3300000>;
+ regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-state-mem {
regulator-off-in-suspend;
@@ -116,7 +116,12 @@
cap-sd-highspeed;
card-detect-delay = <200>;
cd-gpios = <&gpio7 5 GPIO_ACTIVE_LOW>;
+ rockchip,default-sample-phase = <90>;
num-slots = <1>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
vmmc-supply = <&vcc33_sd>;
vqmmc-supply = <&vccio_sd>;
};
diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
index 275c78ccc0f3..860cea0a7613 100644
--- a/arch/arm/boot/dts/rk3288-veyron.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
@@ -149,7 +149,9 @@
broken-cd;
bus-width = <8>;
cap-mmc-highspeed;
+ rockchip,default-sample-phase = <158>;
disable-wp;
+ mmc-hs200-1_8v;
mmc-pwrseq = <&emmc_pwrseq>;
non-removable;
num-slots = <1>;
@@ -355,6 +357,10 @@
num-slots = <1>;
pinctrl-names = "default";
pinctrl-0 = <&sdio0_clk &sdio0_cmd &sdio0_bus4>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
vmmc-supply = <&vcc33_sys>;
vqmmc-supply = <&vcc18_wl>;
};
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 906e938fb6bf..4e7c6b7392af 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -222,8 +222,9 @@
sdmmc: dwmmc@ff0c0000 {
compatible = "rockchip,rk3288-dw-mshc";
clock-freq-min-max = <400000 150000000>;
- clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
- clock-names = "biu", "ciu";
+ clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+ <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xff0c0000 0x4000>;
@@ -233,8 +234,9 @@
sdio0: dwmmc@ff0d0000 {
compatible = "rockchip,rk3288-dw-mshc";
clock-freq-min-max = <400000 150000000>;
- clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>;
- clock-names = "biu", "ciu";
+ clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
+ <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xff0d0000 0x4000>;
@@ -244,8 +246,9 @@
sdio1: dwmmc@ff0e0000 {
compatible = "rockchip,rk3288-dw-mshc";
clock-freq-min-max = <400000 150000000>;
- clocks = <&cru HCLK_SDIO1>, <&cru SCLK_SDIO1>;
- clock-names = "biu", "ciu";
+ clocks = <&cru HCLK_SDIO1>, <&cru SCLK_SDIO1>,
+ <&cru SCLK_SDIO1_DRV>, <&cru SCLK_SDIO1_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xff0e0000 0x4000>;
@@ -255,8 +258,9 @@
emmc: dwmmc@ff0f0000 {
compatible = "rockchip,rk3288-dw-mshc";
clock-freq-min-max = <400000 150000000>;
- clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>;
- clock-names = "biu", "ciu";
+ clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
+ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xff0f0000 0x4000>;
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 034cd48ae28b..cc05cde0f9a4 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -921,6 +921,20 @@
clocks = <&twi1_clk>;
status = "disabled";
};
+
+ pioA: pinctrl@fc038000 {
+ compatible = "atmel,sama5d2-pinctrl";
+ reg = <0xfc038000 0x600>;
+ interrupts = <18 IRQ_TYPE_LEVEL_HIGH 7>,
+ <68 IRQ_TYPE_LEVEL_HIGH 7>,
+ <69 IRQ_TYPE_LEVEL_HIGH 7>,
+ <70 IRQ_TYPE_LEVEL_HIGH 7>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ clocks = <&pioA_clk>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
index 810cda743b6d..9c2387b34d0c 100644
--- a/arch/arm/boot/dts/ste-hrefv60plus.dtsi
+++ b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
@@ -56,7 +56,7 @@
/* VMMCI level-shifter enable */
default_hrefv60_cfg2 {
pins = "GPIO169_D22";
- ste,config = <&gpio_out_lo>;
+ ste,config = <&gpio_out_hi>;
};
/* VMMCI level-shifter voltage select */
default_hrefv60_cfg3 {
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index 32a5ccb14e7e..e80e42163883 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -47,35 +47,35 @@
button@1 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <2>;
label = "userpb";
gpios = <&gpio1 0 0x4>;
};
button@2 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <3>;
label = "extkb1";
gpios = <&gpio4 23 0x4>;
};
button@3 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <4>;
label = "extkb2";
gpios = <&gpio4 24 0x4>;
};
button@4 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <5>;
label = "extkb3";
gpios = <&gpio5 1 0x4>;
};
button@5 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <6>;
label = "extkb4";
gpios = <&gpio5 2 0x4>;
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 9d4f86e9c50a..d845bd1448b5 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -234,7 +234,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 246>;
+ */
};
apbmisc@70000800 {
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 1e204a6de12c..819e2ae2cabe 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -258,7 +258,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 251>;
+ */
};
apbdma: dma@0,60020000 {
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index e058709e6d98..969b828505ae 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -244,7 +244,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 224>;
+ */
};
apbmisc@70000800 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index fe04fb5e155f..c6938ad1b543 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -349,7 +349,9 @@
gpio-controller;
#interrupt-cells = <2>;
interrupt-controller;
+ /*
gpio-ranges = <&pinmux 0 0 248>;
+ */
};
apbmisc@70000800 {
diff --git a/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts b/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
index 33963acd7e8f..f80f772d99fb 100644
--- a/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
+++ b/arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
@@ -85,7 +85,7 @@
};
&ethsc {
- interrupts = <0 50 4>;
+ interrupts = <0 52 4>;
};
&serial0 {
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index 1ff2bfa2e183..13ba48c4b03b 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -166,7 +166,6 @@ CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_S3C=y
CONFIG_MMC_SDHCI_S3C_DMA=y
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
CONFIG_MMC_DW_EXYNOS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX77686=y
diff --git a/arch/arm/configs/hisi_defconfig b/arch/arm/configs/hisi_defconfig
index 5997dbc69822..b2e340b272ee 100644
--- a/arch/arm/configs/hisi_defconfig
+++ b/arch/arm/configs/hisi_defconfig
@@ -69,7 +69,6 @@ CONFIG_NOP_USB_XCEIV=y
CONFIG_MMC=y
CONFIG_RTC_CLASS=y
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
CONFIG_MMC_DW_PLTFM=y
CONFIG_RTC_DRV_PL031=y
CONFIG_DMADEVICES=y
diff --git a/arch/arm/configs/lpc18xx_defconfig b/arch/arm/configs/lpc18xx_defconfig
index 1c47f86c3970..b7e8cdab51f9 100644
--- a/arch/arm/configs/lpc18xx_defconfig
+++ b/arch/arm/configs/lpc18xx_defconfig
@@ -119,7 +119,6 @@ CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_MMC=y
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_PCA9532=y
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h
index 916a2744d5c6..97882f9bad12 100644
--- a/arch/arm/include/asm/cmpxchg.h
+++ b/arch/arm/include/asm/cmpxchg.h
@@ -39,6 +39,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
switch (size) {
#if __LINUX_ARM_ARCH__ >= 6
+#ifndef CONFIG_CPU_V6 /* MIN ARCH >= V6K */
case 1:
asm volatile("@ __xchg1\n"
"1: ldrexb %0, [%3]\n"
@@ -49,6 +50,17 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
: "r" (x), "r" (ptr)
: "memory", "cc");
break;
+ case 2:
+ asm volatile("@ __xchg2\n"
+ "1: ldrexh %0, [%3]\n"
+ " strexh %1, %2, [%3]\n"
+ " teq %1, #0\n"
+ " bne 1b"
+ : "=&r" (ret), "=&r" (tmp)
+ : "r" (x), "r" (ptr)
+ : "memory", "cc");
+ break;
+#endif
case 4:
asm volatile("@ __xchg4\n"
"1: ldrex %0, [%3]\n"
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 43908146a5cf..e6b70d9d084e 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -54,6 +54,14 @@ static inline void arch_local_irq_disable(void)
#define local_fiq_enable() __asm__("cpsie f @ __stf" : : : "memory", "cc")
#define local_fiq_disable() __asm__("cpsid f @ __clf" : : : "memory", "cc")
+
+#ifndef CONFIG_CPU_V7M
+#define local_abt_enable() __asm__("cpsie a @ __sta" : : : "memory", "cc")
+#define local_abt_disable() __asm__("cpsid a @ __cla" : : : "memory", "cc")
+#else
+#define local_abt_enable() do { } while (0)
+#define local_abt_disable() do { } while (0)
+#endif
#else
/*
@@ -136,6 +144,8 @@ static inline void arch_local_irq_disable(void)
: "memory", "cc"); \
})
+#define local_abt_enable() do { } while (0)
+#define local_abt_disable() do { } while (0)
#endif
/*
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index cb3a40717edd..5c1ad11aa392 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -47,7 +47,7 @@ struct machine_desc {
unsigned l2c_aux_val; /* L2 cache aux value */
unsigned l2c_aux_mask; /* L2 cache aux mask */
void (*l2c_write_sec)(unsigned long, unsigned);
- struct smp_operations *smp; /* SMP operations */
+ const struct smp_operations *smp; /* SMP operations */
bool (*smp_init)(void);
void (*fixup)(struct tag *, char **);
void (*dt_fixup)(void);
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 98d58bb04ac5..c79b57bf71c4 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -76,10 +76,12 @@
*/
#define XIP_VIRT_ADDR(physaddr) (MODULES_VADDR + ((physaddr) & 0x000fffff))
+#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
/*
* Allow 16MB-aligned ioremap pages
*/
#define IOREMAP_MAX_ORDER 24
+#endif
#else /* CONFIG_MMU */
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index f40354198bad..348caabb7625 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -43,7 +43,7 @@
*/
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
-#define VMALLOC_END 0xff000000UL
+#define VMALLOC_END 0xff800000UL
#define LIBRARY_TEXT_START 0x0c000000
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index ef356659b4f4..3d6dc8b460e4 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -112,7 +112,7 @@ struct smp_operations {
struct of_cpu_method {
const char *method;
- struct smp_operations *ops;
+ const struct smp_operations *ops;
};
#define CPU_METHOD_OF_DECLARE(name, _method, _ops) \
@@ -122,6 +122,6 @@ struct of_cpu_method {
/*
* set platform specific SMP operations
*/
-extern void smp_set_ops(struct smp_operations *);
+extern void smp_set_ops(const struct smp_operations *);
#endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 7cba573c2cc9..7b84657fba35 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -21,13 +21,6 @@
*/
#define __NR_syscalls (392)
-/*
- * *NOTE*: This is a ghost syscall private to the kernel. Only the
- * __kuser_cmpxchg code in entry-armv.S should be aware of its
- * existence. Don't ever use this from user code.
- */
-#define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0)
-
#define __ARCH_WANT_STAT64
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 11c54de9f8cf..65addcbf5b30 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -101,6 +101,7 @@ void __init arm_dt_init_cpu_maps(void)
if (of_property_read_u32(cpu, "reg", &hwid)) {
pr_debug(" * %s missing reg property\n",
cpu->full_name);
+ of_node_put(cpu);
return;
}
@@ -108,8 +109,10 @@ void __init arm_dt_init_cpu_maps(void)
* 8 MSBs must be set to 0 in the DT since the reg property
* defines the MPIDR[23:0].
*/
- if (hwid & ~MPIDR_HWID_BITMASK)
+ if (hwid & ~MPIDR_HWID_BITMASK) {
+ of_node_put(cpu);
return;
+ }
/*
* Duplicate MPIDRs are a recipe for disaster.
@@ -119,9 +122,11 @@ void __init arm_dt_init_cpu_maps(void)
* to avoid matching valid MPIDR[23:0] values.
*/
for (j = 0; j < cpuidx; j++)
- if (WARN(tmp_map[j] == hwid, "Duplicate /cpu reg "
- "properties in the DT\n"))
+ if (WARN(tmp_map[j] == hwid,
+ "Duplicate /cpu reg properties in the DT\n")) {
+ of_node_put(cpu);
return;
+ }
/*
* Build a stashed array of MPIDR values. Numbering scheme
@@ -143,6 +148,7 @@ void __init arm_dt_init_cpu_maps(void)
"max cores %u, capping them\n",
cpuidx, nr_cpu_ids)) {
cpuidx = nr_cpu_ids;
+ of_node_put(cpu);
break;
}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 3e1c26eb32b4..3ce377f7251f 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -427,8 +427,7 @@ ENDPROC(__fiq_abt)
.endm
.macro kuser_cmpxchg_check
-#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \
- !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
+#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS)
#ifndef CONFIG_MMU
#warning "NPTL on non MMU needs fixing"
#else
@@ -859,20 +858,7 @@ __kuser_helper_start:
__kuser_cmpxchg64: @ 0xffff0f60
-#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
-
- /*
- * Poor you. No fast solution possible...
- * The kernel itself must perform the operation.
- * A special ghost syscall is used for that (see traps.c).
- */
- stmfd sp!, {r7, lr}
- ldr r7, 1f @ it's 20 bits
- swi __ARM_NR_cmpxchg64
- ldmfd sp!, {r7, pc}
-1: .word __ARM_NR_cmpxchg64
-
-#elif defined(CONFIG_CPU_32v6K)
+#if defined(CONFIG_CPU_32v6K)
stmfd sp!, {r4, r5, r6, r7}
ldrd r4, r5, [r0] @ load old val
@@ -948,20 +934,7 @@ __kuser_memory_barrier: @ 0xffff0fa0
__kuser_cmpxchg: @ 0xffff0fc0
-#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
-
- /*
- * Poor you. No fast solution possible...
- * The kernel itself must perform the operation.
- * A special ghost syscall is used for that (see traps.c).
- */
- stmfd sp!, {r7, lr}
- ldr r7, 1f @ it's 20 bits
- swi __ARM_NR_cmpxchg
- ldmfd sp!, {r7, pc}
-1: .word __ARM_NR_cmpxchg
-
-#elif __LINUX_ARM_ARCH__ < 6
+#if __LINUX_ARM_ARCH__ < 6
#ifdef CONFIG_MMU
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index dc7d0a95bd36..6284779d64ee 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -35,7 +35,6 @@
#include <asm/cputype.h>
#include <asm/current.h>
#include <asm/hw_breakpoint.h>
-#include <asm/kdebug.h>
#include <asm/traps.h>
/* Breakpoint currently in use for each BRP. */
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
index fd9eefce0a7b..9232caee7060 100644
--- a/arch/arm/kernel/kgdb.c
+++ b/arch/arm/kernel/kgdb.c
@@ -74,7 +74,7 @@ int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
void
sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
{
- struct pt_regs *thread_regs;
+ struct thread_info *ti;
int regno;
/* Just making sure... */
@@ -86,24 +86,17 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
gdb_regs[regno] = 0;
/* Otherwise, we have only some registers from switch_to() */
- thread_regs = task_pt_regs(task);
- gdb_regs[_R0] = thread_regs->ARM_r0;
- gdb_regs[_R1] = thread_regs->ARM_r1;
- gdb_regs[_R2] = thread_regs->ARM_r2;
- gdb_regs[_R3] = thread_regs->ARM_r3;
- gdb_regs[_R4] = thread_regs->ARM_r4;
- gdb_regs[_R5] = thread_regs->ARM_r5;
- gdb_regs[_R6] = thread_regs->ARM_r6;
- gdb_regs[_R7] = thread_regs->ARM_r7;
- gdb_regs[_R8] = thread_regs->ARM_r8;
- gdb_regs[_R9] = thread_regs->ARM_r9;
- gdb_regs[_R10] = thread_regs->ARM_r10;
- gdb_regs[_FP] = thread_regs->ARM_fp;
- gdb_regs[_IP] = thread_regs->ARM_ip;
- gdb_regs[_SPT] = thread_regs->ARM_sp;
- gdb_regs[_LR] = thread_regs->ARM_lr;
- gdb_regs[_PC] = thread_regs->ARM_pc;
- gdb_regs[_CPSR] = thread_regs->ARM_cpsr;
+ ti = task_thread_info(task);
+ gdb_regs[_R4] = ti->cpu_context.r4;
+ gdb_regs[_R5] = ti->cpu_context.r5;
+ gdb_regs[_R6] = ti->cpu_context.r6;
+ gdb_regs[_R7] = ti->cpu_context.r7;
+ gdb_regs[_R8] = ti->cpu_context.r8;
+ gdb_regs[_R9] = ti->cpu_context.r9;
+ gdb_regs[_R10] = ti->cpu_context.sl;
+ gdb_regs[_FP] = ti->cpu_context.fp;
+ gdb_regs[_SPT] = ti->cpu_context.sp;
+ gdb_regs[_PC] = ti->cpu_context.pc;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 48185a773852..b26361355dae 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -80,7 +80,7 @@ static DECLARE_COMPLETION(cpu_running);
static struct smp_operations smp_ops;
-void __init smp_set_ops(struct smp_operations *ops)
+void __init smp_set_ops(const struct smp_operations *ops)
{
if (ops)
smp_ops = *ops;
@@ -400,6 +400,7 @@ asmlinkage void secondary_start_kernel(void)
local_irq_enable();
local_fiq_enable();
+ local_abt_enable();
/*
* OK, it's off to the idle thread for us
@@ -748,6 +749,15 @@ core_initcall(register_cpufreq_notifier);
static void raise_nmi(cpumask_t *mask)
{
+ /*
+ * Generate the backtrace directly if we are running in a calling
+ * context that is not preemptible by the backtrace IPI. Note
+ * that nmi_cpu_backtrace() automatically removes the current cpu
+ * from mask.
+ */
+ if (cpumask_test_cpu(smp_processor_id(), mask) && irqs_disabled())
+ nmi_cpu_backtrace(NULL);
+
smp_cross_call(mask, IPI_CPU_BACKTRACE);
}
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index e9035cda1485..1bfa7a7f5533 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -23,7 +23,6 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>
-#include <asm/smp_plat.h>
#include <asm/smp_twd.h>
/* set up by the platform code */
@@ -34,6 +33,8 @@ static unsigned long twd_timer_rate;
static DEFINE_PER_CPU(bool, percpu_setup_called);
static struct clock_event_device __percpu *twd_evt;
+static unsigned int twd_features =
+ CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
static int twd_ppi;
static int twd_shutdown(struct clock_event_device *clk)
@@ -294,8 +295,7 @@ static void twd_timer_setup(void)
writel_relaxed(0, twd_base + TWD_TIMER_CONTROL);
clk->name = "local_timer";
- clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
- CLOCK_EVT_FEAT_C3STOP;
+ clk->features = twd_features;
clk->rating = 350;
clk->set_state_shutdown = twd_shutdown;
clk->set_state_periodic = twd_set_periodic;
@@ -350,6 +350,8 @@ static int __init twd_local_timer_common_register(struct device_node *np)
goto out_irq;
twd_get_clock(np);
+ if (!of_property_read_bool(np, "always-on"))
+ twd_features |= CLOCK_EVT_FEAT_C3STOP;
/*
* Immediately configure the timer on the boot CPU, unless we need
@@ -392,9 +394,6 @@ static void __init twd_local_timer_of_register(struct device_node *np)
{
int err;
- if (!is_smp() || !setup_max_cpus)
- return;
-
twd_ppi = irq_of_parse_and_map(np, 0);
if (!twd_ppi) {
err = -EINVAL;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 969f9d9e665f..bc698383e822 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -625,58 +625,6 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
set_tls(regs->ARM_r0);
return 0;
-#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
- /*
- * Atomically store r1 in *r2 if *r2 is equal to r0 for user space.
- * Return zero in r0 if *MEM was changed or non-zero if no exchange
- * happened. Also set the user C flag accordingly.
- * If access permissions have to be fixed up then non-zero is
- * returned and the operation has to be re-attempted.
- *
- * *NOTE*: This is a ghost syscall private to the kernel. Only the
- * __kuser_cmpxchg code in entry-armv.S should be aware of its
- * existence. Don't ever use this from user code.
- */
- case NR(cmpxchg):
- for (;;) {
- extern void do_DataAbort(unsigned long addr, unsigned int fsr,
- struct pt_regs *regs);
- unsigned long val;
- unsigned long addr = regs->ARM_r2;
- struct mm_struct *mm = current->mm;
- pgd_t *pgd; pmd_t *pmd; pte_t *pte;
- spinlock_t *ptl;
-
- regs->ARM_cpsr &= ~PSR_C_BIT;
- down_read(&mm->mmap_sem);
- pgd = pgd_offset(mm, addr);
- if (!pgd_present(*pgd))
- goto bad_access;
- pmd = pmd_offset(pgd, addr);
- if (!pmd_present(*pmd))
- goto bad_access;
- pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
- if (!pte_present(*pte) || !pte_write(*pte) || !pte_dirty(*pte)) {
- pte_unmap_unlock(pte, ptl);
- goto bad_access;
- }
- val = *(unsigned long *)addr;
- val -= regs->ARM_r0;
- if (val == 0) {
- *(unsigned long *)addr = regs->ARM_r1;
- regs->ARM_cpsr |= PSR_C_BIT;
- }
- pte_unmap_unlock(pte, ptl);
- up_read(&mm->mmap_sem);
- return val;
-
- bad_access:
- up_read(&mm->mmap_sem);
- /* simulate a write access fault */
- do_DataAbort(addr, 15 + (1 << 11), regs);
- }
-#endif
-
default:
/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
if not implemented, rather than raising SIGILL. This
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 210eccadb69a..356970f3b25e 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -21,6 +21,7 @@ config KVM
depends on MMU && OF
select PREEMPT_NOTIFIERS
select ANON_INODES
+ select ARM_GIC
select HAVE_KVM_CPU_RELAX_INTERCEPT
select HAVE_KVM_ARCH_TLB_FLUSH_ALL
select KVM_MMIO
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dc017adfddc8..78b286994577 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1080,7 +1080,7 @@ static int init_hyp_mode(void)
*/
err = kvm_timer_hyp_init();
if (err)
- goto out_free_mappings;
+ goto out_free_context;
#ifndef CONFIG_HOTPLUG_CPU
free_boot_hyp_pgd();
diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S
index 970d6c043774..e936352ccb00 100644
--- a/arch/arm/lib/clear_user.S
+++ b/arch/arm/lib/clear_user.S
@@ -9,6 +9,7 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/unwind.h>
.text
@@ -20,6 +21,8 @@
*/
ENTRY(__clear_user_std)
WEAK(arm_clear_user)
+UNWIND(.fnstart)
+UNWIND(.save {r1, lr})
stmfd sp!, {r1, lr}
mov r2, #0
cmp r1, #4
@@ -44,6 +47,7 @@ WEAK(arm_clear_user)
USER( strnebt r2, [r0])
mov r0, #0
ldmfd sp!, {r1, pc}
+UNWIND(.fnend)
ENDPROC(arm_clear_user)
ENDPROC(__clear_user_std)
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index 4a87e86dec45..7c21760f590f 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -200,15 +200,15 @@ no_clk:
args.args_count = 0;
child_domain = of_genpd_get_from_provider(&args);
if (IS_ERR(child_domain))
- goto next_pd;
+ continue;
if (of_parse_phandle_with_args(np, "power-domains",
"#power-domain-cells", 0, &args) != 0)
- goto next_pd;
+ continue;
parent_domain = of_genpd_get_from_provider(&args);
if (IS_ERR(parent_domain))
- goto next_pd;
+ continue;
if (pm_genpd_add_subdomain(parent_domain, child_domain))
pr_warn("%s failed to add subdomain: %s\n",
@@ -216,8 +216,6 @@ no_clk:
else
pr_info("%s has as child subdomain: %s.\n",
parent_domain->name, child_domain->name);
-next_pd:
- of_node_put(np);
}
return 0;
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index c86a5a0aefac..e20fc4178b15 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -117,11 +117,4 @@ config MACH_KIRKWOOD
Say 'Y' here if you want your kernel to support boards based
on the Marvell Kirkwood device tree.
-config MACH_NETXBIG
- bool "LaCie 2Big and 5Big Network v2"
- depends on MACH_KIRKWOOD
- help
- Say 'Y' here if you want your kernel to support the
- LaCie 2Big and 5Big Network v2
-
endif
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index b4f01497ce0b..ecf9e0c3b107 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -13,4 +13,3 @@ endif
obj-$(CONFIG_MACH_DOVE) += dove.o
obj-$(CONFIG_MACH_KIRKWOOD) += kirkwood.o kirkwood-pm.o
-obj-$(CONFIG_MACH_NETXBIG) += netxbig.o
diff --git a/arch/arm/mach-mvebu/board.h b/arch/arm/mach-mvebu/board.h
deleted file mode 100644
index 98e32cc2ef3d..000000000000
--- a/arch/arm/mach-mvebu/board.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Board functions for Marvell System On Chip
- *
- * Copyright (C) 2014
- *
- * Andrew Lunn <andrew@lunn.ch>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __ARCH_MVEBU_BOARD_H
-#define __ARCH_MVEBU_BOARD_H
-
-#ifdef CONFIG_MACH_NETXBIG
-void netxbig_init(void);
-#else
-static inline void netxbig_init(void) {};
-#endif
-#endif
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index 925f75f54268..f9d8e1ea7183 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -25,7 +25,6 @@
#include "kirkwood.h"
#include "kirkwood-pm.h"
#include "common.h"
-#include "board.h"
static struct resource kirkwood_cpufreq_resources[] = {
[0] = {
@@ -180,9 +179,6 @@ static void __init kirkwood_dt_init(void)
kirkwood_pm_init();
kirkwood_dt_eth_fixup();
- if (of_machine_is_compatible("lacie,netxbig"))
- netxbig_init();
-
of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
}
diff --git a/arch/arm/mach-mvebu/netxbig.c b/arch/arm/mach-mvebu/netxbig.c
deleted file mode 100644
index 94b11b6585a4..000000000000
--- a/arch/arm/mach-mvebu/netxbig.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * arch/arm/mach-mvbu/board-netxbig.c
- *
- * LaCie 2Big and 5Big Network v2 board setup
- *
- * Copyright (C) 2010 Simon Guinot <sguinot@lacie.com>
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/leds-kirkwood-netxbig.h>
-#include "common.h"
-
-/*****************************************************************************
- * GPIO extension LEDs
- ****************************************************************************/
-
-/*
- * The LEDs are controlled by a CPLD and can be configured through a GPIO
- * extension bus:
- *
- * - address register : bit [0-2] -> GPIO [47-49]
- * - data register : bit [0-2] -> GPIO [44-46]
- * - enable register : GPIO 29
- */
-
-static int netxbig_v2_gpio_ext_addr[] = { 47, 48, 49 };
-static int netxbig_v2_gpio_ext_data[] = { 44, 45, 46 };
-
-static struct netxbig_gpio_ext netxbig_v2_gpio_ext = {
- .addr = netxbig_v2_gpio_ext_addr,
- .num_addr = ARRAY_SIZE(netxbig_v2_gpio_ext_addr),
- .data = netxbig_v2_gpio_ext_data,
- .num_data = ARRAY_SIZE(netxbig_v2_gpio_ext_data),
- .enable = 29,
-};
-
-/*
- * Address register selection:
- *
- * addr | register
- * ----------------------------
- * 0 | front LED
- * 1 | front LED brightness
- * 2 | SATA LED brightness
- * 3 | SATA0 LED
- * 4 | SATA1 LED
- * 5 | SATA2 LED
- * 6 | SATA3 LED
- * 7 | SATA4 LED
- *
- * Data register configuration:
- *
- * data | LED brightness
- * -------------------------------------------------
- * 0 | min (off)
- * - | -
- * 7 | max
- *
- * data | front LED mode
- * -------------------------------------------------
- * 0 | fix off
- * 1 | fix blue on
- * 2 | fix red on
- * 3 | blink blue on=1 sec and blue off=1 sec
- * 4 | blink red on=1 sec and red off=1 sec
- * 5 | blink blue on=2.5 sec and red on=0.5 sec
- * 6 | blink blue on=1 sec and red on=1 sec
- * 7 | blink blue on=0.5 sec and blue off=2.5 sec
- *
- * data | SATA LED mode
- * -------------------------------------------------
- * 0 | fix off
- * 1 | SATA activity blink
- * 2 | fix red on
- * 3 | blink blue on=1 sec and blue off=1 sec
- * 4 | blink red on=1 sec and red off=1 sec
- * 5 | blink blue on=2.5 sec and red on=0.5 sec
- * 6 | blink blue on=1 sec and red on=1 sec
- * 7 | fix blue on
- */
-
-static int netxbig_v2_red_mled[NETXBIG_LED_MODE_NUM] = {
- [NETXBIG_LED_OFF] = 0,
- [NETXBIG_LED_ON] = 2,
- [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
- [NETXBIG_LED_TIMER1] = 4,
- [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
-};
-
-static int netxbig_v2_blue_pwr_mled[NETXBIG_LED_MODE_NUM] = {
- [NETXBIG_LED_OFF] = 0,
- [NETXBIG_LED_ON] = 1,
- [NETXBIG_LED_SATA] = NETXBIG_LED_INVALID_MODE,
- [NETXBIG_LED_TIMER1] = 3,
- [NETXBIG_LED_TIMER2] = 7,
-};
-
-static int netxbig_v2_blue_sata_mled[NETXBIG_LED_MODE_NUM] = {
- [NETXBIG_LED_OFF] = 0,
- [NETXBIG_LED_ON] = 7,
- [NETXBIG_LED_SATA] = 1,
- [NETXBIG_LED_TIMER1] = 3,
- [NETXBIG_LED_TIMER2] = NETXBIG_LED_INVALID_MODE,
-};
-
-static struct netxbig_led_timer netxbig_v2_led_timer[] = {
- [0] = {
- .delay_on = 500,
- .delay_off = 500,
- .mode = NETXBIG_LED_TIMER1,
- },
- [1] = {
- .delay_on = 500,
- .delay_off = 1000,
- .mode = NETXBIG_LED_TIMER2,
- },
-};
-
-#define NETXBIG_LED(_name, maddr, mval, baddr) \
- { .name = _name, \
- .mode_addr = maddr, \
- .mode_val = mval, \
- .bright_addr = baddr }
-
-static struct netxbig_led net2big_v2_leds_ctrl[] = {
- NETXBIG_LED("net2big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
- NETXBIG_LED("net2big-v2:red:power", 0, netxbig_v2_red_mled, 1),
- NETXBIG_LED("net2big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net2big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net2big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net2big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
-};
-
-static struct netxbig_led_platform_data net2big_v2_leds_data = {
- .gpio_ext = &netxbig_v2_gpio_ext,
- .timer = netxbig_v2_led_timer,
- .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
- .leds = net2big_v2_leds_ctrl,
- .num_leds = ARRAY_SIZE(net2big_v2_leds_ctrl),
-};
-
-static struct netxbig_led net5big_v2_leds_ctrl[] = {
- NETXBIG_LED("net5big-v2:blue:power", 0, netxbig_v2_blue_pwr_mled, 1),
- NETXBIG_LED("net5big-v2:red:power", 0, netxbig_v2_red_mled, 1),
- NETXBIG_LED("net5big-v2:blue:sata0", 3, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata0", 3, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata1", 4, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata1", 4, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata2", 5, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata2", 5, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata3", 6, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata3", 6, netxbig_v2_red_mled, 2),
- NETXBIG_LED("net5big-v2:blue:sata4", 7, netxbig_v2_blue_sata_mled, 2),
- NETXBIG_LED("net5big-v2:red:sata4", 7, netxbig_v2_red_mled, 2),
-};
-
-static struct netxbig_led_platform_data net5big_v2_leds_data = {
- .gpio_ext = &netxbig_v2_gpio_ext,
- .timer = netxbig_v2_led_timer,
- .num_timer = ARRAY_SIZE(netxbig_v2_led_timer),
- .leds = net5big_v2_leds_ctrl,
- .num_leds = ARRAY_SIZE(net5big_v2_leds_ctrl),
-};
-
-static struct platform_device netxbig_v2_leds = {
- .name = "leds-netxbig",
- .id = -1,
- .dev = {
- .platform_data = &net2big_v2_leds_data,
- },
-};
-
-void __init netxbig_init(void)
-{
-
- if (of_machine_is_compatible("lacie,net5big_v2"))
- netxbig_v2_leds.dev.platform_data = &net5big_v2_leds_data;
- platform_device_register(&netxbig_v2_leds);
-}
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index b3a0dff67e3f..33d1460a5639 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -49,6 +49,7 @@ config SOC_OMAP5
select OMAP_INTERCONNECT
select OMAP_INTERCONNECT_BARRIER
select PM_OPP if PM
+ select ZONE_DMA if ARM_LPAE
config SOC_AM33XX
bool "TI AM33XX"
@@ -78,6 +79,7 @@ config SOC_DRA7XX
select OMAP_INTERCONNECT
select OMAP_INTERCONNECT_BARRIER
select PM_OPP if PM
+ select ZONE_DMA if ARM_LPAE
config ARCH_OMAP2PLUS
bool
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 6133eaac685d..fb219a30c10c 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -106,6 +106,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
MACHINE_END
static const char *const omap36xx_boards_compat[] __initconst = {
+ "ti,omap3630",
"ti,omap36xx",
NULL,
};
@@ -243,6 +244,9 @@ static const char *const omap5_boards_compat[] __initconst = {
};
DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+ .dma_zone_size = SZ_2G,
+#endif
.reserve = omap_reserve,
.smp = smp_ops(omap4_smp_ops),
.map_io = omap5_map_io,
@@ -288,6 +292,9 @@ static const char *const dra74x_boards_compat[] __initconst = {
};
DT_MACHINE_START(DRA74X_DT, "Generic DRA74X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+ .dma_zone_size = SZ_2G,
+#endif
.reserve = omap_reserve,
.smp = smp_ops(omap4_smp_ops),
.map_io = dra7xx_map_io,
@@ -308,6 +315,9 @@ static const char *const dra72x_boards_compat[] __initconst = {
};
DT_MACHINE_START(DRA72X_DT, "Generic DRA72X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+ .dma_zone_size = SZ_2G,
+#endif
.reserve = omap_reserve,
.map_io = dra7xx_map_io,
.init_early = dra7xx_init_early,
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index ea56397599c2..1dfe34654c43 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -559,7 +559,14 @@ static void pdata_quirks_check(struct pdata_init *quirks)
void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
{
- omap_sdrc_init(NULL, NULL);
+ /*
+ * We still need this for omap2420 and omap3 PM to work, others are
+ * using drivers/misc/sram.c already.
+ */
+ if (of_machine_is_compatible("ti,omap2420") ||
+ of_machine_is_compatible("ti,omap3"))
+ omap_sdrc_init(NULL, NULL);
+
pdata_quirks_check(auxdata_quirks);
of_platform_populate(NULL, omap_dt_match_table,
omap_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 06005d3f2ba3..20ce2d386f17 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -42,10 +42,6 @@
#define PECR_IS(n) ((1 << ((n) * 2)) << 29)
extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-#ifdef CONFIG_PM
-
-#define ISRAM_START 0x5c000000
-#define ISRAM_SIZE SZ_256K
/*
* NAND NFC: DFI bus arbitration subset
@@ -54,6 +50,11 @@ extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
#define NDCR_ND_ARB_EN (1 << 12)
#define NDCR_ND_ARB_CNTL (1 << 19)
+#ifdef CONFIG_PM
+
+#define ISRAM_START 0x5c000000
+#define ISRAM_SIZE SZ_256K
+
static void __iomem *sram;
static unsigned long wakeup_src;
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index df7537f12469..c21941349b3e 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -419,28 +419,24 @@ config CPU_THUMBONLY
config CPU_32v3
bool
select CPU_USE_DOMAINS if MMU
- select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select NEED_KUSER_HELPERS
select TLS_REG_EMUL if SMP || !MMU
config CPU_32v4
bool
select CPU_USE_DOMAINS if MMU
- select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select NEED_KUSER_HELPERS
select TLS_REG_EMUL if SMP || !MMU
config CPU_32v4T
bool
select CPU_USE_DOMAINS if MMU
- select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select NEED_KUSER_HELPERS
select TLS_REG_EMUL if SMP || !MMU
config CPU_32v5
bool
select CPU_USE_DOMAINS if MMU
- select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select NEED_KUSER_HELPERS
select TLS_REG_EMUL if SMP || !MMU
@@ -805,14 +801,6 @@ config TLS_REG_EMUL
a few prototypes like that in existence) and therefore access to
that required register must be emulated.
-config NEEDS_SYSCALL_FOR_CMPXCHG
- bool
- select NEED_KUSER_HELPERS
- help
- SMP on a pre-ARMv6 processor? Well OK then.
- Forget about fast user space cmpxchg support.
- It is just not possible.
-
config NEED_KUSER_HELPERS
bool
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 1a7815e5421b..ad4eb2d26e16 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1407,12 +1407,19 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
unsigned long uaddr = vma->vm_start;
unsigned long usize = vma->vm_end - vma->vm_start;
struct page **pages = __iommu_get_pages(cpu_addr, attrs);
+ unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ unsigned long off = vma->vm_pgoff;
vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
if (!pages)
return -ENXIO;
+ if (off >= nr_pages || (usize >> PAGE_SHIFT) > nr_pages - off)
+ return -ENXIO;
+
+ pages += off;
+
do {
int ret = vm_insert_page(vma, uaddr, *pages++);
if (ret) {
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 0d629b8f973f..daafcf121ce0 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -593,6 +593,28 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
arm_notify_die("", regs, &info, ifsr, 0);
}
+/*
+ * Abort handler to be used only during first unmasking of asynchronous aborts
+ * on the boot CPU. This makes sure that the machine will not die if the
+ * firmware/bootloader left an imprecise abort pending for us to trip over.
+ */
+static int __init early_abort_handler(unsigned long addr, unsigned int fsr,
+ struct pt_regs *regs)
+{
+ pr_warn("Hit pending asynchronous external abort (FSR=0x%08x) during "
+ "first unmask, this is most likely caused by a "
+ "firmware/bootloader bug.\n", fsr);
+
+ return 0;
+}
+
+void __init early_abt_enable(void)
+{
+ fsr_info[22].fn = early_abort_handler;
+ local_abt_enable();
+ fsr_info[22].fn = do_bad;
+}
+
#ifndef CONFIG_ARM_LPAE
static int __init exceptions_init(void)
{
diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h
index cf08bdfbe0d6..05ec5e0df32d 100644
--- a/arch/arm/mm/fault.h
+++ b/arch/arm/mm/fault.h
@@ -24,5 +24,6 @@ static inline int fsr_fs(unsigned int fsr)
void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
unsigned long search_exception_table(unsigned long addr);
+void early_abt_enable(void);
#endif /* __ARCH_ARM_FAULT_H */
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 7cd15143a507..4867f5daf82c 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -38,6 +38,7 @@
#include <asm/mach/pci.h>
#include <asm/fixmap.h>
+#include "fault.h"
#include "mm.h"
#include "tcm.h"
@@ -1363,6 +1364,9 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
*/
local_flush_tlb_all();
flush_cache_all();
+
+ /* Enable asynchronous aborts */
+ early_abt_enable();
}
static void __init kmap_init(void)
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 876060bcceeb..b8efb8cd1f73 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -614,6 +614,7 @@ load_common:
case BPF_LD | BPF_B | BPF_IND:
load_order = 0;
load_ind:
+ update_on_xread(ctx);
OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
goto load_common;
case BPF_LDX | BPF_IMM:
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 2235081a04ee..8861c367d061 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -495,7 +495,7 @@ void __init orion_ge00_switch_init(struct dsa_platform_data *d, int irq)
d->netdev = &orion_ge00.dev;
for (i = 0; i < d->nr_chips; i++)
- d->chip[i].host_dev = &orion_ge00_shared.dev;
+ d->chip[i].host_dev = &orion_ge_mvmdio.dev;
orion_switch_device.dev.platform_data = d;
platform_device_register(&orion_switch_device);
diff --git a/arch/arm/vdso/vdsomunge.c b/arch/arm/vdso/vdsomunge.c
index aedec81d1198..f6455273b2f8 100644
--- a/arch/arm/vdso/vdsomunge.c
+++ b/arch/arm/vdso/vdsomunge.c
@@ -45,7 +45,6 @@
* it does.
*/
-#include <byteswap.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
@@ -59,6 +58,16 @@
#include <sys/types.h>
#include <unistd.h>
+#define swab16(x) \
+ ((((x) & 0x00ff) << 8) | \
+ (((x) & 0xff00) >> 8))
+
+#define swab32(x) \
+ ((((x) & 0x000000ff) << 24) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0xff000000) >> 24))
+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define HOST_ORDER ELFDATA2LSB
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -104,17 +113,17 @@ static void cleanup(void)
static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
{
- return swap ? bswap_32(word) : word;
+ return swap ? swab32(word) : word;
}
static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
{
- return swap ? bswap_16(half) : half;
+ return swap ? swab16(half) : half;
}
static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
{
- *dst = swap ? bswap_32(val) : val;
+ *dst = swap ? swab32(val) : val;
}
int main(int argc, char **argv)
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index f9914d7c1bb0..d10b5d483022 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -42,7 +42,7 @@ endif
CHECKFLAGS += -D__aarch64__
ifeq ($(CONFIG_ARM64_ERRATUM_843419), y)
-CFLAGS_MODULE += -mcmodel=large
+KBUILD_CFLAGS_MODULE += -mcmodel=large
endif
# Default value
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index d831bc2ac204..fac1720472f9 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -477,6 +477,16 @@
reg = <0x0 0x7c600000 0x0 0x200000>;
pmd-controller = <3>;
};
+
+ edacl3@7e600000 {
+ compatible = "apm,xgene-edac-l3";
+ reg = <0x0 0x7e600000 0x0 0x1000>;
+ };
+
+ edacsoc@7e930000 {
+ compatible = "apm,xgene-edac-soc-v1";
+ reg = <0x0 0x7e930000 0x0 0x1000>;
+ };
};
pcie0: pcie@1f2b0000 {
diff --git a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
index 637e046f0e36..3c386680357e 100644
--- a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
@@ -61,42 +61,42 @@
button@1 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <116>;
label = "POWER";
gpios = <&iofpga_gpio0 0 0x4>;
};
button@2 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <102>;
label = "HOME";
gpios = <&iofpga_gpio0 1 0x4>;
};
button@3 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <152>;
label = "RLOCK";
gpios = <&iofpga_gpio0 2 0x4>;
};
button@4 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <115>;
label = "VOL+";
gpios = <&iofpga_gpio0 3 0x4>;
};
button@5 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <114>;
label = "VOL-";
gpios = <&iofpga_gpio0 4 0x4>;
};
button@6 {
debounce_interval = <50>;
- wakeup = <1>;
+ wakeup-source;
linux,code = <99>;
label = "NMI";
gpios = <&iofpga_gpio0 5 0x4>;
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 3bc498c250dc..41e58fe3c041 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -44,7 +44,7 @@
#define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2)
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5)
-#define __NR_compat_syscalls 388
+#define __NR_compat_syscalls 390
#endif
#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index cef934a90f17..5b925b761a2a 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -797,3 +797,12 @@ __SYSCALL(__NR_memfd_create, sys_memfd_create)
__SYSCALL(__NR_bpf, sys_bpf)
#define __NR_execveat 387
__SYSCALL(__NR_execveat, compat_sys_execveat)
+#define __NR_userfaultfd 388
+__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
+#define __NR_membarrier 389
+__SYSCALL(__NR_membarrier, sys_membarrier)
+
+/*
+ * Please add new compat syscalls above this comment and update
+ * __NR_compat_syscalls in asm/unistd.h.
+ */
diff --git a/arch/arm64/include/uapi/asm/signal.h b/arch/arm64/include/uapi/asm/signal.h
index 8d1e7236431b..991bf5db2ca1 100644
--- a/arch/arm64/include/uapi/asm/signal.h
+++ b/arch/arm64/include/uapi/asm/signal.h
@@ -19,6 +19,9 @@
/* Required for AArch32 compatibility. */
#define SA_RESTORER 0x04000000
+#define MINSIGSTKSZ 5120
+#define SIGSTKSZ 16384
+
#include <asm-generic/signal.h>
#endif
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index bcee7abac68e..937f5e58a4d3 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -284,21 +284,23 @@ static void register_insn_emulation_sysctl(struct ctl_table *table)
__asm__ __volatile__( \
ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, \
CONFIG_ARM64_PAN) \
- " mov %w2, %w1\n" \
- "0: ldxr"B" %w1, [%3]\n" \
- "1: stxr"B" %w0, %w2, [%3]\n" \
+ "0: ldxr"B" %w2, [%3]\n" \
+ "1: stxr"B" %w0, %w1, [%3]\n" \
" cbz %w0, 2f\n" \
" mov %w0, %w4\n" \
+ " b 3f\n" \
"2:\n" \
+ " mov %w1, %w2\n" \
+ "3:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
- "3: mov %w0, %w5\n" \
- " b 2b\n" \
+ "4: mov %w0, %w5\n" \
+ " b 3b\n" \
" .popsection" \
" .pushsection __ex_table,\"a\"\n" \
" .align 3\n" \
- " .quad 0b, 3b\n" \
- " .quad 1b, 3b\n" \
+ " .quad 0b, 4b\n" \
+ " .quad 1b, 4b\n" \
" .popsection\n" \
ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, \
CONFIG_ARM64_PAN) \
diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c
index 816120ece6bc..78dfbd34b6bf 100644
--- a/arch/arm64/kernel/efi-stub.c
+++ b/arch/arm64/kernel/efi-stub.c
@@ -25,10 +25,20 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
unsigned long kernel_size, kernel_memsize = 0;
unsigned long nr_pages;
void *old_image_addr = (void *)*image_addr;
+ unsigned long preferred_offset;
+
+ /*
+ * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
+ * a 2 MB aligned base, which itself may be lower than dram_base, as
+ * long as the resulting offset equals or exceeds it.
+ */
+ preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
+ if (preferred_offset < dram_base)
+ preferred_offset += SZ_2M;
/* Relocate the image, if required. */
kernel_size = _edata - _text;
- if (*image_addr != (dram_base + TEXT_OFFSET)) {
+ if (*image_addr != preferred_offset) {
kernel_memsize = kernel_size + (_end - _edata);
/*
@@ -42,7 +52,7 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
* Mustang), we can still place the kernel at the address
* 'dram_base + TEXT_OFFSET'.
*/
- *image_addr = *reserve_addr = dram_base + TEXT_OFFSET;
+ *image_addr = *reserve_addr = preferred_offset;
nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
EFI_PAGE_SIZE;
status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 407991bf79f5..ccb6078ed9f2 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -48,11 +48,7 @@ int notrace unwind_frame(struct stackframe *frame)
frame->sp = fp + 0x10;
frame->fp = *(unsigned long *)(fp);
- /*
- * -4 here because we care about the PC at time of bl,
- * not where the return will go.
- */
- frame->pc = *(unsigned long *)(fp + 8) - 4;
+ frame->pc = *(unsigned long *)(fp + 8);
return 0;
}
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 8297d502217e..44ca4143b013 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -80,17 +80,21 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
if (ret == 0) {
/*
* We are resuming from reset with TTBR0_EL1 set to the
- * idmap to enable the MMU; restore the active_mm mappings in
- * TTBR0_EL1 unless the active_mm == &init_mm, in which case
- * the thread entered cpu_suspend with TTBR0_EL1 set to
- * reserved TTBR0 page tables and should be restored as such.
+ * idmap to enable the MMU; set the TTBR0 to the reserved
+ * page tables to prevent speculative TLB allocations, flush
+ * the local tlb and set the default tcr_el1.t0sz so that
+ * the TTBR0 address space set-up is properly restored.
+ * If the current active_mm != &init_mm we entered cpu_suspend
+ * with mappings in TTBR0 that must be restored, so we switch
+ * them back to complete the address space configuration
+ * restoration before returning.
*/
- if (mm == &init_mm)
- cpu_set_reserved_ttbr0();
- else
- cpu_switch_mm(mm->pgd, mm);
-
+ cpu_set_reserved_ttbr0();
flush_tlb_all();
+ cpu_set_default_tcr_t0sz();
+
+ if (mm != &init_mm)
+ cpu_switch_mm(mm->pgd, mm);
/*
* Restore per-cpu offset before any kernel
diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c
index 91146b416cdb..99b0a7984950 100644
--- a/arch/avr32/boards/atngw100/mrmt.c
+++ b/arch/avr32/boards/atngw100/mrmt.c
@@ -21,7 +21,6 @@
#include <linux/leds_pwm.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
-#include <linux/atmel_serial.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 8da5653bd895..e086f9e93728 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -57,7 +57,6 @@ config CRIS
select ARCH_WANT_IPC_PARSE_VERSION
select GENERIC_IRQ_SHOW
select GENERIC_IOMAP
- select GENERIC_CMOS_UPDATE
select MODULES_USE_ELF_RELA
select CLONE_BACKWARDS2
select OLD_SIGSUSPEND
diff --git a/arch/cris/arch-v10/kernel/head.S b/arch/cris/arch-v10/kernel/head.S
index 4a146e1749c9..a4877a421756 100644
--- a/arch/cris/arch-v10/kernel/head.S
+++ b/arch/cris/arch-v10/kernel/head.S
@@ -354,63 +354,6 @@ no_command_line:
blo 1b
nop
-#ifdef CONFIG_BLK_DEV_ETRAXIDE
- ;; disable ATA before enabling it in genconfig below
- moveq 0,$r0
- move.d $r0,[R_ATA_CTRL_DATA]
- move.d $r0,[R_ATA_TRANSFER_CNT]
- move.d $r0,[R_ATA_CONFIG]
-#if 0
- move.d R_PORT_G_DATA, $r1
- move.d $r0, [$r1]; assert ATA bus-reset
- nop
- nop
- nop
- nop
- nop
- nop
- move.d 0x08000000,$r0
- move.d $r0,[$r1]
-#endif
-#endif
-
-#ifdef CONFIG_JULIETTE
- ;; configure external DMA channel 0 before enabling it in genconfig
-
- moveq 0,$r0
- move.d $r0,[R_EXT_DMA_0_ADDR]
- ; cnt enable, word size, output, stop, size 0
- move.d IO_STATE (R_EXT_DMA_0_CMD, cnt, enable) \
- | IO_STATE (R_EXT_DMA_0_CMD, rqpol, ahigh) \
- | IO_STATE (R_EXT_DMA_0_CMD, apol, ahigh) \
- | IO_STATE (R_EXT_DMA_0_CMD, rq_ack, burst) \
- | IO_STATE (R_EXT_DMA_0_CMD, wid, word) \
- | IO_STATE (R_EXT_DMA_0_CMD, dir, output) \
- | IO_STATE (R_EXT_DMA_0_CMD, run, stop) \
- | IO_FIELD (R_EXT_DMA_0_CMD, trf_count, 0),$r0
- move.d $r0,[R_EXT_DMA_0_CMD]
-
- ;; reset dma4 and wait for completion
-
- moveq IO_STATE (R_DMA_CH4_CMD, cmd, reset),$r0
- move.b $r0,[R_DMA_CH4_CMD]
-1: move.b [R_DMA_CH4_CMD],$r0
- and.b IO_MASK (R_DMA_CH4_CMD, cmd),$r0
- cmp.b IO_STATE (R_DMA_CH4_CMD, cmd, reset),$r0
- beq 1b
- nop
-
- ;; reset dma5 and wait for completion
-
- moveq IO_STATE (R_DMA_CH5_CMD, cmd, reset),$r0
- move.b $r0,[R_DMA_CH5_CMD]
-1: move.b [R_DMA_CH5_CMD],$r0
- and.b IO_MASK (R_DMA_CH5_CMD, cmd),$r0
- cmp.b IO_STATE (R_DMA_CH5_CMD, cmd, reset),$r0
- beq 1b
- nop
-#endif
-
;; Etrax product HW genconfig setup
moveq 0,$r0
@@ -447,21 +390,6 @@ no_command_line:
| IO_STATE (R_GEN_CONFIG, dma9, usb),$r0
-#if defined(CONFIG_ETRAX_DEF_R_PORT_G0_DIR_OUT)
- or.d IO_STATE (R_GEN_CONFIG, g0dir, out),$r0
-#endif
-
-#if defined(CONFIG_ETRAX_DEF_R_PORT_G8_15_DIR_OUT)
- or.d IO_STATE (R_GEN_CONFIG, g8_15dir, out),$r0
-#endif
-#if defined(CONFIG_ETRAX_DEF_R_PORT_G16_23_DIR_OUT)
- or.d IO_STATE (R_GEN_CONFIG, g16_23dir, out),$r0
-#endif
-
-#if defined(CONFIG_ETRAX_DEF_R_PORT_G24_DIR_OUT)
- or.d IO_STATE (R_GEN_CONFIG, g24dir, out),$r0
-#endif
-
move.d $r0,[genconfig_shadow] ; init a shadow register of R_GEN_CONFIG
move.d $r0,[R_GEN_CONFIG]
@@ -500,19 +428,9 @@ no_command_line:
;; including their shadow registers
move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR,$r0
-#if defined(CONFIG_BLUETOOTH) && defined(CONFIG_BLUETOOTH_RESET_PA7)
- or.b IO_STATE (R_PORT_PA_DIR, dir7, output),$r0
-#endif
move.b $r0,[port_pa_dir_shadow]
move.b $r0,[R_PORT_PA_DIR]
move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA,$r0
-#if defined(CONFIG_BLUETOOTH) && defined(CONFIG_BLUETOOTH_RESET_PA7)
-#if defined(CONFIG_BLUETOOTH_RESET_ACTIVE_HIGH)
- and.b ~(1 << 7),$r0
-#else
- or.b (1 << 7),$r0
-#endif
-#endif
move.b $r0,[port_pa_data_shadow]
move.b $r0,[R_PORT_PA_DATA]
@@ -520,19 +438,9 @@ no_command_line:
move.b $r0,[port_pb_config_shadow]
move.b $r0,[R_PORT_PB_CONFIG]
move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR,$r0
-#if defined(CONFIG_BLUETOOTH) && defined(CONFIG_BLUETOOTH_RESET_PB5)
- or.b IO_STATE (R_PORT_PB_DIR, dir5, output),$r0
-#endif
move.b $r0,[port_pb_dir_shadow]
move.b $r0,[R_PORT_PB_DIR]
move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA,$r0
-#if defined(CONFIG_BLUETOOTH) && defined(CONFIG_BLUETOOTH_RESET_PB5)
-#if defined(CONFIG_BLUETOOTH_RESET_ACTIVE_HIGH)
- and.b ~(1 << 5),$r0
-#else
- or.b (1 << 5),$r0
-#endif
-#endif
move.b $r0,[port_pb_data_shadow]
move.b $r0,[R_PORT_PB_DATA]
@@ -541,20 +449,6 @@ no_command_line:
move.d $r0, [R_PORT_PB_I2C]
moveq 0,$r0
-#if defined(CONFIG_BLUETOOTH) && defined(CONFIG_BLUETOOTH_RESET_G10)
-#if defined(CONFIG_BLUETOOTH_RESET_ACTIVE_HIGH)
- and.d ~(1 << 10),$r0
-#else
- or.d (1 << 10),$r0
-#endif
-#endif
-#if defined(CONFIG_BLUETOOTH) && defined(CONFIG_BLUETOOTH_RESET_G11)
-#if defined(CONFIG_BLUETOOTH_RESET_ACTIVE_HIGH)
- and.d ~(1 << 11),$r0
-#else
- or.d (1 << 11),$r0
-#endif
-#endif
move.d $r0,[port_g_data_shadow]
move.d $r0,[R_PORT_G_DATA]
diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c
index 22d846bfc570..ed71ade93a73 100644
--- a/arch/cris/arch-v10/kernel/kgdb.c
+++ b/arch/cris/arch-v10/kernel/kgdb.c
@@ -275,7 +275,7 @@ static char remcomOutBuffer[BUFMAX];
/* Error and warning messages. */
enum error_type
{
- SUCCESS, E01, E02, E03, E04, E05, E06, E07
+ SUCCESS, E01, E02, E03, E04, E05, E06, E07, E08
};
static char *error_message[] =
{
@@ -286,7 +286,8 @@ static char *error_message[] =
"E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.",
"E05 Change register content - P - the register is not implemented..",
"E06 Change memory content - M - internal error.",
- "E07 Change register content - P - the register is not stored on the stack"
+ "E07 Change register content - P - the register is not stored on the stack",
+ "E08 Invalid parameter"
};
/********************************* Register image ****************************/
/* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's
@@ -351,7 +352,7 @@ char internal_stack[INTERNAL_STACK_SIZE];
breakpoint to be handled. A static breakpoint uses the content of register
BRP as it is whereas a dynamic breakpoint requires subtraction with 2
in order to execute the instruction. The first breakpoint is static. */
-static unsigned char is_dyn_brkp = 0;
+static unsigned char __used is_dyn_brkp;
/********************************* String library ****************************/
/* Single-step over library functions creates trap loops. */
@@ -413,18 +414,6 @@ gdb_cris_strtol (const char *s, char **endptr, int base)
}
/********************************** Packet I/O ******************************/
-/* Returns the integer equivalent of a hexadecimal character. */
-static int
-hex (char ch)
-{
- if ((ch >= 'a') && (ch <= 'f'))
- return (ch - 'a' + 10);
- if ((ch >= '0') && (ch <= '9'))
- return (ch - '0');
- if ((ch >= 'A') && (ch <= 'F'))
- return (ch - 'A' + 10);
- return (-1);
-}
/* Convert the memory, pointed to by mem into hexadecimal representation.
Put the result in buf, and return a pointer to the last character
@@ -455,22 +444,6 @@ mem2hex(char *buf, unsigned char *mem, int count)
return (buf);
}
-/* Convert the array, in hexadecimal representation, pointed to by buf into
- binary representation. Put the result in mem, and return a pointer to
- the character after the last byte written. */
-static unsigned char*
-hex2mem (unsigned char *mem, char *buf, int count)
-{
- int i;
- unsigned char ch;
- for (i = 0; i < count; i++) {
- ch = hex (*buf++) << 4;
- ch = ch + hex (*buf++);
- *mem++ = ch;
- }
- return (mem);
-}
-
/* Put the content of the array, in binary representation, pointed to by buf
into memory pointed to by mem, and return a pointer to the character after
the last byte written.
@@ -524,8 +497,8 @@ getpacket (char *buffer)
buffer[count] = '\0';
if (ch == '#') {
- xmitcsum = hex (getDebugChar ()) << 4;
- xmitcsum += hex (getDebugChar ());
+ xmitcsum = hex_to_bin(getDebugChar()) << 4;
+ xmitcsum += hex_to_bin(getDebugChar());
if (checksum != xmitcsum) {
/* Wrong checksum */
putDebugChar ('-');
@@ -599,7 +572,7 @@ putDebugString (const unsigned char *str, int length)
/********************************* Register image ****************************/
/* Write a value to a specified register in the register image of the current
- thread. Returns status code SUCCESS, E02 or E05. */
+ thread. Returns status code SUCCESS, E02, E05 or E08. */
static int
write_register (int regno, char *val)
{
@@ -608,8 +581,9 @@ write_register (int regno, char *val)
if (regno >= R0 && regno <= PC) {
/* 32-bit register with simple offset. */
- hex2mem ((unsigned char *)current_reg + regno * sizeof(unsigned int),
- val, sizeof(unsigned int));
+ if (hex2bin((unsigned char *)current_reg + regno * sizeof(unsigned int),
+ val, sizeof(unsigned int)))
+ status = E08;
}
else if (regno == P0 || regno == VR || regno == P4 || regno == P8) {
/* Do not support read-only registers. */
@@ -618,13 +592,15 @@ write_register (int regno, char *val)
else if (regno == CCR) {
/* 16 bit register with complex offset. (P4 is read-only, P6 is not implemented,
and P7 (MOF) is 32 bits in ETRAX 100LX. */
- hex2mem ((unsigned char *)&(current_reg->ccr) + (regno-CCR) * sizeof(unsigned short),
- val, sizeof(unsigned short));
+ if (hex2bin((unsigned char *)&(current_reg->ccr) + (regno-CCR) * sizeof(unsigned short),
+ val, sizeof(unsigned short)))
+ status = E08;
}
else if (regno >= MOF && regno <= USP) {
/* 32 bit register with complex offset. (P8 has been taken care of.) */
- hex2mem ((unsigned char *)&(current_reg->ibr) + (regno-IBR) * sizeof(unsigned int),
- val, sizeof(unsigned int));
+ if (hex2bin((unsigned char *)&(current_reg->ibr) + (regno-IBR) * sizeof(unsigned int),
+ val, sizeof(unsigned int)))
+ status = E08;
}
else {
/* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */
@@ -759,9 +735,11 @@ handle_exception (int sigval)
/* Write registers. GXX..XX
Each byte of register data is described by two hex digits.
Success: OK
- Failure: void. */
- hex2mem((char *)&cris_reg, &remcomInBuffer[1], sizeof(registers));
- gdb_cris_strcpy (remcomOutBuffer, "OK");
+ Failure: E08. */
+ if (hex2bin((char *)&cris_reg, &remcomInBuffer[1], sizeof(registers)))
+ gdb_cris_strcpy (remcomOutBuffer, error_message[E08]);
+ else
+ gdb_cris_strcpy (remcomOutBuffer, "OK");
break;
case 'P':
@@ -771,7 +749,7 @@ handle_exception (int sigval)
for each byte in the register (target byte order). P1f=11223344 means
set register 31 to 44332211.
Success: OK
- Failure: E02, E05 */
+ Failure: E02, E05, E08 */
{
char *suffix;
int regno = gdb_cris_strtol (&remcomInBuffer[1], &suffix, 16);
@@ -791,6 +769,10 @@ handle_exception (int sigval)
/* Do not support non-existing registers on the stack. */
gdb_cris_strcpy (remcomOutBuffer, error_message[E07]);
break;
+ case E08:
+ /* Invalid parameter. */
+ gdb_cris_strcpy (remcomOutBuffer, error_message[E08]);
+ break;
default:
/* Valid register number. */
gdb_cris_strcpy (remcomOutBuffer, "OK");
@@ -826,7 +808,7 @@ handle_exception (int sigval)
AA..AA is the start address, LLLL is the number of bytes, and
XX..XX is the hexadecimal data.
Success: OK
- Failure: void. */
+ Failure: E08. */
{
char *lenptr;
char *dataptr;
@@ -835,14 +817,15 @@ handle_exception (int sigval)
int length = gdb_cris_strtol(lenptr+1, &dataptr, 16);
if (*lenptr == ',' && *dataptr == ':') {
if (remcomInBuffer[0] == 'M') {
- hex2mem(addr, dataptr + 1, length);
- }
- else /* X */ {
+ if (hex2bin(addr, dataptr + 1, length))
+ gdb_cris_strcpy (remcomOutBuffer, error_message[E08]);
+ else
+ gdb_cris_strcpy (remcomOutBuffer, "OK");
+ } else /* X */ {
bin2mem(addr, dataptr + 1, length);
+ gdb_cris_strcpy (remcomOutBuffer, "OK");
}
- gdb_cris_strcpy (remcomOutBuffer, "OK");
- }
- else {
+ } else {
gdb_cris_strcpy (remcomOutBuffer, error_message[E06]);
}
}
@@ -970,7 +953,7 @@ asm ("\n"
" move $ibr,[cris_reg+0x4E] ; P9,\n"
" move $irp,[cris_reg+0x52] ; P10,\n"
" move $srp,[cris_reg+0x56] ; P11,\n"
-" move $dtp0,[cris_reg+0x5A] ; P12, register BAR, assembler might not know BAR\n"
+" move $bar,[cris_reg+0x5A] ; P12,\n"
" ; P13, register DCCR already saved\n"
";; Due to the old assembler-versions BRP might not be recognized\n"
" .word 0xE670 ; move brp,r0\n"
@@ -1063,7 +1046,7 @@ asm ("\n"
" move $ibr,[cris_reg+0x4E] ; P9,\n"
" move $irp,[cris_reg+0x52] ; P10,\n"
" move $srp,[cris_reg+0x56] ; P11,\n"
-" move $dtp0,[cris_reg+0x5A] ; P12, register BAR, assembler might not know BAR\n"
+" move $bar,[cris_reg+0x5A] ; P12,\n"
" ; P13, register DCCR already saved\n"
";; Due to the old assembler-versions BRP might not be recognized\n"
" .word 0xE670 ; move brp,r0\n"
diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c
index e7f8066105aa..85e3f1b1f3ac 100644
--- a/arch/cris/arch-v10/mm/init.c
+++ b/arch/cris/arch-v10/mm/init.c
@@ -68,14 +68,10 @@ paging_init(void)
*R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg ) | /* bootrom */
IO_STATE(R_MMU_KSEG, seg_e, page ) |
- IO_STATE(R_MMU_KSEG, seg_d, page ) |
- IO_STATE(R_MMU_KSEG, seg_c, page ) |
+ IO_STATE(R_MMU_KSEG, seg_d, page ) |
+ IO_STATE(R_MMU_KSEG, seg_c, page ) |
IO_STATE(R_MMU_KSEG, seg_b, seg ) | /* kernel reg area */
-#ifdef CONFIG_JULIETTE
- IO_STATE(R_MMU_KSEG, seg_a, seg ) | /* ARTPEC etc. */
-#else
IO_STATE(R_MMU_KSEG, seg_a, page ) |
-#endif
IO_STATE(R_MMU_KSEG, seg_9, seg ) | /* LED's on some boards */
IO_STATE(R_MMU_KSEG, seg_8, seg ) | /* CSE0/1, flash and I/O */
IO_STATE(R_MMU_KSEG, seg_7, page ) | /* kernel vmalloc area */
@@ -92,14 +88,10 @@ paging_init(void)
IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
IO_FIELD(R_MMU_KBASE_HI, base_c, 0x0 ) |
IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
-#ifdef CONFIG_JULIETTE
- IO_FIELD(R_MMU_KBASE_HI, base_a, 0xa ) |
-#else
IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) |
-#endif
IO_FIELD(R_MMU_KBASE_HI, base_9, 0x9 ) |
IO_FIELD(R_MMU_KBASE_HI, base_8, 0x8 ) );
-
+
*R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
IO_FIELD(R_MMU_KBASE_LO, base_6, 0x4 ) |
IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
diff --git a/arch/cris/arch-v32/Kconfig b/arch/cris/arch-v32/Kconfig
index 21bbd93be34f..17dbe03af5f4 100644
--- a/arch/cris/arch-v32/Kconfig
+++ b/arch/cris/arch-v32/Kconfig
@@ -11,95 +11,6 @@ config ETRAX_DRAM_VIRTUAL_BASE
default "c0000000"
choice
- prompt "Nbr of Ethernet LED groups"
- depends on ETRAX_ARCH_V32
- default ETRAX_NBR_LED_GRP_ONE
- help
- Select how many Ethernet LED groups that can be used. Usually one per Ethernet
- interface is a good choice.
-
-config ETRAX_NBR_LED_GRP_ZERO
- bool "Use zero LED groups"
- help
- Select this if you do not want any Ethernet LEDs.
-
-config ETRAX_NBR_LED_GRP_ONE
- bool "Use one LED group"
- help
- Select this if you want one Ethernet LED group. This LED group
- can be used for one or more Ethernet interfaces. However, it is
- recommended that each Ethernet interface use a dedicated LED group.
-
-config ETRAX_NBR_LED_GRP_TWO
- bool "Use two LED groups"
- help
- Select this if you want two Ethernet LED groups. This is the
- best choice if you have more than one Ethernet interface and
- would like to have separate LEDs for the interfaces.
-
-endchoice
-
-config ETRAX_LED_G_NET0
- string "Ethernet LED group 0 green LED bit"
- depends on ETRAX_ARCH_V32 && (ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO)
- default "PA3"
- help
- Bit to use for the green LED in Ethernet LED group 0.
-
-config ETRAX_LED_R_NET0
- string "Ethernet LED group 0 red LED bit"
- depends on ETRAX_ARCH_V32 && (ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO)
- default "PA4"
- help
- Bit to use for the red LED in Ethernet LED group 0.
-
-config ETRAX_LED_G_NET1
- string "Ethernet group 1 green LED bit"
- depends on ETRAX_ARCH_V32 && ETRAX_NBR_LED_GRP_TWO
- default ""
- help
- Bit to use for the green LED in Ethernet LED group 1.
-
-config ETRAX_LED_R_NET1
- string "Ethernet group 1 red LED bit"
- depends on ETRAX_ARCH_V32 && ETRAX_NBR_LED_GRP_TWO
- default ""
- help
- Bit to use for the red LED in Ethernet LED group 1.
-
-config ETRAX_V32_LED2G
- string "Second green LED bit"
- depends on ETRAX_ARCH_V32
- default "PA5"
- help
- Bit to use for the first green LED (status LED).
- Most Axis products use bit A5 here.
-
-config ETRAX_V32_LED2R
- string "Second red LED bit"
- depends on ETRAX_ARCH_V32
- default "PA6"
- help
- Bit to use for the first red LED (network LED).
- Most Axis products use bit A6 here.
-
-config ETRAX_V32_LED3G
- string "Third green LED bit"
- depends on ETRAX_ARCH_V32
- default "PA7"
- help
- Bit to use for the first green LED (drive/power LED).
- Most Axis products use bit A7 here.
-
-config ETRAX_V32_LED3R
- string "Third red LED bit"
- depends on ETRAX_ARCH_V32
- default "PA7"
- help
- Bit to use for the first red LED (drive/power LED).
- Most Axis products use bit A7 here.
-
-choice
prompt "Kernel GDB port"
depends on ETRAX_KGDB
default ETRAX_KGDB_PORT0
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index e6c523cc40bc..2735eb7671a5 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -149,173 +149,6 @@ config ETRAX_NANDBOOT
Say Y if your boot code, kernel and root file system is in
NAND flash. Say N if they are in NOR flash.
-config ETRAX_I2C
- bool "I2C driver"
- depends on ETRAX_ARCH_V32
- help
- This option enables the I2C driver used by e.g. the RTC driver.
-
-config ETRAX_V32_I2C_DATA_PORT
- string "I2C data pin"
- depends on ETRAX_I2C
- help
- The pin to use for I2C data.
-
-config ETRAX_V32_I2C_CLK_PORT
- string "I2C clock pin"
- depends on ETRAX_I2C
- help
- The pin to use for I2C clock.
-
-config ETRAX_GPIO
- bool "GPIO support"
- depends on ETRAX_ARCH_V32
- ---help---
- Enables the ETRAX general port device (major 120, minors 0-4).
- You can use this driver to access the general port bits. It supports
- these ioctl's:
- #include <linux/etraxgpio.h>
- fd = open("/dev/gpioa", O_RDWR); // or /dev/gpiob
- ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), bits_to_set);
- ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), bits_to_clear);
- err = ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_READ_INBITS), &val);
- Remember that you need to setup the port directions appropriately in
- the General configuration.
-
-config ETRAX_VIRTUAL_GPIO
- bool "Virtual GPIO support"
- depends on ETRAX_GPIO
- help
- Enables the virtual Etrax general port device (major 120, minor 6).
- It uses an I/O expander for the I2C-bus.
-
-config ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN
- int "Virtual GPIO interrupt pin on PA pin"
- range 0 7
- depends on ETRAX_VIRTUAL_GPIO
- help
- The pin to use on PA for virtual gpio interrupt.
-
-config ETRAX_PA_CHANGEABLE_DIR
- hex "PA user changeable dir mask"
- depends on ETRAX_GPIO
- default "0x00" if ETRAXFS
- default "0x00000000" if !ETRAXFS
- help
- This is a bitmask with information of what bits in PA that a
- user can change direction on using ioctl's.
- Bit set = changeable.
- You probably want 0 here, but it depends on your hardware.
-
-config ETRAX_PA_CHANGEABLE_BITS
- hex "PA user changeable bits mask"
- depends on ETRAX_GPIO
- default "0x00" if ETRAXFS
- default "0x00000000" if !ETRAXFS
- help
- This is a bitmask with information of what bits in PA
- that a user can change the value on using ioctl's.
- Bit set = changeable.
-
-config ETRAX_PB_CHANGEABLE_DIR
- hex "PB user changeable dir mask"
- depends on ETRAX_GPIO
- default "0x00000" if ETRAXFS
- default "0x00000000" if !ETRAXFS
- help
- This is a bitmask with information of what bits in PB
- that a user can change direction on using ioctl's.
- Bit set = changeable.
- You probably want 0 here, but it depends on your hardware.
-
-config ETRAX_PB_CHANGEABLE_BITS
- hex "PB user changeable bits mask"
- depends on ETRAX_GPIO
- default "0x00000" if ETRAXFS
- default "0x00000000" if !ETRAXFS
- help
- This is a bitmask with information of what bits in PB
- that a user can change the value on using ioctl's.
- Bit set = changeable.
-
-config ETRAX_PC_CHANGEABLE_DIR
- hex "PC user changeable dir mask"
- depends on ETRAX_GPIO
- default "0x00000" if ETRAXFS
- default "0x00000000" if !ETRAXFS
- help
- This is a bitmask with information of what bits in PC
- that a user can change direction on using ioctl's.
- Bit set = changeable.
- You probably want 0 here, but it depends on your hardware.
-
-config ETRAX_PC_CHANGEABLE_BITS
- hex "PC user changeable bits mask"
- depends on ETRAX_GPIO
- default "0x00000" if ETRAXFS
- default "0x00000000" if !ETRAXFS
- help
- This is a bitmask with information of what bits in PC
- that a user can change the value on using ioctl's.
- Bit set = changeable.
-
-config ETRAX_PD_CHANGEABLE_DIR
- hex "PD user changeable dir mask"
- depends on ETRAX_GPIO && ETRAXFS
- default "0x00000"
- help
- This is a bitmask with information of what bits in PD
- that a user can change direction on using ioctl's.
- Bit set = changeable.
- You probably want 0x00000 here, but it depends on your hardware.
-
-config ETRAX_PD_CHANGEABLE_BITS
- hex "PD user changeable bits mask"
- depends on ETRAX_GPIO && ETRAXFS
- default "0x00000"
- help
- This is a bitmask (18 bits) with information of what bits in PD
- that a user can change the value on using ioctl's.
- Bit set = changeable.
-
-config ETRAX_PE_CHANGEABLE_DIR
- hex "PE user changeable dir mask"
- depends on ETRAX_GPIO && ETRAXFS
- default "0x00000"
- help
- This is a bitmask (18 bits) with information of what bits in PE
- that a user can change direction on using ioctl's.
- Bit set = changeable.
- You probably want 0x00000 here, but it depends on your hardware.
-
-config ETRAX_PE_CHANGEABLE_BITS
- hex "PE user changeable bits mask"
- depends on ETRAX_GPIO && ETRAXFS
- default "0x00000"
- help
- This is a bitmask (18 bits) with information of what bits in PE
- that a user can change the value on using ioctl's.
- Bit set = changeable.
-
-config ETRAX_PV_CHANGEABLE_DIR
- hex "PV user changeable dir mask"
- depends on ETRAX_VIRTUAL_GPIO
- default "0x0000"
- help
- This is a bitmask (16 bits) with information of what bits in PV
- that a user can change direction on using ioctl's.
- Bit set = changeable.
- You probably want 0x0000 here, but it depends on your hardware.
-
-config ETRAX_PV_CHANGEABLE_BITS
- hex "PV user changeable bits mask"
- depends on ETRAX_VIRTUAL_GPIO
- default "0x0000"
- help
- This is a bitmask (16 bits) with information of what bits in PV
- that a user can change the value on using ioctl's.
- Bit set = changeable.
-
config ETRAX_CARDBUS
bool "Cardbus support"
depends on ETRAX_ARCH_V32
diff --git a/arch/cris/arch-v32/drivers/Makefile b/arch/cris/arch-v32/drivers/Makefile
index 15fbfefced2c..b5a75fdce77b 100644
--- a/arch/cris/arch-v32/drivers/Makefile
+++ b/arch/cris/arch-v32/drivers/Makefile
@@ -7,6 +7,5 @@ obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
obj-$(CONFIG_ETRAXFS) += mach-fs/
obj-$(CONFIG_CRIS_MACH_ARTPEC3) += mach-a3/
obj-$(CONFIG_ETRAX_IOP_FW_LOAD) += iop_fw_load.o
-obj-$(CONFIG_ETRAX_I2C) += i2c.o
obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o
obj-$(CONFIG_PCI) += pci/
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index 5387424683cc..c6309a182f46 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -361,7 +361,7 @@ static int __init init_axis_flash(void)
#if 0 /* Dump flash memory so we can see what is going on */
if (main_mtd) {
- int sectoraddr, i;
+ int sectoraddr;
for (sectoraddr = 0; sectoraddr < 2*65536+4096;
sectoraddr += PAGESIZE) {
main_mtd->read(main_mtd, sectoraddr, PAGESIZE, &len,
@@ -369,21 +369,7 @@ static int __init init_axis_flash(void)
printk(KERN_INFO
"Sector at %d (length %d):\n",
sectoraddr, len);
- for (i = 0; i < PAGESIZE; i += 16) {
- printk(KERN_INFO
- "%02x %02x %02x %02x "
- "%02x %02x %02x %02x "
- "%02x %02x %02x %02x "
- "%02x %02x %02x %02x\n",
- page[i] & 255, page[i+1] & 255,
- page[i+2] & 255, page[i+3] & 255,
- page[i+4] & 255, page[i+5] & 255,
- page[i+6] & 255, page[i+7] & 255,
- page[i+8] & 255, page[i+9] & 255,
- page[i+10] & 255, page[i+11] & 255,
- page[i+12] & 255, page[i+13] & 255,
- page[i+14] & 255, page[i+15] & 255);
- }
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, page, PAGESIZE, false);
}
}
#endif
@@ -417,25 +403,11 @@ static int __init init_axis_flash(void)
#if 0 /* Dump partition table so we can see what is going on */
printk(KERN_INFO
- "axisflashmap: flash read %d bytes at 0x%08x, data: "
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- len, CONFIG_ETRAX_PTABLE_SECTOR,
- page[0] & 255, page[1] & 255,
- page[2] & 255, page[3] & 255,
- page[4] & 255, page[5] & 255,
- page[6] & 255, page[7] & 255);
+ "axisflashmap: flash read %d bytes at 0x%08x, data: %8ph\n",
+ len, CONFIG_ETRAX_PTABLE_SECTOR, page);
printk(KERN_INFO
- "axisflashmap: partition table offset %d, data: "
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- PARTITION_TABLE_OFFSET,
- page[PARTITION_TABLE_OFFSET+0] & 255,
- page[PARTITION_TABLE_OFFSET+1] & 255,
- page[PARTITION_TABLE_OFFSET+2] & 255,
- page[PARTITION_TABLE_OFFSET+3] & 255,
- page[PARTITION_TABLE_OFFSET+4] & 255,
- page[PARTITION_TABLE_OFFSET+5] & 255,
- page[PARTITION_TABLE_OFFSET+6] & 255,
- page[PARTITION_TABLE_OFFSET+7] & 255);
+ "axisflashmap: partition table offset %d, data: %8ph\n",
+ PARTITION_TABLE_OFFSET, page + PARTITION_TABLE_OFFSET);
#endif
}
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
deleted file mode 100644
index 3b2c82ce8147..000000000000
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/*!***************************************************************************
-*!
-*! FILE NAME : i2c.c
-*!
-*! DESCRIPTION: implements an interface for IIC/I2C, both directly from other
-*! kernel modules (i2c_writereg/readreg) and from userspace using
-*! ioctl()'s
-*!
-*! Nov 30 1998 Torbjorn Eliasson Initial version.
-*! Bjorn Wesen Elinux kernel version.
-*! Jan 14 2000 Johan Adolfsson Fixed PB shadow register stuff -
-*! don't use PB_I2C if DS1302 uses same bits,
-*! use PB.
-*| June 23 2003 Pieter Grimmerink Added 'i2c_sendnack'. i2c_readreg now
-*| generates nack on last received byte,
-*| instead of ack.
-*| i2c_getack changed data level while clock
-*| was high, causing DS75 to see a stop condition
-*!
-*! ---------------------------------------------------------------------------
-*!
-*! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN
-*!
-*!***************************************************************************/
-
-/****************** INCLUDE FILES SECTION ***********************************/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-
-#include <asm/etraxi2c.h>
-
-#include <asm/io.h>
-#include <asm/delay.h>
-
-#include "i2c.h"
-
-/****************** I2C DEFINITION SECTION *************************/
-
-#define D(x)
-
-#define I2C_MAJOR 123 /* LOCAL/EXPERIMENTAL */
-static DEFINE_MUTEX(i2c_mutex);
-static const char i2c_name[] = "i2c";
-
-#define CLOCK_LOW_TIME 8
-#define CLOCK_HIGH_TIME 8
-#define START_CONDITION_HOLD_TIME 8
-#define STOP_CONDITION_HOLD_TIME 8
-#define ENABLE_OUTPUT 0x01
-#define ENABLE_INPUT 0x00
-#define I2C_CLOCK_HIGH 1
-#define I2C_CLOCK_LOW 0
-#define I2C_DATA_HIGH 1
-#define I2C_DATA_LOW 0
-
-#define i2c_enable()
-#define i2c_disable()
-
-/* enable or disable output-enable, to select output or input on the i2c bus */
-
-#define i2c_dir_out() crisv32_io_set_dir(&cris_i2c_data, crisv32_io_dir_out)
-#define i2c_dir_in() crisv32_io_set_dir(&cris_i2c_data, crisv32_io_dir_in)
-
-/* control the i2c clock and data signals */
-
-#define i2c_clk(x) crisv32_io_set(&cris_i2c_clk, x)
-#define i2c_data(x) crisv32_io_set(&cris_i2c_data, x)
-
-/* read a bit from the i2c interface */
-
-#define i2c_getbit() crisv32_io_rd(&cris_i2c_data)
-
-#define i2c_delay(usecs) udelay(usecs)
-
-static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */
-
-/****************** VARIABLE SECTION ************************************/
-
-static struct crisv32_iopin cris_i2c_clk;
-static struct crisv32_iopin cris_i2c_data;
-
-/****************** FUNCTION DEFINITION SECTION *************************/
-
-
-/* generate i2c start condition */
-
-void
-i2c_start(void)
-{
- /*
- * SCL=1 SDA=1
- */
- i2c_dir_out();
- i2c_delay(CLOCK_HIGH_TIME/6);
- i2c_data(I2C_DATA_HIGH);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME);
- /*
- * SCL=1 SDA=0
- */
- i2c_data(I2C_DATA_LOW);
- i2c_delay(START_CONDITION_HOLD_TIME);
- /*
- * SCL=0 SDA=0
- */
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME);
-}
-
-/* generate i2c stop condition */
-
-void
-i2c_stop(void)
-{
- i2c_dir_out();
-
- /*
- * SCL=0 SDA=0
- */
- i2c_clk(I2C_CLOCK_LOW);
- i2c_data(I2C_DATA_LOW);
- i2c_delay(CLOCK_LOW_TIME*2);
- /*
- * SCL=1 SDA=0
- */
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME*2);
- /*
- * SCL=1 SDA=1
- */
- i2c_data(I2C_DATA_HIGH);
- i2c_delay(STOP_CONDITION_HOLD_TIME);
-
- i2c_dir_in();
-}
-
-/* write a byte to the i2c interface */
-
-void
-i2c_outbyte(unsigned char x)
-{
- int i;
-
- i2c_dir_out();
-
- for (i = 0; i < 8; i++) {
- if (x & 0x80) {
- i2c_data(I2C_DATA_HIGH);
- } else {
- i2c_data(I2C_DATA_LOW);
- }
-
- i2c_delay(CLOCK_LOW_TIME/2);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME);
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME/2);
- x <<= 1;
- }
- i2c_data(I2C_DATA_LOW);
- i2c_delay(CLOCK_LOW_TIME/2);
-
- /*
- * enable input
- */
- i2c_dir_in();
-}
-
-/* read a byte from the i2c interface */
-
-unsigned char
-i2c_inbyte(void)
-{
- unsigned char aBitByte = 0;
- int i;
-
- /* Switch off I2C to get bit */
- i2c_disable();
- i2c_dir_in();
- i2c_delay(CLOCK_HIGH_TIME/2);
-
- /* Get bit */
- aBitByte |= i2c_getbit();
-
- /* Enable I2C */
- i2c_enable();
- i2c_delay(CLOCK_LOW_TIME/2);
-
- for (i = 1; i < 8; i++) {
- aBitByte <<= 1;
- /* Clock pulse */
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME);
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME);
-
- /* Switch off I2C to get bit */
- i2c_disable();
- i2c_dir_in();
- i2c_delay(CLOCK_HIGH_TIME/2);
-
- /* Get bit */
- aBitByte |= i2c_getbit();
-
- /* Enable I2C */
- i2c_enable();
- i2c_delay(CLOCK_LOW_TIME/2);
- }
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME);
-
- /*
- * we leave the clock low, getbyte is usually followed
- * by sendack/nack, they assume the clock to be low
- */
- i2c_clk(I2C_CLOCK_LOW);
- return aBitByte;
-}
-
-/*#---------------------------------------------------------------------------
-*#
-*# FUNCTION NAME: i2c_getack
-*#
-*# DESCRIPTION : checks if ack was received from ic2
-*#
-*#--------------------------------------------------------------------------*/
-
-int
-i2c_getack(void)
-{
- int ack = 1;
- /*
- * enable output
- */
- i2c_dir_out();
- /*
- * Release data bus by setting
- * data high
- */
- i2c_data(I2C_DATA_HIGH);
- /*
- * enable input
- */
- i2c_dir_in();
- i2c_delay(CLOCK_HIGH_TIME/4);
- /*
- * generate ACK clock pulse
- */
- i2c_clk(I2C_CLOCK_HIGH);
-#if 0
- /*
- * Use PORT PB instead of I2C
- * for input. (I2C not working)
- */
- i2c_clk(1);
- i2c_data(1);
- /*
- * switch off I2C
- */
- i2c_data(1);
- i2c_disable();
- i2c_dir_in();
-#endif
-
- /*
- * now wait for ack
- */
- i2c_delay(CLOCK_HIGH_TIME/2);
- /*
- * check for ack
- */
- if (i2c_getbit())
- ack = 0;
- i2c_delay(CLOCK_HIGH_TIME/2);
- if (!ack) {
- if (!i2c_getbit()) /* receiver pulld SDA low */
- ack = 1;
- i2c_delay(CLOCK_HIGH_TIME/2);
- }
-
- /*
- * our clock is high now, make sure data is low
- * before we enable our output. If we keep data high
- * and enable output, we would generate a stop condition.
- */
-#if 0
- i2c_data(I2C_DATA_LOW);
-
- /*
- * end clock pulse
- */
- i2c_enable();
- i2c_dir_out();
-#endif
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_HIGH_TIME/4);
- /*
- * enable output
- */
- i2c_dir_out();
- /*
- * remove ACK clock pulse
- */
- i2c_data(I2C_DATA_HIGH);
- i2c_delay(CLOCK_LOW_TIME/2);
- return ack;
-}
-
-/*#---------------------------------------------------------------------------
-*#
-*# FUNCTION NAME: I2C::sendAck
-*#
-*# DESCRIPTION : Send ACK on received data
-*#
-*#--------------------------------------------------------------------------*/
-void
-i2c_sendack(void)
-{
- /*
- * enable output
- */
- i2c_delay(CLOCK_LOW_TIME);
- i2c_dir_out();
- /*
- * set ack pulse high
- */
- i2c_data(I2C_DATA_LOW);
- /*
- * generate clock pulse
- */
- i2c_delay(CLOCK_HIGH_TIME/6);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME);
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME/6);
- /*
- * reset data out
- */
- i2c_data(I2C_DATA_HIGH);
- i2c_delay(CLOCK_LOW_TIME);
-
- i2c_dir_in();
-}
-
-/*#---------------------------------------------------------------------------
-*#
-*# FUNCTION NAME: i2c_sendnack
-*#
-*# DESCRIPTION : Sends NACK on received data
-*#
-*#--------------------------------------------------------------------------*/
-void
-i2c_sendnack(void)
-{
- /*
- * enable output
- */
- i2c_delay(CLOCK_LOW_TIME);
- i2c_dir_out();
- /*
- * set data high
- */
- i2c_data(I2C_DATA_HIGH);
- /*
- * generate clock pulse
- */
- i2c_delay(CLOCK_HIGH_TIME/6);
- i2c_clk(I2C_CLOCK_HIGH);
- i2c_delay(CLOCK_HIGH_TIME);
- i2c_clk(I2C_CLOCK_LOW);
- i2c_delay(CLOCK_LOW_TIME);
-
- i2c_dir_in();
-}
-
-/*#---------------------------------------------------------------------------
-*#
-*# FUNCTION NAME: i2c_write
-*#
-*# DESCRIPTION : Writes a value to an I2C device
-*#
-*#--------------------------------------------------------------------------*/
-int
-i2c_write(unsigned char theSlave, void *data, size_t nbytes)
-{
- int error, cntr = 3;
- unsigned char bytes_wrote = 0;
- unsigned char value;
- unsigned long flags;
-
- spin_lock_irqsave(&i2c_lock, flags);
-
- do {
- error = 0;
-
- i2c_start();
- /*
- * send slave address
- */
- i2c_outbyte((theSlave & 0xfe));
- /*
- * wait for ack
- */
- if (!i2c_getack())
- error = 1;
- /*
- * send data
- */
- for (bytes_wrote = 0; bytes_wrote < nbytes; bytes_wrote++) {
- memcpy(&value, data + bytes_wrote, sizeof value);
- i2c_outbyte(value);
- /*
- * now it's time to wait for ack
- */
- if (!i2c_getack())
- error |= 4;
- }
- /*
- * end byte stream
- */
- i2c_stop();
-
- } while (error && cntr--);
-
- i2c_delay(CLOCK_LOW_TIME);
-
- spin_unlock_irqrestore(&i2c_lock, flags);
-
- return -error;
-}
-
-/*#---------------------------------------------------------------------------
-*#
-*# FUNCTION NAME: i2c_read
-*#
-*# DESCRIPTION : Reads a value from an I2C device
-*#
-*#--------------------------------------------------------------------------*/
-int
-i2c_read(unsigned char theSlave, void *data, size_t nbytes)
-{
- unsigned char b = 0;
- unsigned char bytes_read = 0;
- int error, cntr = 3;
- unsigned long flags;
-
- spin_lock_irqsave(&i2c_lock, flags);
-
- do {
- error = 0;
- memset(data, 0, nbytes);
- /*
- * generate start condition
- */
- i2c_start();
- /*
- * send slave address
- */
- i2c_outbyte((theSlave | 0x01));
- /*
- * wait for ack
- */
- if (!i2c_getack())
- error = 1;
- /*
- * fetch data
- */
- for (bytes_read = 0; bytes_read < nbytes; bytes_read++) {
- b = i2c_inbyte();
- memcpy(data + bytes_read, &b, sizeof b);
-
- if (bytes_read < (nbytes - 1))
- i2c_sendack();
- }
- /*
- * last received byte needs to be nacked
- * instead of acked
- */
- i2c_sendnack();
- /*
- * end sequence
- */
- i2c_stop();
- } while (error && cntr--);
-
- spin_unlock_irqrestore(&i2c_lock, flags);
-
- return -error;
-}
-
-/*#---------------------------------------------------------------------------
-*#
-*# FUNCTION NAME: i2c_writereg
-*#
-*# DESCRIPTION : Writes a value to an I2C device
-*#
-*#--------------------------------------------------------------------------*/
-int
-i2c_writereg(unsigned char theSlave, unsigned char theReg,
- unsigned char theValue)
-{
- int error, cntr = 3;
- unsigned long flags;
-
- spin_lock_irqsave(&i2c_lock, flags);
-
- do {
- error = 0;
-
- i2c_start();
- /*
- * send slave address
- */
- i2c_outbyte((theSlave & 0xfe));
- /*
- * wait for ack
- */
- if(!i2c_getack())
- error = 1;
- /*
- * now select register
- */
- i2c_dir_out();
- i2c_outbyte(theReg);
- /*
- * now it's time to wait for ack
- */
- if(!i2c_getack())
- error |= 2;
- /*
- * send register register data
- */
- i2c_outbyte(theValue);
- /*
- * now it's time to wait for ack
- */
- if(!i2c_getack())
- error |= 4;
- /*
- * end byte stream
- */
- i2c_stop();
- } while(error && cntr--);
-
- i2c_delay(CLOCK_LOW_TIME);
-
- spin_unlock_irqrestore(&i2c_lock, flags);
-
- return -error;
-}
-
-/*#---------------------------------------------------------------------------
-*#
-*# FUNCTION NAME: i2c_readreg
-*#
-*# DESCRIPTION : Reads a value from the decoder registers.
-*#
-*#--------------------------------------------------------------------------*/
-unsigned char
-i2c_readreg(unsigned char theSlave, unsigned char theReg)
-{
- unsigned char b = 0;
- int error, cntr = 3;
- unsigned long flags;
-
- spin_lock_irqsave(&i2c_lock, flags);
-
- do {
- error = 0;
- /*
- * generate start condition
- */
- i2c_start();
-
- /*
- * send slave address
- */
- i2c_outbyte((theSlave & 0xfe));
- /*
- * wait for ack
- */
- if(!i2c_getack())
- error = 1;
- /*
- * now select register
- */
- i2c_dir_out();
- i2c_outbyte(theReg);
- /*
- * now it's time to wait for ack
- */
- if(!i2c_getack())
- error |= 2;
- /*
- * repeat start condition
- */
- i2c_delay(CLOCK_LOW_TIME);
- i2c_start();
- /*
- * send slave address
- */
- i2c_outbyte(theSlave | 0x01);
- /*
- * wait for ack
- */
- if(!i2c_getack())
- error |= 4;
- /*
- * fetch register
- */
- b = i2c_inbyte();
- /*
- * last received byte needs to be nacked
- * instead of acked
- */
- i2c_sendnack();
- /*
- * end sequence
- */
- i2c_stop();
-
- } while(error && cntr--);
-
- spin_unlock_irqrestore(&i2c_lock, flags);
-
- return b;
-}
-
-static int
-i2c_open(struct inode *inode, struct file *filp)
-{
- return 0;
-}
-
-static int
-i2c_release(struct inode *inode, struct file *filp)
-{
- return 0;
-}
-
-/* Main device API. ioctl's to write or read to/from i2c registers.
- */
-
-static long
-i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- int ret;
- if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) {
- return -ENOTTY;
- }
-
- switch (_IOC_NR(cmd)) {
- case I2C_WRITEREG:
- /* write to an i2c slave */
- D(printk("i2cw %d %d %d\n",
- I2C_ARGSLAVE(arg),
- I2C_ARGREG(arg),
- I2C_ARGVALUE(arg)));
-
- mutex_lock(&i2c_mutex);
- ret = i2c_writereg(I2C_ARGSLAVE(arg),
- I2C_ARGREG(arg),
- I2C_ARGVALUE(arg));
- mutex_unlock(&i2c_mutex);
- return ret;
-
- case I2C_READREG:
- {
- unsigned char val;
- /* read from an i2c slave */
- D(printk("i2cr %d %d ",
- I2C_ARGSLAVE(arg),
- I2C_ARGREG(arg)));
- mutex_lock(&i2c_mutex);
- val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg));
- mutex_unlock(&i2c_mutex);
- D(printk("= %d\n", val));
- return val;
- }
- default:
- return -EINVAL;
-
- }
-
- return 0;
-}
-
-static const struct file_operations i2c_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = i2c_ioctl,
- .open = i2c_open,
- .release = i2c_release,
- .llseek = noop_llseek,
-};
-
-static int __init i2c_init(void)
-{
- static int res;
- static int first = 1;
-
- if (!first)
- return res;
-
- first = 0;
-
- /* Setup and enable the DATA and CLK pins */
-
- res = crisv32_io_get_name(&cris_i2c_data,
- CONFIG_ETRAX_V32_I2C_DATA_PORT);
- if (res < 0)
- return res;
-
- res = crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_V32_I2C_CLK_PORT);
- crisv32_io_set_dir(&cris_i2c_clk, crisv32_io_dir_out);
-
- return res;
-}
-
-
-static int __init i2c_register(void)
-{
- int res;
-
- res = i2c_init();
- if (res < 0)
- return res;
-
- /* register char device */
-
- res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops);
- if (res < 0) {
- printk(KERN_ERR "i2c: couldn't get a major number.\n");
- return res;
- }
-
- printk(KERN_INFO
- "I2C driver v2.2, (c) 1999-2007 Axis Communications AB\n");
-
- return 0;
-}
-/* this makes sure that i2c_init is called during boot */
-module_init(i2c_register);
-
-/****************** END OF FILE i2c.c ********************************/
diff --git a/arch/cris/arch-v32/drivers/i2c.h b/arch/cris/arch-v32/drivers/i2c.h
deleted file mode 100644
index d9cc856f89fb..000000000000
--- a/arch/cris/arch-v32/drivers/i2c.h
+++ /dev/null
@@ -1,16 +0,0 @@
-
-#include <linux/init.h>
-
-/* High level I2C actions */
-int i2c_write(unsigned char theSlave, void *data, size_t nbytes);
-int i2c_read(unsigned char theSlave, void *data, size_t nbytes);
-int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue);
-unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg);
-
-/* Low level I2C */
-void i2c_start(void);
-void i2c_stop(void);
-void i2c_outbyte(unsigned char x);
-unsigned char i2c_inbyte(void);
-int i2c_getack(void);
-void i2c_sendack(void);
diff --git a/arch/cris/arch-v32/drivers/mach-a3/Makefile b/arch/cris/arch-v32/drivers/mach-a3/Makefile
index 5c6d2a2a080e..59028d0b981c 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/Makefile
+++ b/arch/cris/arch-v32/drivers/mach-a3/Makefile
@@ -3,4 +3,3 @@
#
obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o
-obj-$(CONFIG_ETRAX_GPIO) += gpio.o
diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c
deleted file mode 100644
index c92e1da3684d..000000000000
--- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c
+++ /dev/null
@@ -1,999 +0,0 @@
-/*
- * Artec-3 general port I/O device
- *
- * Copyright (c) 2007 Axis Communications AB
- *
- * Authors: Bjorn Wesen (initial version)
- * Ola Knutsson (LED handling)
- * Johan Adolfsson (read/set directions, write, port G,
- * port to ETRAX FS.
- * Ricard Wanderlof (PWM for Artpec-3)
- *
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-
-#include <asm/etraxgpio.h>
-#include <hwregs/reg_map.h>
-#include <hwregs/reg_rdwr.h>
-#include <hwregs/gio_defs.h>
-#include <hwregs/intr_vect_defs.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <mach/pinmux.h>
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-#include "../i2c.h"
-
-#define VIRT_I2C_ADDR 0x40
-#endif
-
-/* The following gio ports on ARTPEC-3 is available:
- * pa 32 bits
- * pb 32 bits
- * pc 16 bits
- * each port has a rw_px_dout, r_px_din and rw_px_oe register.
- */
-
-#define GPIO_MAJOR 120 /* experimental MAJOR number */
-
-#define I2C_INTERRUPT_BITS 0x300 /* i2c0_done and i2c1_done bits */
-
-#define D(x)
-
-#if 0
-static int dp_cnt;
-#define DP(x) \
- do { \
- dp_cnt++; \
- if (dp_cnt % 1000 == 0) \
- x; \
- } while (0)
-#else
-#define DP(x)
-#endif
-
-static DEFINE_MUTEX(gpio_mutex);
-static char gpio_name[] = "etrax gpio";
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg);
-#endif
-static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-static ssize_t gpio_write(struct file *file, const char __user *buf,
- size_t count, loff_t *off);
-static int gpio_open(struct inode *inode, struct file *filp);
-static int gpio_release(struct inode *inode, struct file *filp);
-static unsigned int gpio_poll(struct file *filp,
- struct poll_table_struct *wait);
-
-/* private data per open() of this driver */
-
-struct gpio_private {
- struct gpio_private *next;
- /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */
- unsigned char clk_mask;
- unsigned char data_mask;
- unsigned char write_msb;
- unsigned char pad1;
- /* These fields are generic */
- unsigned long highalarm, lowalarm;
- wait_queue_head_t alarm_wq;
- int minor;
-};
-
-static void gpio_set_alarm(struct gpio_private *priv);
-static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
-static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,
- unsigned long arg);
-
-
-/* linked list of alarms to check for */
-
-static struct gpio_private *alarmlist;
-
-static int wanted_interrupts;
-
-static DEFINE_SPINLOCK(gpio_lock);
-
-#define NUM_PORTS (GPIO_MINOR_LAST+1)
-#define GIO_REG_RD_ADDR(reg) \
- (unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)
-#define GIO_REG_WR_ADDR(reg) \
- (unsigned long *)(regi_gio + REG_WR_ADDR_gio_##reg)
-static unsigned long led_dummy;
-static unsigned long port_d_dummy; /* Only input on Artpec-3 */
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static unsigned long port_e_dummy; /* Non existent on Artpec-3 */
-static unsigned long virtual_dummy;
-static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE;
-static unsigned short cached_virtual_gpio_read;
-#endif
-
-static unsigned long *data_out[NUM_PORTS] = {
- GIO_REG_WR_ADDR(rw_pa_dout),
- GIO_REG_WR_ADDR(rw_pb_dout),
- &led_dummy,
- GIO_REG_WR_ADDR(rw_pc_dout),
- &port_d_dummy,
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- &port_e_dummy,
- &virtual_dummy,
-#endif
-};
-
-static unsigned long *data_in[NUM_PORTS] = {
- GIO_REG_RD_ADDR(r_pa_din),
- GIO_REG_RD_ADDR(r_pb_din),
- &led_dummy,
- GIO_REG_RD_ADDR(r_pc_din),
- GIO_REG_RD_ADDR(r_pd_din),
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- &port_e_dummy,
- &virtual_dummy,
-#endif
-};
-
-static unsigned long changeable_dir[NUM_PORTS] = {
- CONFIG_ETRAX_PA_CHANGEABLE_DIR,
- CONFIG_ETRAX_PB_CHANGEABLE_DIR,
- 0,
- CONFIG_ETRAX_PC_CHANGEABLE_DIR,
- 0,
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- 0,
- CONFIG_ETRAX_PV_CHANGEABLE_DIR,
-#endif
-};
-
-static unsigned long changeable_bits[NUM_PORTS] = {
- CONFIG_ETRAX_PA_CHANGEABLE_BITS,
- CONFIG_ETRAX_PB_CHANGEABLE_BITS,
- 0,
- CONFIG_ETRAX_PC_CHANGEABLE_BITS,
- 0,
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- 0,
- CONFIG_ETRAX_PV_CHANGEABLE_BITS,
-#endif
-};
-
-static unsigned long *dir_oe[NUM_PORTS] = {
- GIO_REG_WR_ADDR(rw_pa_oe),
- GIO_REG_WR_ADDR(rw_pb_oe),
- &led_dummy,
- GIO_REG_WR_ADDR(rw_pc_oe),
- &port_d_dummy,
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- &port_e_dummy,
- &virtual_rw_pv_oe,
-#endif
-};
-
-static void gpio_set_alarm(struct gpio_private *priv)
-{
- int bit;
- int intr_cfg;
- int mask;
- int pins;
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
- intr_cfg = REG_RD_INT(gio, regi_gio, rw_intr_cfg);
- pins = REG_RD_INT(gio, regi_gio, rw_intr_pins);
- mask = REG_RD_INT(gio, regi_gio, rw_intr_mask) & I2C_INTERRUPT_BITS;
-
- for (bit = 0; bit < 32; bit++) {
- int intr = bit % 8;
- int pin = bit / 8;
- if (priv->minor < GPIO_MINOR_LEDS)
- pin += priv->minor * 4;
- else
- pin += (priv->minor - 1) * 4;
-
- if (priv->highalarm & (1<<bit)) {
- intr_cfg |= (regk_gio_hi << (intr * 3));
- mask |= 1 << intr;
- wanted_interrupts = mask & 0xff;
- pins |= pin << (intr * 4);
- } else if (priv->lowalarm & (1<<bit)) {
- intr_cfg |= (regk_gio_lo << (intr * 3));
- mask |= 1 << intr;
- wanted_interrupts = mask & 0xff;
- pins |= pin << (intr * 4);
- }
- }
-
- REG_WR_INT(gio, regi_gio, rw_intr_cfg, intr_cfg);
- REG_WR_INT(gio, regi_gio, rw_intr_pins, pins);
- REG_WR_INT(gio, regi_gio, rw_intr_mask, mask);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-}
-
-static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait)
-{
- unsigned int mask = 0;
- struct gpio_private *priv = file->private_data;
- unsigned long data;
- unsigned long tmp;
-
- if (priv->minor >= GPIO_MINOR_PWM0 &&
- priv->minor <= GPIO_MINOR_LAST_PWM)
- return 0;
-
- poll_wait(file, &priv->alarm_wq, wait);
- if (priv->minor <= GPIO_MINOR_D) {
- data = readl(data_in[priv->minor]);
- REG_WR_INT(gio, regi_gio, rw_ack_intr, wanted_interrupts);
- tmp = REG_RD_INT(gio, regi_gio, rw_intr_mask);
- tmp &= I2C_INTERRUPT_BITS;
- tmp |= wanted_interrupts;
- REG_WR_INT(gio, regi_gio, rw_intr_mask, tmp);
- } else
- return 0;
-
- if ((data & priv->highalarm) || (~data & priv->lowalarm))
- mask = POLLIN|POLLRDNORM;
-
- DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask));
- return mask;
-}
-
-static irqreturn_t gpio_interrupt(int irq, void *dev_id)
-{
- reg_gio_rw_intr_mask intr_mask;
- reg_gio_r_masked_intr masked_intr;
- reg_gio_rw_ack_intr ack_intr;
- unsigned long flags;
- unsigned long tmp;
- unsigned long tmp2;
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- unsigned char enable_gpiov_ack = 0;
-#endif
-
- /* Find what PA interrupts are active */
- masked_intr = REG_RD(gio, regi_gio, r_masked_intr);
- tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr);
-
- /* Find those that we have enabled */
- spin_lock_irqsave(&gpio_lock, flags);
- tmp &= wanted_interrupts;
- spin_unlock_irqrestore(&gpio_lock, flags);
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- /* Something changed on virtual GPIO. Interrupt is acked by
- * reading the device.
- */
- if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) {
- i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read,
- sizeof(cached_virtual_gpio_read));
- enable_gpiov_ack = 1;
- }
-#endif
-
- /* Ack them */
- ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp);
- REG_WR(gio, regi_gio, rw_ack_intr, ack_intr);
-
- /* Disable those interrupts.. */
- intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
- tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask);
- tmp2 &= ~tmp;
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- /* Do not disable interrupt on virtual GPIO. Changes on virtual
- * pins are only noticed by an interrupt.
- */
- if (enable_gpiov_ack)
- tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
-#endif
- intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2);
- REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
-
- return IRQ_RETVAL(tmp);
-}
-
-static void gpio_write_bit(unsigned long *port, unsigned char data, int bit,
- unsigned char clk_mask, unsigned char data_mask)
-{
- unsigned long shadow = readl(port) & ~clk_mask;
- writel(shadow, port);
- if (data & 1 << bit)
- shadow |= data_mask;
- else
- shadow &= ~data_mask;
- writel(shadow, port);
- /* For FPGA: min 5.0ns (DCC) before CCLK high */
- shadow |= clk_mask;
- writel(shadow, port);
-}
-
-static void gpio_write_byte(struct gpio_private *priv, unsigned long *port,
- unsigned char data)
-{
- int i;
-
- if (priv->write_msb)
- for (i = 7; i >= 0; i--)
- gpio_write_bit(port, data, i, priv->clk_mask,
- priv->data_mask);
- else
- for (i = 0; i <= 7; i++)
- gpio_write_bit(port, data, i, priv->clk_mask,
- priv->data_mask);
-}
-
-
-static ssize_t gpio_write(struct file *file, const char __user *buf,
- size_t count, loff_t *off)
-{
- struct gpio_private *priv = file->private_data;
- unsigned long flags;
- ssize_t retval = count;
- /* Only bits 0-7 may be used for write operations but allow all
- devices except leds... */
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- if (priv->minor == GPIO_MINOR_V)
- return -EFAULT;
-#endif
- if (priv->minor == GPIO_MINOR_LEDS)
- return -EFAULT;
-
- if (priv->minor >= GPIO_MINOR_PWM0 &&
- priv->minor <= GPIO_MINOR_LAST_PWM)
- return -EFAULT;
-
- if (!access_ok(VERIFY_READ, buf, count))
- return -EFAULT;
-
- /* It must have been configured using the IO_CFG_WRITE_MODE */
- /* Perhaps a better error code? */
- if (priv->clk_mask == 0 || priv->data_mask == 0)
- return -EPERM;
-
- D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X "
- "msb: %i\n",
- count, priv->data_mask, priv->clk_mask, priv->write_msb));
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- while (count--)
- gpio_write_byte(priv, data_out[priv->minor], *buf++);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
- return retval;
-}
-
-static int gpio_open(struct inode *inode, struct file *filp)
-{
- struct gpio_private *priv;
- int p = iminor(inode);
-
- if (p > GPIO_MINOR_LAST_PWM ||
- (p > GPIO_MINOR_LAST && p < GPIO_MINOR_PWM0))
- return -EINVAL;
-
- priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL);
-
- if (!priv)
- return -ENOMEM;
-
- mutex_lock(&gpio_mutex);
- memset(priv, 0, sizeof(*priv));
-
- priv->minor = p;
- filp->private_data = priv;
-
- /* initialize the io/alarm struct, not for PWM ports though */
- if (p <= GPIO_MINOR_LAST) {
-
- priv->clk_mask = 0;
- priv->data_mask = 0;
- priv->highalarm = 0;
- priv->lowalarm = 0;
-
- init_waitqueue_head(&priv->alarm_wq);
-
- /* link it into our alarmlist */
- spin_lock_irq(&gpio_lock);
- priv->next = alarmlist;
- alarmlist = priv;
- spin_unlock_irq(&gpio_lock);
- }
-
- mutex_unlock(&gpio_mutex);
- return 0;
-}
-
-static int gpio_release(struct inode *inode, struct file *filp)
-{
- struct gpio_private *p;
- struct gpio_private *todel;
- /* local copies while updating them: */
- unsigned long a_high, a_low;
-
- /* prepare to free private structure */
- todel = filp->private_data;
-
- /* unlink from alarmlist - only for non-PWM ports though */
- if (todel->minor <= GPIO_MINOR_LAST) {
- spin_lock_irq(&gpio_lock);
- p = alarmlist;
-
- if (p == todel)
- alarmlist = todel->next;
- else {
- while (p->next != todel)
- p = p->next;
- p->next = todel->next;
- }
-
- /* Check if there are still any alarms set */
- p = alarmlist;
- a_high = 0;
- a_low = 0;
- while (p) {
- if (p->minor == GPIO_MINOR_A) {
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
-#endif
- a_high |= p->highalarm;
- a_low |= p->lowalarm;
- }
-
- p = p->next;
- }
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- /* Variable 'a_low' needs to be set here again
- * to ensure that interrupt for virtual GPIO is handled.
- */
- a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
-#endif
-
- spin_unlock_irq(&gpio_lock);
- }
- kfree(todel);
-
- return 0;
-}
-
-/* Main device API. ioctl's to read/set/clear bits, as well as to
- * set alarms to wait for using a subsequent select().
- */
-
-inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg)
-{
- /* Set direction 0=unchanged 1=input,
- * return mask with 1=input
- */
- unsigned long flags;
- unsigned long dir_shadow;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- dir_shadow = readl(dir_oe[priv->minor]) &
- ~(arg & changeable_dir[priv->minor]);
- writel(dir_shadow, dir_oe[priv->minor]);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- if (priv->minor == GPIO_MINOR_C)
- dir_shadow ^= 0xFFFF; /* Only 16 bits */
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- else if (priv->minor == GPIO_MINOR_V)
- dir_shadow ^= 0xFFFF; /* Only 16 bits */
-#endif
- else
- dir_shadow ^= 0xFFFFFFFF; /* PA, PB and PD 32 bits */
-
- return dir_shadow;
-
-} /* setget_input */
-
-static inline unsigned long setget_output(struct gpio_private *priv,
- unsigned long arg)
-{
- unsigned long flags;
- unsigned long dir_shadow;
-
- spin_lock_irqsave(&gpio_lock, flags);
-
- dir_shadow = readl(dir_oe[priv->minor]) |
- (arg & changeable_dir[priv->minor]);
- writel(dir_shadow, dir_oe[priv->minor]);
-
- spin_unlock_irqrestore(&gpio_lock, flags);
- return dir_shadow;
-} /* setget_output */
-
-static long gpio_ioctl_unlocked(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- unsigned long val;
- unsigned long shadow;
- struct gpio_private *priv = file->private_data;
-
- if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
- return -ENOTTY;
-
- /* Check for special ioctl handlers first */
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- if (priv->minor == GPIO_MINOR_V)
- return virtual_gpio_ioctl(file, cmd, arg);
-#endif
-
- if (priv->minor == GPIO_MINOR_LEDS)
- return gpio_leds_ioctl(cmd, arg);
-
- if (priv->minor >= GPIO_MINOR_PWM0 &&
- priv->minor <= GPIO_MINOR_LAST_PWM)
- return gpio_pwm_ioctl(priv, cmd, arg);
-
- switch (_IOC_NR(cmd)) {
- case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
- /* Read the port. */
- return readl(data_in[priv->minor]);
- case IO_SETBITS:
- spin_lock_irqsave(&gpio_lock, flags);
- /* Set changeable bits with a 1 in arg. */
- shadow = readl(data_out[priv->minor]) |
- (arg & changeable_bits[priv->minor]);
- writel(shadow, data_out[priv->minor]);
- spin_unlock_irqrestore(&gpio_lock, flags);
- break;
- case IO_CLRBITS:
- spin_lock_irqsave(&gpio_lock, flags);
- /* Clear changeable bits with a 1 in arg. */
- shadow = readl(data_out[priv->minor]) &
- ~(arg & changeable_bits[priv->minor]);
- writel(shadow, data_out[priv->minor]);
- spin_unlock_irqrestore(&gpio_lock, flags);
- break;
- case IO_HIGHALARM:
- /* Set alarm when bits with 1 in arg go high. */
- priv->highalarm |= arg;
- gpio_set_alarm(priv);
- break;
- case IO_LOWALARM:
- /* Set alarm when bits with 1 in arg go low. */
- priv->lowalarm |= arg;
- gpio_set_alarm(priv);
- break;
- case IO_CLRALARM:
- /* Clear alarm for bits with 1 in arg. */
- priv->highalarm &= ~arg;
- priv->lowalarm &= ~arg;
- gpio_set_alarm(priv);
- break;
- case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
- /* Read direction 0=input 1=output */
- return readl(dir_oe[priv->minor]);
-
- case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
- /* Set direction 0=unchanged 1=input,
- * return mask with 1=input
- */
- return setget_input(priv, arg);
-
- case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
- /* Set direction 0=unchanged 1=output,
- * return mask with 1=output
- */
- return setget_output(priv, arg);
-
- case IO_CFG_WRITE_MODE:
- {
- int res = -EPERM;
- unsigned long dir_shadow, clk_mask, data_mask, write_msb;
-
- clk_mask = arg & 0xFF;
- data_mask = (arg >> 8) & 0xFF;
- write_msb = (arg >> 16) & 0x01;
-
- /* Check if we're allowed to change the bits and
- * the direction is correct
- */
- spin_lock_irqsave(&gpio_lock, flags);
- dir_shadow = readl(dir_oe[priv->minor]);
- if ((clk_mask & changeable_bits[priv->minor]) &&
- (data_mask & changeable_bits[priv->minor]) &&
- (clk_mask & dir_shadow) &&
- (data_mask & dir_shadow)) {
- priv->clk_mask = clk_mask;
- priv->data_mask = data_mask;
- priv->write_msb = write_msb;
- res = 0;
- }
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- return res;
- }
- case IO_READ_INBITS:
- /* *arg is result of reading the input pins */
- val = readl(data_in[priv->minor]);
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- return 0;
- case IO_READ_OUTBITS:
- /* *arg is result of reading the output shadow */
- val = *data_out[priv->minor];
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- case IO_SETGET_INPUT:
- /* bits set in *arg is set to input,
- * *arg updated with current input pins.
- */
- if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_input(priv, val);
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- case IO_SETGET_OUTPUT:
- /* bits set in *arg is set to output,
- * *arg updated with current output pins.
- */
- if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_output(priv, val);
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- default:
- return -EINVAL;
- } /* switch */
-
- return 0;
-}
-
-static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- long ret;
-
- mutex_lock(&gpio_mutex);
- ret = gpio_ioctl_unlocked(file, cmd, arg);
- mutex_unlock(&gpio_mutex);
-
- return ret;
-}
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- unsigned long flags;
- unsigned short val;
- unsigned short shadow;
- struct gpio_private *priv = file->private_data;
-
- switch (_IOC_NR(cmd)) {
- case IO_SETBITS:
- spin_lock_irqsave(&gpio_lock, flags);
- /* Set changeable bits with a 1 in arg. */
- i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- shadow |= ~readl(dir_oe[priv->minor]) |
- (arg & changeable_bits[priv->minor]);
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- spin_unlock_irqrestore(&gpio_lock, flags);
- break;
- case IO_CLRBITS:
- spin_lock_irqsave(&gpio_lock, flags);
- /* Clear changeable bits with a 1 in arg. */
- i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- shadow |= ~readl(dir_oe[priv->minor]) &
- ~(arg & changeable_bits[priv->minor]);
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- spin_unlock_irqrestore(&gpio_lock, flags);
- break;
- case IO_HIGHALARM:
- /* Set alarm when bits with 1 in arg go high. */
- priv->highalarm |= arg;
- break;
- case IO_LOWALARM:
- /* Set alarm when bits with 1 in arg go low. */
- priv->lowalarm |= arg;
- break;
- case IO_CLRALARM:
- /* Clear alarm for bits with 1 in arg. */
- priv->highalarm &= ~arg;
- priv->lowalarm &= ~arg;
- break;
- case IO_CFG_WRITE_MODE:
- {
- unsigned long dir_shadow;
- dir_shadow = readl(dir_oe[priv->minor]);
-
- priv->clk_mask = arg & 0xFF;
- priv->data_mask = (arg >> 8) & 0xFF;
- priv->write_msb = (arg >> 16) & 0x01;
- /* Check if we're allowed to change the bits and
- * the direction is correct
- */
- if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
- (priv->data_mask & changeable_bits[priv->minor]) &&
- (priv->clk_mask & dir_shadow) &&
- (priv->data_mask & dir_shadow))) {
- priv->clk_mask = 0;
- priv->data_mask = 0;
- return -EPERM;
- }
- break;
- }
- case IO_READ_INBITS:
- /* *arg is result of reading the input pins */
- val = cached_virtual_gpio_read & ~readl(dir_oe[priv->minor]);
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- return 0;
-
- case IO_READ_OUTBITS:
- /* *arg is result of reading the output shadow */
- i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val));
- val &= readl(dir_oe[priv->minor]);
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- case IO_SETGET_INPUT:
- {
- /* bits set in *arg is set to input,
- * *arg updated with current input pins.
- */
- unsigned short input_mask = ~readl(dir_oe[priv->minor]);
- if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_input(priv, val);
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- if ((input_mask & val) != input_mask) {
- /* Input pins changed. All ports desired as input
- * should be set to logic 1.
- */
- unsigned short change = input_mask ^ val;
- i2c_read(VIRT_I2C_ADDR, (void *)&shadow,
- sizeof(shadow));
- shadow &= ~change;
- shadow |= val;
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow,
- sizeof(shadow));
- }
- break;
- }
- case IO_SETGET_OUTPUT:
- /* bits set in *arg is set to output,
- * *arg updated with current output pins.
- */
- if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_output(priv, val);
- if (copy_to_user((void __user *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- default:
- return -EINVAL;
- } /* switch */
- return 0;
-}
-#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */
-
-static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
-{
- unsigned char green;
- unsigned char red;
-
- switch (_IOC_NR(cmd)) {
- case IO_LEDACTIVE_SET:
- green = ((unsigned char) arg) & 1;
- red = (((unsigned char) arg) >> 1) & 1;
- CRIS_LED_ACTIVE_SET_G(green);
- CRIS_LED_ACTIVE_SET_R(red);
- break;
-
- default:
- return -EINVAL;
- } /* switch */
-
- return 0;
-}
-
-static int gpio_pwm_set_mode(unsigned long arg, int pwm_port)
-{
- int pinmux_pwm = pinmux_pwm0 + pwm_port;
- int mode;
- reg_gio_rw_pwm0_ctrl rw_pwm_ctrl = {
- .ccd_val = 0,
- .ccd_override = regk_gio_no,
- .mode = regk_gio_no
- };
- int allocstatus;
-
- if (get_user(mode, &((struct io_pwm_set_mode *) arg)->mode))
- return -EFAULT;
- rw_pwm_ctrl.mode = mode;
- if (mode != PWM_OFF)
- allocstatus = crisv32_pinmux_alloc_fixed(pinmux_pwm);
- else
- allocstatus = crisv32_pinmux_dealloc_fixed(pinmux_pwm);
- if (allocstatus)
- return allocstatus;
- REG_WRITE(reg_gio_rw_pwm0_ctrl, REG_ADDR(gio, regi_gio, rw_pwm0_ctrl) +
- 12 * pwm_port, rw_pwm_ctrl);
- return 0;
-}
-
-static int gpio_pwm_set_period(unsigned long arg, int pwm_port)
-{
- struct io_pwm_set_period periods;
- reg_gio_rw_pwm0_var rw_pwm_widths;
-
- if (copy_from_user(&periods, (void __user *)arg, sizeof(periods)))
- return -EFAULT;
- if (periods.lo > 8191 || periods.hi > 8191)
- return -EINVAL;
- rw_pwm_widths.lo = periods.lo;
- rw_pwm_widths.hi = periods.hi;
- REG_WRITE(reg_gio_rw_pwm0_var, REG_ADDR(gio, regi_gio, rw_pwm0_var) +
- 12 * pwm_port, rw_pwm_widths);
- return 0;
-}
-
-static int gpio_pwm_set_duty(unsigned long arg, int pwm_port)
-{
- unsigned int duty;
- reg_gio_rw_pwm0_data rw_pwm_duty;
-
- if (get_user(duty, &((struct io_pwm_set_duty *) arg)->duty))
- return -EFAULT;
- if (duty > 255)
- return -EINVAL;
- rw_pwm_duty.data = duty;
- REG_WRITE(reg_gio_rw_pwm0_data, REG_ADDR(gio, regi_gio, rw_pwm0_data) +
- 12 * pwm_port, rw_pwm_duty);
- return 0;
-}
-
-static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd,
- unsigned long arg)
-{
- int pwm_port = priv->minor - GPIO_MINOR_PWM0;
-
- switch (_IOC_NR(cmd)) {
- case IO_PWM_SET_MODE:
- return gpio_pwm_set_mode(arg, pwm_port);
- case IO_PWM_SET_PERIOD:
- return gpio_pwm_set_period(arg, pwm_port);
- case IO_PWM_SET_DUTY:
- return gpio_pwm_set_duty(arg, pwm_port);
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static const struct file_operations gpio_fops = {
- .owner = THIS_MODULE,
- .poll = gpio_poll,
- .unlocked_ioctl = gpio_ioctl,
- .write = gpio_write,
- .open = gpio_open,
- .release = gpio_release,
- .llseek = noop_llseek,
-};
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static void __init virtual_gpio_init(void)
-{
- reg_gio_rw_intr_cfg intr_cfg;
- reg_gio_rw_intr_mask intr_mask;
- unsigned short shadow;
-
- shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */
- shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT;
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
-
- /* Set interrupt mask and on what state the interrupt shall trigger.
- * For virtual gpio the interrupt shall trigger on logic '0'.
- */
- intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
- intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
-
- switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) {
- case 0:
- intr_cfg.pa0 = regk_gio_lo;
- intr_mask.pa0 = regk_gio_yes;
- break;
- case 1:
- intr_cfg.pa1 = regk_gio_lo;
- intr_mask.pa1 = regk_gio_yes;
- break;
- case 2:
- intr_cfg.pa2 = regk_gio_lo;
- intr_mask.pa2 = regk_gio_yes;
- break;
- case 3:
- intr_cfg.pa3 = regk_gio_lo;
- intr_mask.pa3 = regk_gio_yes;
- break;
- case 4:
- intr_cfg.pa4 = regk_gio_lo;
- intr_mask.pa4 = regk_gio_yes;
- break;
- case 5:
- intr_cfg.pa5 = regk_gio_lo;
- intr_mask.pa5 = regk_gio_yes;
- break;
- case 6:
- intr_cfg.pa6 = regk_gio_lo;
- intr_mask.pa6 = regk_gio_yes;
- break;
- case 7:
- intr_cfg.pa7 = regk_gio_lo;
- intr_mask.pa7 = regk_gio_yes;
- break;
- }
-
- REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
- REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
-}
-#endif
-
-/* main driver initialization routine, called from mem.c */
-
-static int __init gpio_init(void)
-{
- int res, res2;
-
- printk(KERN_INFO "ETRAX FS GPIO driver v2.7, (c) 2003-2008 "
- "Axis Communications AB\n");
-
- /* do the formalities */
-
- res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
- if (res < 0) {
- printk(KERN_ERR "gpio: couldn't get a major number.\n");
- return res;
- }
-
- /* Clear all leds */
- CRIS_LED_NETWORK_GRP0_SET(0);
- CRIS_LED_NETWORK_GRP1_SET(0);
- CRIS_LED_ACTIVE_SET(0);
- CRIS_LED_DISK_READ(0);
- CRIS_LED_DISK_WRITE(0);
-
- res2 = request_irq(GIO_INTR_VECT, gpio_interrupt,
- IRQF_SHARED, "gpio", &alarmlist);
- if (res2) {
- printk(KERN_ERR "err: irq for gpio\n");
- return res2;
- }
-
- /* No IRQs by default. */
- REG_WR_INT(gio, regi_gio, rw_intr_pins, 0);
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- virtual_gpio_init();
-#endif
-
- return res;
-}
-
-/* this makes sure that gpio_init is called during kernel boot */
-
-module_init(gpio_init);
diff --git a/arch/cris/arch-v32/drivers/mach-fs/Makefile b/arch/cris/arch-v32/drivers/mach-fs/Makefile
index 5c6d2a2a080e..59028d0b981c 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/Makefile
+++ b/arch/cris/arch-v32/drivers/mach-fs/Makefile
@@ -3,4 +3,3 @@
#
obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o
-obj-$(CONFIG_ETRAX_GPIO) += gpio.o
diff --git a/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/arch/cris/arch-v32/drivers/mach-fs/gpio.c
deleted file mode 100644
index 72968fbf814b..000000000000
--- a/arch/cris/arch-v32/drivers/mach-fs/gpio.c
+++ /dev/null
@@ -1,978 +0,0 @@
-/*
- * ETRAX CRISv32 general port I/O device
- *
- * Copyright (c) 1999-2006 Axis Communications AB
- *
- * Authors: Bjorn Wesen (initial version)
- * Ola Knutsson (LED handling)
- * Johan Adolfsson (read/set directions, write, port G,
- * port to ETRAX FS.
- *
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-
-#include <asm/etraxgpio.h>
-#include <hwregs/reg_map.h>
-#include <hwregs/reg_rdwr.h>
-#include <hwregs/gio_defs.h>
-#include <hwregs/intr_vect_defs.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-#include "../i2c.h"
-
-#define VIRT_I2C_ADDR 0x40
-#endif
-
-/* The following gio ports on ETRAX FS is available:
- * pa 8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge
- * pb 18 bits
- * pc 18 bits
- * pd 18 bits
- * pe 18 bits
- * each port has a rw_px_dout, r_px_din and rw_px_oe register.
- */
-
-#define GPIO_MAJOR 120 /* experimental MAJOR number */
-
-#define D(x)
-
-#if 0
-static int dp_cnt;
-#define DP(x) \
- do { \
- dp_cnt++; \
- if (dp_cnt % 1000 == 0) \
- x; \
- } while (0)
-#else
-#define DP(x)
-#endif
-
-static DEFINE_MUTEX(gpio_mutex);
-static char gpio_name[] = "etrax gpio";
-
-#if 0
-static wait_queue_head_t *gpio_wq;
-#endif
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static int virtual_gpio_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg);
-#endif
-static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-static ssize_t gpio_write(struct file *file, const char *buf, size_t count,
- loff_t *off);
-static int gpio_open(struct inode *inode, struct file *filp);
-static int gpio_release(struct inode *inode, struct file *filp);
-static unsigned int gpio_poll(struct file *filp,
- struct poll_table_struct *wait);
-
-/* private data per open() of this driver */
-
-struct gpio_private {
- struct gpio_private *next;
- /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */
- unsigned char clk_mask;
- unsigned char data_mask;
- unsigned char write_msb;
- unsigned char pad1;
- /* These fields are generic */
- unsigned long highalarm, lowalarm;
- wait_queue_head_t alarm_wq;
- int minor;
-};
-
-/* linked list of alarms to check for */
-
-static struct gpio_private *alarmlist;
-
-static int gpio_some_alarms; /* Set if someone uses alarm */
-static unsigned long gpio_pa_high_alarms;
-static unsigned long gpio_pa_low_alarms;
-
-static DEFINE_SPINLOCK(alarm_lock);
-
-#define NUM_PORTS (GPIO_MINOR_LAST+1)
-#define GIO_REG_RD_ADDR(reg) \
- (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)
-#define GIO_REG_WR_ADDR(reg) \
- (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg)
-unsigned long led_dummy;
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static unsigned long virtual_dummy;
-static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE;
-static unsigned short cached_virtual_gpio_read;
-#endif
-
-static volatile unsigned long *data_out[NUM_PORTS] = {
- GIO_REG_WR_ADDR(rw_pa_dout),
- GIO_REG_WR_ADDR(rw_pb_dout),
- &led_dummy,
- GIO_REG_WR_ADDR(rw_pc_dout),
- GIO_REG_WR_ADDR(rw_pd_dout),
- GIO_REG_WR_ADDR(rw_pe_dout),
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- &virtual_dummy,
-#endif
-};
-
-static volatile unsigned long *data_in[NUM_PORTS] = {
- GIO_REG_RD_ADDR(r_pa_din),
- GIO_REG_RD_ADDR(r_pb_din),
- &led_dummy,
- GIO_REG_RD_ADDR(r_pc_din),
- GIO_REG_RD_ADDR(r_pd_din),
- GIO_REG_RD_ADDR(r_pe_din),
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- &virtual_dummy,
-#endif
-};
-
-static unsigned long changeable_dir[NUM_PORTS] = {
- CONFIG_ETRAX_PA_CHANGEABLE_DIR,
- CONFIG_ETRAX_PB_CHANGEABLE_DIR,
- 0,
- CONFIG_ETRAX_PC_CHANGEABLE_DIR,
- CONFIG_ETRAX_PD_CHANGEABLE_DIR,
- CONFIG_ETRAX_PE_CHANGEABLE_DIR,
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- CONFIG_ETRAX_PV_CHANGEABLE_DIR,
-#endif
-};
-
-static unsigned long changeable_bits[NUM_PORTS] = {
- CONFIG_ETRAX_PA_CHANGEABLE_BITS,
- CONFIG_ETRAX_PB_CHANGEABLE_BITS,
- 0,
- CONFIG_ETRAX_PC_CHANGEABLE_BITS,
- CONFIG_ETRAX_PD_CHANGEABLE_BITS,
- CONFIG_ETRAX_PE_CHANGEABLE_BITS,
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- CONFIG_ETRAX_PV_CHANGEABLE_BITS,
-#endif
-};
-
-static volatile unsigned long *dir_oe[NUM_PORTS] = {
- GIO_REG_WR_ADDR(rw_pa_oe),
- GIO_REG_WR_ADDR(rw_pb_oe),
- &led_dummy,
- GIO_REG_WR_ADDR(rw_pc_oe),
- GIO_REG_WR_ADDR(rw_pd_oe),
- GIO_REG_WR_ADDR(rw_pe_oe),
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- &virtual_rw_pv_oe,
-#endif
-};
-
-
-
-static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait)
-{
- unsigned int mask = 0;
- struct gpio_private *priv = file->private_data;
- unsigned long data;
- poll_wait(file, &priv->alarm_wq, wait);
- if (priv->minor == GPIO_MINOR_A) {
- reg_gio_rw_intr_cfg intr_cfg;
- unsigned long tmp;
- unsigned long flags;
-
- local_irq_save(flags);
- data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din,
- REG_RD(gio, regi_gio, r_pa_din));
- /* PA has support for interrupt
- * lets activate high for those low and with highalarm set
- */
- intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
-
- tmp = ~data & priv->highalarm & 0xFF;
- if (tmp & (1 << 0))
- intr_cfg.pa0 = regk_gio_hi;
- if (tmp & (1 << 1))
- intr_cfg.pa1 = regk_gio_hi;
- if (tmp & (1 << 2))
- intr_cfg.pa2 = regk_gio_hi;
- if (tmp & (1 << 3))
- intr_cfg.pa3 = regk_gio_hi;
- if (tmp & (1 << 4))
- intr_cfg.pa4 = regk_gio_hi;
- if (tmp & (1 << 5))
- intr_cfg.pa5 = regk_gio_hi;
- if (tmp & (1 << 6))
- intr_cfg.pa6 = regk_gio_hi;
- if (tmp & (1 << 7))
- intr_cfg.pa7 = regk_gio_hi;
- /*
- * lets activate low for those high and with lowalarm set
- */
- tmp = data & priv->lowalarm & 0xFF;
- if (tmp & (1 << 0))
- intr_cfg.pa0 = regk_gio_lo;
- if (tmp & (1 << 1))
- intr_cfg.pa1 = regk_gio_lo;
- if (tmp & (1 << 2))
- intr_cfg.pa2 = regk_gio_lo;
- if (tmp & (1 << 3))
- intr_cfg.pa3 = regk_gio_lo;
- if (tmp & (1 << 4))
- intr_cfg.pa4 = regk_gio_lo;
- if (tmp & (1 << 5))
- intr_cfg.pa5 = regk_gio_lo;
- if (tmp & (1 << 6))
- intr_cfg.pa6 = regk_gio_lo;
- if (tmp & (1 << 7))
- intr_cfg.pa7 = regk_gio_lo;
-
- REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
- local_irq_restore(flags);
- } else if (priv->minor <= GPIO_MINOR_E)
- data = *data_in[priv->minor];
- else
- return 0;
-
- if ((data & priv->highalarm) || (~data & priv->lowalarm))
- mask = POLLIN|POLLRDNORM;
-
- DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask));
- return mask;
-}
-
-int etrax_gpio_wake_up_check(void)
-{
- struct gpio_private *priv;
- unsigned long data = 0;
- unsigned long flags;
- int ret = 0;
- spin_lock_irqsave(&alarm_lock, flags);
- priv = alarmlist;
- while (priv) {
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- if (priv->minor == GPIO_MINOR_V)
- data = (unsigned long)cached_virtual_gpio_read;
- else {
- data = *data_in[priv->minor];
- if (priv->minor == GPIO_MINOR_A)
- priv->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
- }
-#else
- data = *data_in[priv->minor];
-#endif
- if ((data & priv->highalarm) ||
- (~data & priv->lowalarm)) {
- DP(printk(KERN_DEBUG
- "etrax_gpio_wake_up_check %i\n", priv->minor));
- wake_up_interruptible(&priv->alarm_wq);
- ret = 1;
- }
- priv = priv->next;
- }
- spin_unlock_irqrestore(&alarm_lock, flags);
- return ret;
-}
-
-static irqreturn_t
-gpio_poll_timer_interrupt(int irq, void *dev_id)
-{
- if (gpio_some_alarms)
- return IRQ_RETVAL(etrax_gpio_wake_up_check());
- return IRQ_NONE;
-}
-
-static irqreturn_t
-gpio_pa_interrupt(int irq, void *dev_id)
-{
- reg_gio_rw_intr_mask intr_mask;
- reg_gio_r_masked_intr masked_intr;
- reg_gio_rw_ack_intr ack_intr;
- unsigned long tmp;
- unsigned long tmp2;
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- unsigned char enable_gpiov_ack = 0;
-#endif
-
- /* Find what PA interrupts are active */
- masked_intr = REG_RD(gio, regi_gio, r_masked_intr);
- tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr);
-
- /* Find those that we have enabled */
- spin_lock(&alarm_lock);
- tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms);
- spin_unlock(&alarm_lock);
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- /* Something changed on virtual GPIO. Interrupt is acked by
- * reading the device.
- */
- if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) {
- i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read,
- sizeof(cached_virtual_gpio_read));
- enable_gpiov_ack = 1;
- }
-#endif
-
- /* Ack them */
- ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp);
- REG_WR(gio, regi_gio, rw_ack_intr, ack_intr);
-
- /* Disable those interrupts.. */
- intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
- tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask);
- tmp2 &= ~tmp;
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- /* Do not disable interrupt on virtual GPIO. Changes on virtual
- * pins are only noticed by an interrupt.
- */
- if (enable_gpiov_ack)
- tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
-#endif
- intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2);
- REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
-
- if (gpio_some_alarms)
- return IRQ_RETVAL(etrax_gpio_wake_up_check());
- return IRQ_NONE;
-}
-
-
-static ssize_t gpio_write(struct file *file, const char *buf, size_t count,
- loff_t *off)
-{
- struct gpio_private *priv = file->private_data;
- unsigned char data, clk_mask, data_mask, write_msb;
- unsigned long flags;
- unsigned long shadow;
- volatile unsigned long *port;
- ssize_t retval = count;
- /* Only bits 0-7 may be used for write operations but allow all
- devices except leds... */
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- if (priv->minor == GPIO_MINOR_V)
- return -EFAULT;
-#endif
- if (priv->minor == GPIO_MINOR_LEDS)
- return -EFAULT;
-
- if (!access_ok(VERIFY_READ, buf, count))
- return -EFAULT;
- clk_mask = priv->clk_mask;
- data_mask = priv->data_mask;
- /* It must have been configured using the IO_CFG_WRITE_MODE */
- /* Perhaps a better error code? */
- if (clk_mask == 0 || data_mask == 0)
- return -EPERM;
- write_msb = priv->write_msb;
- D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X "
- "msb: %i\n", count, data_mask, clk_mask, write_msb));
- port = data_out[priv->minor];
-
- while (count--) {
- int i;
- data = *buf++;
- if (priv->write_msb) {
- for (i = 7; i >= 0; i--) {
- local_irq_save(flags);
- shadow = *port;
- *port = shadow &= ~clk_mask;
- if (data & 1<<i)
- *port = shadow |= data_mask;
- else
- *port = shadow &= ~data_mask;
- /* For FPGA: min 5.0ns (DCC) before CCLK high */
- *port = shadow |= clk_mask;
- local_irq_restore(flags);
- }
- } else {
- for (i = 0; i <= 7; i++) {
- local_irq_save(flags);
- shadow = *port;
- *port = shadow &= ~clk_mask;
- if (data & 1<<i)
- *port = shadow |= data_mask;
- else
- *port = shadow &= ~data_mask;
- /* For FPGA: min 5.0ns (DCC) before CCLK high */
- *port = shadow |= clk_mask;
- local_irq_restore(flags);
- }
- }
- }
- return retval;
-}
-
-
-
-static int
-gpio_open(struct inode *inode, struct file *filp)
-{
- struct gpio_private *priv;
- int p = iminor(inode);
-
- if (p > GPIO_MINOR_LAST)
- return -EINVAL;
-
- priv = kzalloc(sizeof(struct gpio_private), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- mutex_lock(&gpio_mutex);
-
- priv->minor = p;
-
- /* initialize the io/alarm struct */
-
- priv->clk_mask = 0;
- priv->data_mask = 0;
- priv->highalarm = 0;
- priv->lowalarm = 0;
- init_waitqueue_head(&priv->alarm_wq);
-
- filp->private_data = (void *)priv;
-
- /* link it into our alarmlist */
- spin_lock_irq(&alarm_lock);
- priv->next = alarmlist;
- alarmlist = priv;
- spin_unlock_irq(&alarm_lock);
-
- mutex_unlock(&gpio_mutex);
- return 0;
-}
-
-static int
-gpio_release(struct inode *inode, struct file *filp)
-{
- struct gpio_private *p;
- struct gpio_private *todel;
- /* local copies while updating them: */
- unsigned long a_high, a_low;
- unsigned long some_alarms;
-
- /* unlink from alarmlist and free the private structure */
-
- spin_lock_irq(&alarm_lock);
- p = alarmlist;
- todel = filp->private_data;
-
- if (p == todel) {
- alarmlist = todel->next;
- } else {
- while (p->next != todel)
- p = p->next;
- p->next = todel->next;
- }
-
- kfree(todel);
- /* Check if there are still any alarms set */
- p = alarmlist;
- some_alarms = 0;
- a_high = 0;
- a_low = 0;
- while (p) {
- if (p->minor == GPIO_MINOR_A) {
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
-#endif
- a_high |= p->highalarm;
- a_low |= p->lowalarm;
- }
-
- if (p->highalarm | p->lowalarm)
- some_alarms = 1;
- p = p->next;
- }
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- /* Variables 'some_alarms' and 'a_low' needs to be set here again
- * to ensure that interrupt for virtual GPIO is handled.
- */
- some_alarms = 1;
- a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
-#endif
-
- gpio_some_alarms = some_alarms;
- gpio_pa_high_alarms = a_high;
- gpio_pa_low_alarms = a_low;
- spin_unlock_irq(&alarm_lock);
-
- return 0;
-}
-
-/* Main device API. ioctl's to read/set/clear bits, as well as to
- * set alarms to wait for using a subsequent select().
- */
-
-inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg)
-{
- /* Set direction 0=unchanged 1=input,
- * return mask with 1=input
- */
- unsigned long flags;
- unsigned long dir_shadow;
-
- local_irq_save(flags);
- dir_shadow = *dir_oe[priv->minor];
- dir_shadow &= ~(arg & changeable_dir[priv->minor]);
- *dir_oe[priv->minor] = dir_shadow;
- local_irq_restore(flags);
-
- if (priv->minor == GPIO_MINOR_A)
- dir_shadow ^= 0xFF; /* Only 8 bits */
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- else if (priv->minor == GPIO_MINOR_V)
- dir_shadow ^= 0xFFFF; /* Only 16 bits */
-#endif
- else
- dir_shadow ^= 0x3FFFF; /* Only 18 bits */
- return dir_shadow;
-
-} /* setget_input */
-
-inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg)
-{
- unsigned long flags;
- unsigned long dir_shadow;
-
- local_irq_save(flags);
- dir_shadow = *dir_oe[priv->minor];
- dir_shadow |= (arg & changeable_dir[priv->minor]);
- *dir_oe[priv->minor] = dir_shadow;
- local_irq_restore(flags);
- return dir_shadow;
-} /* setget_output */
-
-static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg);
-
-static int
-gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- unsigned long val;
- unsigned long shadow;
- struct gpio_private *priv = file->private_data;
- if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE)
- return -EINVAL;
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- if (priv->minor == GPIO_MINOR_V)
- return virtual_gpio_ioctl(file, cmd, arg);
-#endif
-
- switch (_IOC_NR(cmd)) {
- case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */
- /* Read the port. */
- return *data_in[priv->minor];
- break;
- case IO_SETBITS:
- local_irq_save(flags);
- /* Set changeable bits with a 1 in arg. */
- shadow = *data_out[priv->minor];
- shadow |= (arg & changeable_bits[priv->minor]);
- *data_out[priv->minor] = shadow;
- local_irq_restore(flags);
- break;
- case IO_CLRBITS:
- local_irq_save(flags);
- /* Clear changeable bits with a 1 in arg. */
- shadow = *data_out[priv->minor];
- shadow &= ~(arg & changeable_bits[priv->minor]);
- *data_out[priv->minor] = shadow;
- local_irq_restore(flags);
- break;
- case IO_HIGHALARM:
- /* Set alarm when bits with 1 in arg go high. */
- priv->highalarm |= arg;
- spin_lock_irqsave(&alarm_lock, flags);
- gpio_some_alarms = 1;
- if (priv->minor == GPIO_MINOR_A)
- gpio_pa_high_alarms |= arg;
- spin_unlock_irqrestore(&alarm_lock, flags);
- break;
- case IO_LOWALARM:
- /* Set alarm when bits with 1 in arg go low. */
- priv->lowalarm |= arg;
- spin_lock_irqsave(&alarm_lock, flags);
- gpio_some_alarms = 1;
- if (priv->minor == GPIO_MINOR_A)
- gpio_pa_low_alarms |= arg;
- spin_unlock_irqrestore(&alarm_lock, flags);
- break;
- case IO_CLRALARM:
- /* Clear alarm for bits with 1 in arg. */
- priv->highalarm &= ~arg;
- priv->lowalarm &= ~arg;
- spin_lock_irqsave(&alarm_lock, flags);
- if (priv->minor == GPIO_MINOR_A) {
- if (gpio_pa_high_alarms & arg ||
- gpio_pa_low_alarms & arg)
- /* Must update the gpio_pa_*alarms masks */
- ;
- }
- spin_unlock_irqrestore(&alarm_lock, flags);
- break;
- case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */
- /* Read direction 0=input 1=output */
- return *dir_oe[priv->minor];
- case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */
- /* Set direction 0=unchanged 1=input,
- * return mask with 1=input
- */
- return setget_input(priv, arg);
- break;
- case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */
- /* Set direction 0=unchanged 1=output,
- * return mask with 1=output
- */
- return setget_output(priv, arg);
-
- case IO_CFG_WRITE_MODE:
- {
- unsigned long dir_shadow;
- dir_shadow = *dir_oe[priv->minor];
-
- priv->clk_mask = arg & 0xFF;
- priv->data_mask = (arg >> 8) & 0xFF;
- priv->write_msb = (arg >> 16) & 0x01;
- /* Check if we're allowed to change the bits and
- * the direction is correct
- */
- if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
- (priv->data_mask & changeable_bits[priv->minor]) &&
- (priv->clk_mask & dir_shadow) &&
- (priv->data_mask & dir_shadow))) {
- priv->clk_mask = 0;
- priv->data_mask = 0;
- return -EPERM;
- }
- break;
- }
- case IO_READ_INBITS:
- /* *arg is result of reading the input pins */
- val = *data_in[priv->minor];
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- return 0;
- break;
- case IO_READ_OUTBITS:
- /* *arg is result of reading the output shadow */
- val = *data_out[priv->minor];
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- case IO_SETGET_INPUT:
- /* bits set in *arg is set to input,
- * *arg updated with current input pins.
- */
- if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_input(priv, val);
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- case IO_SETGET_OUTPUT:
- /* bits set in *arg is set to output,
- * *arg updated with current output pins.
- */
- if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_output(priv, val);
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- default:
- if (priv->minor == GPIO_MINOR_LEDS)
- return gpio_leds_ioctl(cmd, arg);
- else
- return -EINVAL;
- } /* switch */
-
- return 0;
-}
-
-static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- long ret;
-
- mutex_lock(&gpio_mutex);
- ret = gpio_ioctl_unlocked(file, cmd, arg);
- mutex_unlock(&gpio_mutex);
-
- return ret;
-}
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static int
-virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- unsigned short val;
- unsigned short shadow;
- struct gpio_private *priv = file->private_data;
-
- switch (_IOC_NR(cmd)) {
- case IO_SETBITS:
- local_irq_save(flags);
- /* Set changeable bits with a 1 in arg. */
- i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- shadow |= ~*dir_oe[priv->minor];
- shadow |= (arg & changeable_bits[priv->minor]);
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- local_irq_restore(flags);
- break;
- case IO_CLRBITS:
- local_irq_save(flags);
- /* Clear changeable bits with a 1 in arg. */
- i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- shadow |= ~*dir_oe[priv->minor];
- shadow &= ~(arg & changeable_bits[priv->minor]);
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
- local_irq_restore(flags);
- break;
- case IO_HIGHALARM:
- /* Set alarm when bits with 1 in arg go high. */
- priv->highalarm |= arg;
- spin_lock(&alarm_lock);
- gpio_some_alarms = 1;
- spin_unlock(&alarm_lock);
- break;
- case IO_LOWALARM:
- /* Set alarm when bits with 1 in arg go low. */
- priv->lowalarm |= arg;
- spin_lock(&alarm_lock);
- gpio_some_alarms = 1;
- spin_unlock(&alarm_lock);
- break;
- case IO_CLRALARM:
- /* Clear alarm for bits with 1 in arg. */
- priv->highalarm &= ~arg;
- priv->lowalarm &= ~arg;
- spin_lock(&alarm_lock);
- spin_unlock(&alarm_lock);
- break;
- case IO_CFG_WRITE_MODE:
- {
- unsigned long dir_shadow;
- dir_shadow = *dir_oe[priv->minor];
-
- priv->clk_mask = arg & 0xFF;
- priv->data_mask = (arg >> 8) & 0xFF;
- priv->write_msb = (arg >> 16) & 0x01;
- /* Check if we're allowed to change the bits and
- * the direction is correct
- */
- if (!((priv->clk_mask & changeable_bits[priv->minor]) &&
- (priv->data_mask & changeable_bits[priv->minor]) &&
- (priv->clk_mask & dir_shadow) &&
- (priv->data_mask & dir_shadow))) {
- priv->clk_mask = 0;
- priv->data_mask = 0;
- return -EPERM;
- }
- break;
- }
- case IO_READ_INBITS:
- /* *arg is result of reading the input pins */
- val = cached_virtual_gpio_read;
- val &= ~*dir_oe[priv->minor];
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- return 0;
- break;
- case IO_READ_OUTBITS:
- /* *arg is result of reading the output shadow */
- i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val));
- val &= *dir_oe[priv->minor];
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- case IO_SETGET_INPUT:
- {
- /* bits set in *arg is set to input,
- * *arg updated with current input pins.
- */
- unsigned short input_mask = ~*dir_oe[priv->minor];
- if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_input(priv, val);
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- if ((input_mask & val) != input_mask) {
- /* Input pins changed. All ports desired as input
- * should be set to logic 1.
- */
- unsigned short change = input_mask ^ val;
- i2c_read(VIRT_I2C_ADDR, (void *)&shadow,
- sizeof(shadow));
- shadow &= ~change;
- shadow |= val;
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow,
- sizeof(shadow));
- }
- break;
- }
- case IO_SETGET_OUTPUT:
- /* bits set in *arg is set to output,
- * *arg updated with current output pins.
- */
- if (copy_from_user(&val, (unsigned long *)arg, sizeof(val)))
- return -EFAULT;
- val = setget_output(priv, val);
- if (copy_to_user((unsigned long *)arg, &val, sizeof(val)))
- return -EFAULT;
- break;
- default:
- return -EINVAL;
- } /* switch */
- return 0;
-}
-#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */
-
-static int
-gpio_leds_ioctl(unsigned int cmd, unsigned long arg)
-{
- unsigned char green;
- unsigned char red;
-
- switch (_IOC_NR(cmd)) {
- case IO_LEDACTIVE_SET:
- green = ((unsigned char) arg) & 1;
- red = (((unsigned char) arg) >> 1) & 1;
- CRIS_LED_ACTIVE_SET_G(green);
- CRIS_LED_ACTIVE_SET_R(red);
- break;
-
- default:
- return -EINVAL;
- } /* switch */
-
- return 0;
-}
-
-static const struct file_operations gpio_fops = {
- .owner = THIS_MODULE,
- .poll = gpio_poll,
- .unlocked_ioctl = gpio_ioctl,
- .write = gpio_write,
- .open = gpio_open,
- .release = gpio_release,
- .llseek = noop_llseek,
-};
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-static void
-virtual_gpio_init(void)
-{
- reg_gio_rw_intr_cfg intr_cfg;
- reg_gio_rw_intr_mask intr_mask;
- unsigned short shadow;
-
- shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */
- shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT;
- i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow));
-
- /* Set interrupt mask and on what state the interrupt shall trigger.
- * For virtual gpio the interrupt shall trigger on logic '0'.
- */
- intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg);
- intr_mask = REG_RD(gio, regi_gio, rw_intr_mask);
-
- switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) {
- case 0:
- intr_cfg.pa0 = regk_gio_lo;
- intr_mask.pa0 = regk_gio_yes;
- break;
- case 1:
- intr_cfg.pa1 = regk_gio_lo;
- intr_mask.pa1 = regk_gio_yes;
- break;
- case 2:
- intr_cfg.pa2 = regk_gio_lo;
- intr_mask.pa2 = regk_gio_yes;
- break;
- case 3:
- intr_cfg.pa3 = regk_gio_lo;
- intr_mask.pa3 = regk_gio_yes;
- break;
- case 4:
- intr_cfg.pa4 = regk_gio_lo;
- intr_mask.pa4 = regk_gio_yes;
- break;
- case 5:
- intr_cfg.pa5 = regk_gio_lo;
- intr_mask.pa5 = regk_gio_yes;
- break;
- case 6:
- intr_cfg.pa6 = regk_gio_lo;
- intr_mask.pa6 = regk_gio_yes;
- break;
- case 7:
- intr_cfg.pa7 = regk_gio_lo;
- intr_mask.pa7 = regk_gio_yes;
- break;
- }
-
- REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg);
- REG_WR(gio, regi_gio, rw_intr_mask, intr_mask);
-
- gpio_pa_low_alarms |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN);
- gpio_some_alarms = 1;
-}
-#endif
-
-/* main driver initialization routine, called from mem.c */
-
-static __init int
-gpio_init(void)
-{
- int res;
-
- /* do the formalities */
-
- res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops);
- if (res < 0) {
- printk(KERN_ERR "gpio: couldn't get a major number.\n");
- return res;
- }
-
- /* Clear all leds */
- CRIS_LED_NETWORK_GRP0_SET(0);
- CRIS_LED_NETWORK_GRP1_SET(0);
- CRIS_LED_ACTIVE_SET(0);
- CRIS_LED_DISK_READ(0);
- CRIS_LED_DISK_WRITE(0);
-
- printk(KERN_INFO "ETRAX FS GPIO driver v2.5, (c) 2003-2007 "
- "Axis Communications AB\n");
- /* We call etrax_gpio_wake_up_check() from timer interrupt */
- if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt,
- IRQF_SHARED, "gpio poll", &alarmlist))
- printk(KERN_ERR "timer0 irq for gpio\n");
-
- if (request_irq(GIO_INTR_VECT, gpio_pa_interrupt,
- IRQF_SHARED, "gpio PA", &alarmlist))
- printk(KERN_ERR "PA irq for gpio\n");
-
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- virtual_gpio_init();
-#endif
-
- return res;
-}
-
-/* this makes sure that gpio_init is called during kernel boot */
-
-module_init(gpio_init);
diff --git a/arch/cris/arch-v32/kernel/crisksyms.c b/arch/cris/arch-v32/kernel/crisksyms.c
index bde8d1a10cad..b0566350a840 100644
--- a/arch/cris/arch-v32/kernel/crisksyms.c
+++ b/arch/cris/arch-v32/kernel/crisksyms.c
@@ -3,7 +3,6 @@
#include <arch/dma.h>
#include <arch/intmem.h>
#include <mach/pinmux.h>
-#include <arch/io.h>
/* Functions for allocating DMA channels */
EXPORT_SYMBOL(crisv32_request_dma);
@@ -20,8 +19,6 @@ EXPORT_SYMBOL(crisv32_pinmux_alloc);
EXPORT_SYMBOL(crisv32_pinmux_alloc_fixed);
EXPORT_SYMBOL(crisv32_pinmux_dealloc);
EXPORT_SYMBOL(crisv32_pinmux_dealloc_fixed);
-EXPORT_SYMBOL(crisv32_io_get_name);
-EXPORT_SYMBOL(crisv32_io_get);
/* Functions masking/unmasking interrupts */
EXPORT_SYMBOL(crisv32_mask_irq);
diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c
index 02e33ebe51ec..d2f3f9c37102 100644
--- a/arch/cris/arch-v32/kernel/debugport.c
+++ b/arch/cris/arch-v32/kernel/debugport.c
@@ -77,8 +77,6 @@ static struct dbg_port *port =
&ports[2];
#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
&ports[3];
-#elif defined(CONFIG_ETRAX_DEBUG_PORT4)
- &ports[4];
#else
NULL;
#endif
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S
index 74a66e0e3777..ea6366800df7 100644
--- a/arch/cris/arch-v32/kernel/head.S
+++ b/arch/cris/arch-v32/kernel/head.S
@@ -292,11 +292,7 @@ _no_romfs_in_flash:
;; For cramfs, partition starts with magic and length.
;; For jffs2, a jhead is prepended which contains with magic and length.
;; The jhead is not part of the jffs2 partition however.
-#ifndef CONFIG_ETRAXFS_SIM
move.d __bss_start, $r0
-#else
- move.d __end, $r0
-#endif
move.d [$r0], $r1
cmp.d CRAMFS_MAGIC, $r1 ; cramfs magic?
beq 2f ; yes, jump
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index 6a881e0e92b4..6de8db67cb09 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -37,7 +37,7 @@
#define IGNOREMASK (1 << (SER0_INTR_VECT - FIRST_IRQ))
#elif defined(CONFIG_ETRAX_KGDB_PORT1)
#define IGNOREMASK (1 << (SER1_INTR_VECT - FIRST_IRQ))
-#elif defined(CONFIG_ETRAX_KGB_PORT2)
+#elif defined(CONFIG_ETRAX_KGDB_PORT2)
#define IGNOREMASK (1 << (SER2_INTR_VECT - FIRST_IRQ))
#elif defined(CONFIG_ETRAX_KGDB_PORT3)
#define IGNOREMASK (1 << (SER3_INTR_VECT - FIRST_IRQ))
@@ -464,14 +464,14 @@ init_IRQ(void)
etrax_irv->v[i] = weird_irq;
np = of_find_compatible_node(NULL, NULL, "axis,crisv32-intc");
- domain = irq_domain_add_legacy(np, NR_IRQS - FIRST_IRQ,
+ domain = irq_domain_add_legacy(np, NBR_INTR_VECT - FIRST_IRQ,
FIRST_IRQ, FIRST_IRQ,
&crisv32_irq_ops, NULL);
BUG_ON(!domain);
irq_set_default_host(domain);
of_node_put(np);
- for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
+ for (i = FIRST_IRQ, j = 0; j < NBR_INTR_VECT; i++, j++) {
set_exception_vector(i, interrupt[j]);
}
diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c
index b06813aeb120..e0fdea706eca 100644
--- a/arch/cris/arch-v32/kernel/kgdb.c
+++ b/arch/cris/arch-v32/kernel/kgdb.c
@@ -384,19 +384,11 @@ int getDebugChar(void);
/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */
void putDebugChar(int val);
-/* Returns the integer equivalent of a hexadecimal character. */
-static int hex(char ch);
-
/* Convert the memory, pointed to by mem into hexadecimal representation.
Put the result in buf, and return a pointer to the last character
in buf (null). */
static char *mem2hex(char *buf, unsigned char *mem, int count);
-/* Convert the array, in hexadecimal representation, pointed to by buf into
- binary representation. Put the result in mem, and return a pointer to
- the character after the last byte written. */
-static unsigned char *hex2mem(unsigned char *mem, char *buf, int count);
-
/* Put the content of the array, in binary representation, pointed to by buf
into memory pointed to by mem, and return a pointer to
the character after the last byte written. */
@@ -449,7 +441,7 @@ static char output_buffer[BUFMAX];
/* Error and warning messages. */
enum error_type
{
- SUCCESS, E01, E02, E03, E04, E05, E06,
+ SUCCESS, E01, E02, E03, E04, E05, E06, E07, E08
};
static char *error_message[] =
@@ -461,6 +453,8 @@ static char *error_message[] =
"E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.",
"E05 Change register content - P - the register is not implemented..",
"E06 Change memory content - M - internal error.",
+ "E07 Change register content - P - the register is not stored on the stack",
+ "E08 Invalid parameter"
};
/********************************** Breakpoint *******************************/
@@ -539,7 +533,7 @@ gdb_cris_strtol(const char *s, char **endptr, int base)
/********************************* Register image ****************************/
/* Write a value to a specified register in the register image of the current
- thread. Returns status code SUCCESS, E02 or E05. */
+ thread. Returns status code SUCCESS, E02, E05 or E08. */
static int
write_register(int regno, char *val)
{
@@ -547,8 +541,9 @@ write_register(int regno, char *val)
if (regno >= R0 && regno <= ACR) {
/* Consecutive 32-bit registers. */
- hex2mem((unsigned char *)&reg.r0 + (regno - R0) * sizeof(unsigned int),
- val, sizeof(unsigned int));
+ if (hex2bin((unsigned char *)&reg.r0 + (regno - R0) * sizeof(unsigned int),
+ val, sizeof(unsigned int)))
+ status = E08;
} else if (regno == BZ || regno == VR || regno == WZ || regno == DZ) {
/* Read-only registers. */
@@ -557,16 +552,19 @@ write_register(int regno, char *val)
} else if (regno == PID) {
/* 32-bit register. (Even though we already checked SRS and WZ, we cannot
combine this with the EXS - SPC write since SRS and WZ have different size.) */
- hex2mem((unsigned char *)&reg.pid, val, sizeof(unsigned int));
+ if (hex2bin((unsigned char *)&reg.pid, val, sizeof(unsigned int)))
+ status = E08;
} else if (regno == SRS) {
/* 8-bit register. */
- hex2mem((unsigned char *)&reg.srs, val, sizeof(unsigned char));
+ if (hex2bin((unsigned char *)&reg.srs, val, sizeof(unsigned char)))
+ status = E08;
} else if (regno >= EXS && regno <= SPC) {
/* Consecutive 32-bit registers. */
- hex2mem((unsigned char *)&reg.exs + (regno - EXS) * sizeof(unsigned int),
- val, sizeof(unsigned int));
+ if (hex2bin((unsigned char *)&reg.exs + (regno - EXS) * sizeof(unsigned int),
+ val, sizeof(unsigned int)))
+ status = E08;
} else if (regno == PC) {
/* Pseudo-register. Treat as read-only. */
@@ -574,7 +572,9 @@ write_register(int regno, char *val)
} else if (regno >= S0 && regno <= S15) {
/* 32-bit registers. */
- hex2mem((unsigned char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int), val, sizeof(unsigned int));
+ if (hex2bin((unsigned char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int),
+ val, sizeof(unsigned int)))
+ status = E08;
} else {
/* Non-existing register. */
status = E05;
@@ -630,19 +630,6 @@ read_register(char regno, unsigned int *valptr)
}
/********************************** Packet I/O ******************************/
-/* Returns the integer equivalent of a hexadecimal character. */
-static int
-hex(char ch)
-{
- if ((ch >= 'a') && (ch <= 'f'))
- return (ch - 'a' + 10);
- if ((ch >= '0') && (ch <= '9'))
- return (ch - '0');
- if ((ch >= 'A') && (ch <= 'F'))
- return (ch - 'A' + 10);
- return -1;
-}
-
/* Convert the memory, pointed to by mem into hexadecimal representation.
Put the result in buf, and return a pointer to the last character
in buf (null). */
@@ -689,22 +676,6 @@ mem2hex_nbo(char *buf, unsigned char *mem, int count)
return buf;
}
-/* Convert the array, in hexadecimal representation, pointed to by buf into
- binary representation. Put the result in mem, and return a pointer to
- the character after the last byte written. */
-static unsigned char*
-hex2mem(unsigned char *mem, char *buf, int count)
-{
- int i;
- unsigned char ch;
- for (i = 0; i < count; i++) {
- ch = hex (*buf++) << 4;
- ch = ch + hex (*buf++);
- *mem++ = ch;
- }
- return mem;
-}
-
/* Put the content of the array, in binary representation, pointed to by buf
into memory pointed to by mem, and return a pointer to the character after
the last byte written.
@@ -763,8 +734,8 @@ getpacket(char *buffer)
buffer[count] = 0;
if (ch == '#') {
- xmitcsum = hex(getDebugChar()) << 4;
- xmitcsum += hex(getDebugChar());
+ xmitcsum = hex_to_bin(getDebugChar()) << 4;
+ xmitcsum += hex_to_bin(getDebugChar());
if (checksum != xmitcsum) {
/* Wrong checksum */
putDebugChar('-');
@@ -1304,14 +1275,17 @@ handle_exception(int sigval)
/* Write registers. GXX..XX
Each byte of register data is described by two hex digits.
Success: OK
- Failure: void. */
+ Failure: E08. */
/* General and special registers. */
- hex2mem((char *)&reg, &input_buffer[1], sizeof(registers));
+ if (hex2bin((char *)&reg, &input_buffer[1], sizeof(registers)))
+ gdb_cris_strcpy(output_buffer, error_message[E08]);
/* Support registers. */
- hex2mem((char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)),
+ else if (hex2bin((char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)),
&input_buffer[1] + sizeof(registers),
- 16 * sizeof(unsigned int));
- gdb_cris_strcpy(output_buffer, "OK");
+ 16 * sizeof(unsigned int)))
+ gdb_cris_strcpy(output_buffer, error_message[E08]);
+ else
+ gdb_cris_strcpy(output_buffer, "OK");
break;
case 'P':
@@ -1338,6 +1312,10 @@ handle_exception(int sigval)
/* Do not support non-existing registers. */
gdb_cris_strcpy(output_buffer, error_message[E05]);
break;
+ case E08:
+ /* Invalid parameter. */
+ gdb_cris_strcpy(output_buffer, error_message[E08]);
+ break;
default:
/* Valid register number. */
gdb_cris_strcpy(output_buffer, "OK");
@@ -1380,7 +1358,7 @@ handle_exception(int sigval)
AA..AA is the start address, LLLL is the number of bytes, and
XX..XX is the hexadecimal data.
Success: OK
- Failure: void. */
+ Failure: E08. */
{
char *lenptr;
char *dataptr;
@@ -1389,13 +1367,15 @@ handle_exception(int sigval)
int len = gdb_cris_strtol(lenptr+1, &dataptr, 16);
if (*lenptr == ',' && *dataptr == ':') {
if (input_buffer[0] == 'M') {
- hex2mem(addr, dataptr + 1, len);
+ if (hex2bin(addr, dataptr + 1, len))
+ gdb_cris_strcpy(output_buffer, error_message[E08]);
+ else
+ gdb_cris_strcpy(output_buffer, "OK");
} else /* X */ {
bin2mem(addr, dataptr + 1, len);
+ gdb_cris_strcpy(output_buffer, "OK");
}
- gdb_cris_strcpy(output_buffer, "OK");
- }
- else {
+ } else {
gdb_cris_strcpy(output_buffer, error_message[E06]);
}
}
diff --git a/arch/cris/arch-v32/kernel/setup.c b/arch/cris/arch-v32/kernel/setup.c
index cd1865d68b2e..fe50287aa928 100644
--- a/arch/cris/arch-v32/kernel/setup.c
+++ b/arch/cris/arch-v32/kernel/setup.c
@@ -129,10 +129,6 @@ static struct i2c_board_info __initdata i2c_info[] = {
#ifdef CONFIG_RTC_DRV_PCF8563
{I2C_BOARD_INFO("pcf8563", 0x51)},
#endif
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- {I2C_BOARD_INFO("vgpio", 0x20)},
- {I2C_BOARD_INFO("vgpio", 0x21)},
-#endif
{I2C_BOARD_INFO("pca9536", 0x41)},
{I2C_BOARD_INFO("fnp300", 0x40)},
{I2C_BOARD_INFO("fnp300", 0x42)},
@@ -146,10 +142,6 @@ static struct i2c_board_info __initdata i2c_info2[] = {
{I2C_BOARD_INFO("tmp100", 0x4C)},
{I2C_BOARD_INFO("tmp100", 0x4D)},
{I2C_BOARD_INFO("tmp100", 0x4E)},
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
- {I2C_BOARD_INFO("vgpio", 0x20)},
- {I2C_BOARD_INFO("vgpio", 0x21)},
-#endif
{I2C_BOARD_INFO("pca9536", 0x41)},
{I2C_BOARD_INFO("fnp300", 0x40)},
{I2C_BOARD_INFO("fnp300", 0x42)},
diff --git a/arch/cris/arch-v32/mach-a3/Makefile b/arch/cris/arch-v32/mach-a3/Makefile
index 18a227196a41..0cc6eebacbed 100644
--- a/arch/cris/arch-v32/mach-a3/Makefile
+++ b/arch/cris/arch-v32/mach-a3/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-obj-y := dma.o pinmux.o io.o arbiter.o
+obj-y := dma.o pinmux.o arbiter.o
clean:
diff --git a/arch/cris/arch-v32/mach-a3/io.c b/arch/cris/arch-v32/mach-a3/io.c
deleted file mode 100644
index 090ceb99ef0b..000000000000
--- a/arch/cris/arch-v32/mach-a3/io.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Helper functions for I/O pins.
- *
- * Copyright (c) 2005-2007 Axis Communications AB.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#include <mach/pinmux.h>
-#include <hwregs/gio_defs.h>
-
-struct crisv32_ioport crisv32_ioports[] = {
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din),
- 32
- },
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din),
- 32
- },
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din),
- 16
- },
-};
-
-#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports)
-
-struct crisv32_iopin crisv32_led_net0_green;
-struct crisv32_iopin crisv32_led_net0_red;
-struct crisv32_iopin crisv32_led2_green;
-struct crisv32_iopin crisv32_led2_red;
-struct crisv32_iopin crisv32_led3_green;
-struct crisv32_iopin crisv32_led3_red;
-
-/* Dummy port used when green LED and red LED is on the same bit */
-static unsigned long io_dummy;
-static struct crisv32_ioport dummy_port = {
- &io_dummy,
- &io_dummy,
- &io_dummy,
- 32
-};
-static struct crisv32_iopin dummy_led = {
- &dummy_port,
- 0
-};
-
-static int __init crisv32_io_init(void)
-{
- int ret = 0;
-
- u32 i;
-
- /* Locks *should* be dynamically initialized. */
- for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++)
- spin_lock_init(&crisv32_ioports[i].lock);
- spin_lock_init(&dummy_port.lock);
-
- /* Initialize LEDs */
-#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO))
- ret += crisv32_io_get_name(&crisv32_led_net0_green,
- CONFIG_ETRAX_LED_G_NET0);
- crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out);
- if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) {
- ret += crisv32_io_get_name(&crisv32_led_net0_red,
- CONFIG_ETRAX_LED_R_NET0);
- crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out);
- } else
- crisv32_led_net0_red = dummy_led;
-#endif
-
- ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G);
- ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R);
- ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G);
- ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R);
-
- crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
-
- return ret;
-}
-
-__initcall(crisv32_io_init);
-
-int crisv32_io_get(struct crisv32_iopin *iopin,
- unsigned int port, unsigned int pin)
-{
- if (port > NBR_OF_PORTS)
- return -EINVAL;
- if (port > crisv32_ioports[port].pin_count)
- return -EINVAL;
-
- iopin->bit = 1 << pin;
- iopin->port = &crisv32_ioports[port];
-
- if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
- return -EIO;
-
- return 0;
-}
-
-int crisv32_io_get_name(struct crisv32_iopin *iopin, const char *name)
-{
- int port;
- int pin;
-
- if (toupper(*name) == 'P')
- name++;
-
- if (toupper(*name) < 'A' || toupper(*name) > 'E')
- return -EINVAL;
-
- port = toupper(*name) - 'A';
- name++;
- pin = simple_strtoul(name, NULL, 10);
-
- if (pin < 0 || pin > crisv32_ioports[port].pin_count)
- return -EINVAL;
-
- iopin->bit = 1 << pin;
- iopin->port = &crisv32_ioports[port];
-
- if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
- return -EIO;
-
- return 0;
-}
-
-#ifdef CONFIG_PCI
-/* PCI I/O access stuff */
-struct cris_io_operations *cris_iops = NULL;
-EXPORT_SYMBOL(cris_iops);
-#endif
-
diff --git a/arch/cris/arch-v32/mach-fs/Kconfig b/arch/cris/arch-v32/mach-fs/Kconfig
index 774de82abef6..7d1ab972bc0f 100644
--- a/arch/cris/arch-v32/mach-fs/Kconfig
+++ b/arch/cris/arch-v32/mach-fs/Kconfig
@@ -192,25 +192,6 @@ config ETRAX_DEF_GIO_PE_OUT
Configures the initial data for the general port E bits. Most
products should use 00000 here.
-config ETRAX_DEF_GIO_PV_OE
- hex "GIO_PV_OE"
- depends on ETRAX_VIRTUAL_GPIO
- default "0000"
- help
- Configures the direction of virtual general port V bits. 1 is out,
- 0 is in. This is often totally different depending on the product
- used. These bits are used for all kinds of stuff. If you don't know
- what to use, it is always safe to put all as inputs, although
- floating inputs isn't good.
-
-config ETRAX_DEF_GIO_PV_OUT
- hex "GIO_PV_OUT"
- depends on ETRAX_VIRTUAL_GPIO
- default "0000"
- help
- Configures the initial data for the virtual general port V bits.
- Most products should use 0000 here.
-
endmenu
endif
diff --git a/arch/cris/arch-v32/mach-fs/Makefile b/arch/cris/arch-v32/mach-fs/Makefile
index 18a227196a41..0cc6eebacbed 100644
--- a/arch/cris/arch-v32/mach-fs/Makefile
+++ b/arch/cris/arch-v32/mach-fs/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-obj-y := dma.o pinmux.o io.o arbiter.o
+obj-y := dma.o pinmux.o arbiter.o
clean:
diff --git a/arch/cris/arch-v32/mach-fs/io.c b/arch/cris/arch-v32/mach-fs/io.c
deleted file mode 100644
index a6958661fa8e..000000000000
--- a/arch/cris/arch-v32/mach-fs/io.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Helper functions for I/O pins.
- *
- * Copyright (c) 2004-2007 Axis Communications AB.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#include <mach/pinmux.h>
-#include <hwregs/gio_defs.h>
-
-#ifndef DEBUG
-#define DEBUG(x)
-#endif
-
-struct crisv32_ioport crisv32_ioports[] = {
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din),
- 8
- },
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din),
- 18
- },
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din),
- 18
- },
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pd_din),
- 18
- },
- {
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_oe),
- (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_dout),
- (unsigned long *)REG_ADDR(gio, regi_gio, r_pe_din),
- 18
- }
-};
-
-#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports)
-
-struct crisv32_iopin crisv32_led_net0_green;
-struct crisv32_iopin crisv32_led_net0_red;
-struct crisv32_iopin crisv32_led_net1_green;
-struct crisv32_iopin crisv32_led_net1_red;
-struct crisv32_iopin crisv32_led2_green;
-struct crisv32_iopin crisv32_led2_red;
-struct crisv32_iopin crisv32_led3_green;
-struct crisv32_iopin crisv32_led3_red;
-
-/* Dummy port used when green LED and red LED is on the same bit */
-static unsigned long io_dummy;
-static struct crisv32_ioport dummy_port = {
- &io_dummy,
- &io_dummy,
- &io_dummy,
- 18
-};
-static struct crisv32_iopin dummy_led = {
- &dummy_port,
- 0
-};
-
-static int __init crisv32_io_init(void)
-{
- int ret = 0;
-
- u32 i;
-
- /* Locks *should* be dynamically initialized. */
- for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++)
- spin_lock_init(&crisv32_ioports[i].lock);
- spin_lock_init(&dummy_port.lock);
-
- /* Initialize LEDs */
-#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO))
- ret +=
- crisv32_io_get_name(&crisv32_led_net0_green,
- CONFIG_ETRAX_LED_G_NET0);
- crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out);
- if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) {
- ret +=
- crisv32_io_get_name(&crisv32_led_net0_red,
- CONFIG_ETRAX_LED_R_NET0);
- crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out);
- } else
- crisv32_led_net0_red = dummy_led;
-#endif
-
-#ifdef CONFIG_ETRAX_NBR_LED_GRP_TWO
- ret +=
- crisv32_io_get_name(&crisv32_led_net1_green,
- CONFIG_ETRAX_LED_G_NET1);
- crisv32_io_set_dir(&crisv32_led_net1_green, crisv32_io_dir_out);
- if (strcmp(CONFIG_ETRAX_LED_G_NET1, CONFIG_ETRAX_LED_R_NET1)) {
- crisv32_io_get_name(&crisv32_led_net1_red,
- CONFIG_ETRAX_LED_R_NET1);
- crisv32_io_set_dir(&crisv32_led_net1_red, crisv32_io_dir_out);
- } else
- crisv32_led_net1_red = dummy_led;
-#endif
-
- ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G);
- ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R);
- ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G);
- ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R);
-
- crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
- crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
-
- return ret;
-}
-
-__initcall(crisv32_io_init);
-
-int crisv32_io_get(struct crisv32_iopin *iopin,
- unsigned int port, unsigned int pin)
-{
- if (port > NBR_OF_PORTS)
- return -EINVAL;
- if (port > crisv32_ioports[port].pin_count)
- return -EINVAL;
-
- iopin->bit = 1 << pin;
- iopin->port = &crisv32_ioports[port];
-
- /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */
- /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */
- if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio))
- return -EIO;
- DEBUG(printk(KERN_DEBUG "crisv32_io_get: Allocated pin %d on port %d\n",
- pin, port));
-
- return 0;
-}
-
-int crisv32_io_get_name(struct crisv32_iopin *iopin, const char *name)
-{
- int port;
- int pin;
-
- if (toupper(*name) == 'P')
- name++;
-
- if (toupper(*name) < 'A' || toupper(*name) > 'E')
- return -EINVAL;
-
- port = toupper(*name) - 'A';
- name++;
- pin = simple_strtoul(name, NULL, 10);
-
- if (pin < 0 || pin > crisv32_ioports[port].pin_count)
- return -EINVAL;
-
- iopin->bit = 1 << pin;
- iopin->port = &crisv32_ioports[port];
-
- /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */
- /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */
- if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio))
- return -EIO;
-
- DEBUG(printk(KERN_DEBUG
- "crisv32_io_get_name: Allocated pin %d on port %d\n",
- pin, port));
-
- return 0;
-}
-
-#ifdef CONFIG_PCI
-/* PCI I/O access stuff */
-struct cris_io_operations *cris_iops = NULL;
-EXPORT_SYMBOL(cris_iops);
-#endif
diff --git a/arch/cris/boot/dts/artpec3.dtsi b/arch/cris/boot/dts/artpec3.dtsi
new file mode 100644
index 000000000000..be15be67b653
--- /dev/null
+++ b/arch/cris/boot/dts/artpec3.dtsi
@@ -0,0 +1,46 @@
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ model = "axis,crisv32";
+ reg = <0>;
+ };
+ };
+
+ soc {
+ compatible = "simple-bus";
+ model = "artpec3";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ intc: interrupt-controller {
+ compatible = "axis,crisv32-intc";
+ reg = <0xb002a000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ gio: gpio@b0020000 {
+ compatible = "axis,artpec3-gio";
+ reg = <0xb0020000 0x1000>;
+ interrupts = <61>;
+ gpio-controller;
+ #gpio-cells = <3>;
+ };
+
+ serial@b003e000 {
+ compatible = "axis,etraxfs-uart";
+ reg = <0xb003e000 0x1000>;
+ interrupts = <64>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/cris/boot/dts/dev88.dts b/arch/cris/boot/dts/dev88.dts
index 4fa5a3f9d0ec..b9a230d10874 100644
--- a/arch/cris/boot/dts/dev88.dts
+++ b/arch/cris/boot/dts/dev88.dts
@@ -1,5 +1,7 @@
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+
/include/ "etraxfs.dtsi"
/ {
@@ -15,4 +17,51 @@
status = "okay";
};
};
+
+ spi {
+ compatible = "spi-gpio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-sck = <&gio 1 0 0xd>;
+ gpio-miso = <&gio 4 0 0xd>;
+ gpio-mosi = <&gio 0 0 0xd>;
+ cs-gpios = <&gio 3 0 0xd>;
+ num-chipselects = <1>;
+
+ temp-sensor@0 {
+ compatible = "ti,lm70";
+ reg = <0>;
+
+ spi-max-frequency = <100000>;
+ };
+ };
+
+ i2c {
+ compatible = "i2c-gpio";
+ gpios = <&gio 5 0 0xd>, <&gio 6 0 0xd>;
+ i2c-gpio,delay-us = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ network {
+ label = "network";
+ gpios = <&gio 2 GPIO_ACTIVE_LOW 0xa>;
+ };
+
+ status {
+ label = "status";
+ gpios = <&gio 3 GPIO_ACTIVE_LOW 0xa>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
};
diff --git a/arch/cris/boot/dts/etraxfs.dtsi b/arch/cris/boot/dts/etraxfs.dtsi
index 909bcedc3565..bf1b8582d4d8 100644
--- a/arch/cris/boot/dts/etraxfs.dtsi
+++ b/arch/cris/boot/dts/etraxfs.dtsi
@@ -28,6 +28,14 @@
#interrupt-cells = <1>;
};
+ gio: gpio@b001a000 {
+ compatible = "axis,etraxfs-gio";
+ reg = <0xb001a000 0x1000>;
+ interrupts = <50>;
+ gpio-controller;
+ #gpio-cells = <3>;
+ };
+
serial@b00260000 {
compatible = "axis,etraxfs-uart";
reg = <0xb0026000 0x1000>;
diff --git a/arch/cris/boot/dts/include/dt-bindings b/arch/cris/boot/dts/include/dt-bindings
new file mode 120000
index 000000000000..08c00e4972fa
--- /dev/null
+++ b/arch/cris/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings \ No newline at end of file
diff --git a/arch/cris/boot/dts/p1343.dts b/arch/cris/boot/dts/p1343.dts
new file mode 100644
index 000000000000..fab7bdbd0f15
--- /dev/null
+++ b/arch/cris/boot/dts/p1343.dts
@@ -0,0 +1,76 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/include/ "artpec3.dtsi"
+
+/ {
+ model = "Axis P1343 Network Camera";
+ compatible = "axis,p1343";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ soc {
+ uart0: serial@b003e000 {
+ status = "okay";
+ };
+ };
+
+ i2c {
+ compatible = "i2c-gpio";
+ gpios = <&gio 3 0 0xa>, <&gio 2 0 0xa>;
+ i2c-gpio,delay-us = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ status_green {
+ label = "status:green";
+ gpios = <&gio 0 GPIO_ACTIVE_LOW 0xc>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ status_red {
+ label = "status:red";
+ gpios = <&gio 1 GPIO_ACTIVE_LOW 0xc>;
+ };
+
+ network_green {
+ label = "network:green";
+ gpios = <&gio 2 GPIO_ACTIVE_LOW 0xc>;
+ };
+
+ network_red {
+ label = "network:red";
+ gpios = <&gio 3 GPIO_ACTIVE_LOW 0xc>;
+ };
+
+ power_red {
+ label = "power:red";
+ gpios = <&gio 4 GPIO_ACTIVE_LOW 0xc>;
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ activity-button@0 {
+ label = "Activity Button";
+ linux,code = <KEY_FN>;
+ gpios = <&gio 13 GPIO_ACTIVE_LOW 0xd>;
+ };
+ };
+};
diff --git a/arch/cris/boot/rescue/head_v10.S b/arch/cris/boot/rescue/head_v10.S
index af55df0994b3..1c05492f3eb2 100644
--- a/arch/cris/boot/rescue/head_v10.S
+++ b/arch/cris/boot/rescue/head_v10.S
@@ -281,9 +281,6 @@ wait_ser:
#ifdef CONFIG_ETRAX_PB_LEDS
move.b $r2, [R_PORT_PB_DATA]
#endif
-#ifdef CONFIG_ETRAX_90000000_LEDS
- move.b $r2, [0x90000000]
-#endif
#endif
;; check if we got something on the serial port
diff --git a/arch/cris/include/arch-v32/arch/io.h b/arch/cris/include/arch-v32/arch/io.h
deleted file mode 100644
index adc5484351bf..000000000000
--- a/arch/cris/include/arch-v32/arch/io.h
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _ASM_ARCH_CRIS_IO_H
-#define _ASM_ARCH_CRIS_IO_H
-
-#include <linux/spinlock.h>
-#include <hwregs/reg_map.h>
-#include <hwregs/reg_rdwr.h>
-#include <hwregs/gio_defs.h>
-
-enum crisv32_io_dir
-{
- crisv32_io_dir_in = 0,
- crisv32_io_dir_out = 1
-};
-
-struct crisv32_ioport
-{
- volatile unsigned long *oe;
- volatile unsigned long *data;
- volatile unsigned long *data_in;
- unsigned int pin_count;
- spinlock_t lock;
-};
-
-struct crisv32_iopin
-{
- struct crisv32_ioport* port;
- int bit;
-};
-
-extern struct crisv32_ioport crisv32_ioports[];
-
-extern struct crisv32_iopin crisv32_led1_green;
-extern struct crisv32_iopin crisv32_led1_red;
-extern struct crisv32_iopin crisv32_led2_green;
-extern struct crisv32_iopin crisv32_led2_red;
-extern struct crisv32_iopin crisv32_led3_green;
-extern struct crisv32_iopin crisv32_led3_red;
-
-extern struct crisv32_iopin crisv32_led_net0_green;
-extern struct crisv32_iopin crisv32_led_net0_red;
-extern struct crisv32_iopin crisv32_led_net1_green;
-extern struct crisv32_iopin crisv32_led_net1_red;
-
-static inline void crisv32_io_set(struct crisv32_iopin *iopin, int val)
-{
- unsigned long flags;
- spin_lock_irqsave(&iopin->port->lock, flags);
-
- if (iopin->port->data) {
- if (val)
- *iopin->port->data |= iopin->bit;
- else
- *iopin->port->data &= ~iopin->bit;
- }
-
- spin_unlock_irqrestore(&iopin->port->lock, flags);
-}
-
-static inline void crisv32_io_set_dir(struct crisv32_iopin* iopin,
- enum crisv32_io_dir dir)
-{
- unsigned long flags;
- spin_lock_irqsave(&iopin->port->lock, flags);
-
- if (iopin->port->oe) {
- if (dir == crisv32_io_dir_in)
- *iopin->port->oe &= ~iopin->bit;
- else
- *iopin->port->oe |= iopin->bit;
- }
-
- spin_unlock_irqrestore(&iopin->port->lock, flags);
-}
-
-static inline int crisv32_io_rd(struct crisv32_iopin* iopin)
-{
- return ((*iopin->port->data_in & iopin->bit) ? 1 : 0);
-}
-
-int crisv32_io_get(struct crisv32_iopin* iopin,
- unsigned int port, unsigned int pin);
-int crisv32_io_get_name(struct crisv32_iopin* iopin,
- const char *name);
-
-#define CRIS_LED_OFF 0x00
-#define CRIS_LED_GREEN 0x01
-#define CRIS_LED_RED 0x02
-#define CRIS_LED_ORANGE (CRIS_LED_GREEN | CRIS_LED_RED)
-
-#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO))
-#define CRIS_LED_NETWORK_GRP0_SET(x) \
- do { \
- CRIS_LED_NETWORK_GRP0_SET_G((x) & CRIS_LED_GREEN); \
- CRIS_LED_NETWORK_GRP0_SET_R((x) & CRIS_LED_RED); \
- } while (0)
-#else
-#define CRIS_LED_NETWORK_GRP0_SET(x) while (0) {}
-#endif
-
-#define CRIS_LED_NETWORK_GRP0_SET_G(x) \
- crisv32_io_set(&crisv32_led_net0_green, !(x));
-
-#define CRIS_LED_NETWORK_GRP0_SET_R(x) \
- crisv32_io_set(&crisv32_led_net0_red, !(x));
-
-#if defined(CONFIG_ETRAX_NBR_LED_GRP_TWO)
-#define CRIS_LED_NETWORK_GRP1_SET(x) \
- do { \
- CRIS_LED_NETWORK_GRP1_SET_G((x) & CRIS_LED_GREEN); \
- CRIS_LED_NETWORK_GRP1_SET_R((x) & CRIS_LED_RED); \
- } while (0)
-#else
-#define CRIS_LED_NETWORK_GRP1_SET(x) while (0) {}
-#endif
-
-#define CRIS_LED_NETWORK_GRP1_SET_G(x) \
- crisv32_io_set(&crisv32_led_net1_green, !(x));
-
-#define CRIS_LED_NETWORK_GRP1_SET_R(x) \
- crisv32_io_set(&crisv32_led_net1_red, !(x));
-
-#define CRIS_LED_ACTIVE_SET(x) \
- do { \
- CRIS_LED_ACTIVE_SET_G((x) & CRIS_LED_GREEN); \
- CRIS_LED_ACTIVE_SET_R((x) & CRIS_LED_RED); \
- } while (0)
-
-#define CRIS_LED_ACTIVE_SET_G(x) \
- crisv32_io_set(&crisv32_led2_green, !(x));
-#define CRIS_LED_ACTIVE_SET_R(x) \
- crisv32_io_set(&crisv32_led2_red, !(x));
-#define CRIS_LED_DISK_WRITE(x) \
- do{\
- crisv32_io_set(&crisv32_led3_green, !(x)); \
- crisv32_io_set(&crisv32_led3_red, !(x)); \
- }while(0)
-#define CRIS_LED_DISK_READ(x) \
- crisv32_io_set(&crisv32_led3_green, !(x));
-
-#endif
diff --git a/arch/cris/include/arch-v32/arch/irq.h b/arch/cris/include/arch-v32/arch/irq.h
index 0c1b4d3a34e7..8270a1bbfdb6 100644
--- a/arch/cris/include/arch-v32/arch/irq.h
+++ b/arch/cris/include/arch-v32/arch/irq.h
@@ -4,7 +4,7 @@
#include <hwregs/intr_vect.h>
/* Number of non-cpu interrupts. */
-#define NR_IRQS NBR_INTR_VECT /* Exceptions + IRQs */
+#define NR_IRQS (NBR_INTR_VECT + 256) /* Exceptions + IRQs */
#define FIRST_IRQ 0x31 /* Exception number for first IRQ */
#define NR_REAL_IRQS (NBR_INTR_VECT - FIRST_IRQ) /* IRQs */
#if NR_REAL_IRQS > 32
diff --git a/arch/cris/include/asm/eshlibld.h b/arch/cris/include/asm/eshlibld.h
index 10ce36cf79a9..70aa448256b0 100644
--- a/arch/cris/include/asm/eshlibld.h
+++ b/arch/cris/include/asm/eshlibld.h
@@ -45,8 +45,7 @@
assumed that we want to share code when debugging (exposes more
trouble). */
#ifndef SHARE_LIB_CORE
-# if (defined(__KERNEL__) || !defined(RELOC_DEBUG)) \
- && !defined(CONFIG_SHARE_SHLIB_CORE)
+# if (defined(__KERNEL__) || !defined(RELOC_DEBUG))
# define SHARE_LIB_CORE 0
# else
# define SHARE_LIB_CORE 1
diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h
index 752a3f45df60..cce8664d5dd6 100644
--- a/arch/cris/include/asm/io.h
+++ b/arch/cris/include/asm/io.h
@@ -2,7 +2,9 @@
#define _ASM_CRIS_IO_H
#include <asm/page.h> /* for __va, __pa */
+#ifdef CONFIG_ETRAX_ARCH_V10
#include <arch/io.h>
+#endif
#include <asm-generic/iomap.h>
#include <linux/kernel.h>
diff --git a/arch/cris/include/uapi/asm/etraxgpio.h b/arch/cris/include/uapi/asm/etraxgpio.h
index 461c089db765..c6e7d57c8b24 100644
--- a/arch/cris/include/uapi/asm/etraxgpio.h
+++ b/arch/cris/include/uapi/asm/etraxgpio.h
@@ -11,26 +11,6 @@
* g1-g7 and g25-g31 is both input and outputs but on different pins
* Also note that some bits change pins depending on what interfaces
* are enabled.
- *
- * For ETRAX FS (CONFIG_ETRAXFS):
- * /dev/gpioa minor 0, 8 bit GPIO, each bit can change direction
- * /dev/gpiob minor 1, 18 bit GPIO, each bit can change direction
- * /dev/gpioc minor 3, 18 bit GPIO, each bit can change direction
- * /dev/gpiod minor 4, 18 bit GPIO, each bit can change direction
- * /dev/gpioe minor 5, 18 bit GPIO, each bit can change direction
- * /dev/leds minor 2, Access to leds depending on kernelconfig
- *
- * For ARTPEC-3 (CONFIG_CRIS_MACH_ARTPEC3):
- * /dev/gpioa minor 0, 32 bit GPIO, each bit can change direction
- * /dev/gpiob minor 1, 32 bit GPIO, each bit can change direction
- * /dev/gpioc minor 3, 16 bit GPIO, each bit can change direction
- * /dev/gpiod minor 4, 32 bit GPIO, input only
- * /dev/leds minor 2, Access to leds depending on kernelconfig
- * /dev/pwm0 minor 16, PWM channel 0 on PA30
- * /dev/pwm1 minor 17, PWM channel 1 on PA31
- * /dev/pwm2 minor 18, PWM channel 2 on PB26
- * /dev/ppwm minor 19, PPWM channel
- *
*/
#ifndef _ASM_ETRAXGPIO_H
#define _ASM_ETRAXGPIO_H
@@ -40,52 +20,12 @@
#define ETRAXGPIO_IOCTYPE 43
/* etraxgpio _IOC_TYPE, bits 8 to 15 in ioctl cmd */
-#ifdef CONFIG_ETRAX_ARCH_V10
#define GPIO_MINOR_A 0
#define GPIO_MINOR_B 1
#define GPIO_MINOR_LEDS 2
#define GPIO_MINOR_G 3
#define GPIO_MINOR_LAST 3
#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST
-#endif
-
-#ifdef CONFIG_ETRAXFS
-#define GPIO_MINOR_A 0
-#define GPIO_MINOR_B 1
-#define GPIO_MINOR_LEDS 2
-#define GPIO_MINOR_C 3
-#define GPIO_MINOR_D 4
-#define GPIO_MINOR_E 5
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-#define GPIO_MINOR_V 6
-#define GPIO_MINOR_LAST 6
-#else
-#define GPIO_MINOR_LAST 5
-#endif
-#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST
-#endif
-
-#ifdef CONFIG_CRIS_MACH_ARTPEC3
-#define GPIO_MINOR_A 0
-#define GPIO_MINOR_B 1
-#define GPIO_MINOR_LEDS 2
-#define GPIO_MINOR_C 3
-#define GPIO_MINOR_D 4
-#ifdef CONFIG_ETRAX_VIRTUAL_GPIO
-#define GPIO_MINOR_V 6
-#define GPIO_MINOR_LAST 6
-#else
-#define GPIO_MINOR_LAST 4
-#endif
-#define GPIO_MINOR_FIRST_PWM 16
-#define GPIO_MINOR_PWM0 (GPIO_MINOR_FIRST_PWM+0)
-#define GPIO_MINOR_PWM1 (GPIO_MINOR_FIRST_PWM+1)
-#define GPIO_MINOR_PWM2 (GPIO_MINOR_FIRST_PWM+2)
-#define GPIO_MINOR_PPWM (GPIO_MINOR_FIRST_PWM+3)
-#define GPIO_MINOR_LAST_PWM GPIO_MINOR_PPWM
-#define GPIO_MINOR_LAST_REAL GPIO_MINOR_LAST_PWM
-#endif
-
/* supported ioctl _IOC_NR's */
@@ -139,101 +79,4 @@
#define IO_SETGET_OUTPUT 0x13 /* bits set in *arg is set to output, */
/* *arg updated with current output pins. */
-/* The following ioctl's are applicable to the PWM channels only */
-
-#define IO_PWM_SET_MODE 0x20
-
-enum io_pwm_mode {
- PWM_OFF = 0, /* disabled, deallocated */
- PWM_STANDARD = 1, /* 390 kHz, duty cycle 0..255/256 */
- PWM_FAST = 2, /* variable freq, w/ 10ns active pulse len */
- PWM_VARFREQ = 3, /* individually configurable high/low periods */
- PWM_SOFT = 4 /* software generated */
-};
-
-struct io_pwm_set_mode {
- enum io_pwm_mode mode;
-};
-
-/* Only for mode PWM_VARFREQ. Period lo/high set in increments of 10ns
- * from 10ns (value = 0) to 81920ns (value = 8191)
- * (Resulting frequencies range from 50 MHz (10ns + 10ns) down to
- * 6.1 kHz (81920ns + 81920ns) at 50% duty cycle, to 12.2 kHz at min/max duty
- * cycle (81920 + 10ns or 10ns + 81920ns, respectively).)
- */
-#define IO_PWM_SET_PERIOD 0x21
-
-struct io_pwm_set_period {
- unsigned int lo; /* 0..8191 */
- unsigned int hi; /* 0..8191 */
-};
-
-/* Only for modes PWM_STANDARD and PWM_FAST.
- * For PWM_STANDARD, set duty cycle of 390 kHz PWM output signal, from
- * 0 (value = 0) to 255/256 (value = 255).
- * For PWM_FAST, set duty cycle of PWM output signal from
- * 0% (value = 0) to 100% (value = 255). Output signal in this mode
- * is a 10ns pulse surrounded by a high or low level depending on duty
- * cycle (except for 0% and 100% which result in a constant output).
- * Resulting output frequency varies from 50 MHz at 50% duty cycle,
- * down to 390 kHz at min/max duty cycle.
- */
-#define IO_PWM_SET_DUTY 0x22
-
-struct io_pwm_set_duty {
- int duty; /* 0..255 */
-};
-
-/* Returns information about the latest PWM pulse.
- * lo: Length of the latest low period, in units of 10ns.
- * hi: Length of the latest high period, in units of 10ns.
- * cnt: Time since last detected edge, in units of 10ns.
- *
- * The input source to PWM is decied by IO_PWM_SET_INPUT_SRC.
- *
- * NOTE: All PWM devices is connected to the same input source.
- */
-#define IO_PWM_GET_PERIOD 0x23
-
-struct io_pwm_get_period {
- unsigned int lo;
- unsigned int hi;
- unsigned int cnt;
-};
-
-/* Sets the input source for the PWM input. For the src value see the
- * register description for gio:rw_pwm_in_cfg.
- *
- * NOTE: All PWM devices is connected to the same input source.
- */
-#define IO_PWM_SET_INPUT_SRC 0x24
-struct io_pwm_set_input_src {
- unsigned int src; /* 0..7 */
-};
-
-/* Sets the duty cycles in steps of 1/256, 0 = 0%, 255 = 100% duty cycle */
-#define IO_PPWM_SET_DUTY 0x25
-
-struct io_ppwm_set_duty {
- int duty; /* 0..255 */
-};
-
-/* Configuraton struct for the IO_PWMCLK_SET_CONFIG ioctl to configure
- * PWM capable gpio pins:
- */
-#define IO_PWMCLK_SETGET_CONFIG 0x26
-struct gpio_pwmclk_conf {
- unsigned int gpiopin; /* The pin number based on the opened device */
- unsigned int baseclk; /* The base clock to use, or sw will select one close*/
- unsigned int low; /* The number of low periods of the baseclk */
- unsigned int high; /* The number of high periods of the baseclk */
-};
-
-/* Examples:
- * To get a symmetric 12 MHz clock without knowing anything about the hardware:
- * baseclk = 12000000, low = 0, high = 0
- * To just get info of current setting:
- * baseclk = 0, low = 0, high = 0, the values will be updated by driver.
- */
-
#endif
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index e704f81f85cc..31b4bd288cad 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -18,7 +18,6 @@
#include <asm/pgtable.h>
#include <asm/fasttimer.h>
-extern unsigned long get_cmos_time(void);
extern void __Udiv(void);
extern void __Umod(void);
extern void __Div(void);
@@ -30,7 +29,6 @@ extern void __negdi2(void);
extern void iounmap(volatile void * __iomem);
/* Platform dependent support */
-EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(loops_per_usec);
/* Math functions */
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 7780d379522f..2dda6da71521 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -39,31 +39,6 @@
extern unsigned long loops_per_jiffy; /* init/main.c */
unsigned long loops_per_usec;
-int set_rtc_mmss(unsigned long nowtime)
-{
- D(printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime));
- return 0;
-}
-
-/* grab the time from the RTC chip */
-unsigned long get_cmos_time(void)
-{
- return 0;
-}
-
-
-int update_persistent_clock(struct timespec now)
-{
- return set_rtc_mmss(now.tv_sec);
-}
-
-void read_persistent_clock(struct timespec *ts)
-{
- ts->tv_sec = 0;
- ts->tv_nsec = 0;
-}
-
-
extern void cris_profile_sample(struct pt_regs* regs);
void
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index 99c96a5e6016..db73390568c8 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -11,7 +11,7 @@
-#define NR_syscalls 321 /* length of syscall table */
+#define NR_syscalls 322 /* length of syscall table */
/*
* The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
index 98e94e19a5a0..9038726e7d26 100644
--- a/arch/ia64/include/uapi/asm/unistd.h
+++ b/arch/ia64/include/uapi/asm/unistd.h
@@ -334,5 +334,6 @@
#define __NR_execveat 1342
#define __NR_userfaultfd 1343
#define __NR_membarrier 1344
+#define __NR_kcmp 1345
#endif /* _UAPI_ASM_IA64_UNISTD_H */
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 37cc7a65cd3e..dcd97f84d065 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1770,5 +1770,6 @@ sys_call_table:
data8 sys_execveat
data8 sys_userfaultfd
data8 sys_membarrier
+ data8 sys_kcmp // 1345
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/m68k/sun3/idprom.c b/arch/m68k/sun3/idprom.c
index c86ac37d1983..cfe9aa422343 100644
--- a/arch/m68k/sun3/idprom.c
+++ b/arch/m68k/sun3/idprom.c
@@ -125,8 +125,5 @@ void __init idprom_init(void)
display_system_type(idprom->id_machtype);
- printk("Ethernet address: %x:%x:%x:%x:%x:%x\n",
- idprom->id_ethaddr[0], idprom->id_ethaddr[1],
- idprom->id_ethaddr[2], idprom->id_ethaddr[3],
- idprom->id_ethaddr[4], idprom->id_ethaddr[5]);
+ printk("Ethernet address: %pM\n", idprom->id_ethaddr);
}
diff --git a/arch/mips/configs/pistachio_defconfig b/arch/mips/configs/pistachio_defconfig
index 642b50946943..8b7429127a1d 100644
--- a/arch/mips/configs/pistachio_defconfig
+++ b/arch/mips/configs/pistachio_defconfig
@@ -257,7 +257,6 @@ CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16
CONFIG_MMC_TEST=m
CONFIG_MMC_DW=y
-CONFIG_MMC_DW_IDMAC=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_RTC_CLASS=y
diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile
index 2e52cbd20ceb..7a584e0bf933 100644
--- a/arch/mips/mti-sead3/Makefile
+++ b/arch/mips/mti-sead3/Makefile
@@ -12,6 +12,4 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \
sead3-int.o sead3-platform.o sead3-reset.o \
sead3-setup.o sead3-time.o
-obj-y += leds-sead3.o
-
obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c
deleted file mode 100644
index c938ceeb8848..000000000000
--- a/arch/mips/mti-sead3/leds-sead3.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
- * Copyright (C) 2015 Imagination Technologies, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <asm/mips-boards/sead3-addr.h>
-
-static void sead3_pled_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- writel(value, (void __iomem *)SEAD3_CPLD_P_LED);
-}
-
-static void sead3_fled_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- writel(value, (void __iomem *)SEAD3_CPLD_F_LED);
-}
-
-static struct led_classdev sead3_pled = {
- .name = "sead3::pled",
- .brightness_set = sead3_pled_set,
- .flags = LED_CORE_SUSPENDRESUME,
-};
-
-static struct led_classdev sead3_fled = {
- .name = "sead3::fled",
- .brightness_set = sead3_fled_set,
- .flags = LED_CORE_SUSPENDRESUME,
-};
-
-static int sead3_led_probe(struct platform_device *pdev)
-{
- int ret;
-
- ret = led_classdev_register(&pdev->dev, &sead3_pled);
- if (ret < 0)
- return ret;
-
- ret = led_classdev_register(&pdev->dev, &sead3_fled);
- if (ret < 0)
- led_classdev_unregister(&sead3_pled);
-
- return ret;
-}
-
-static int sead3_led_remove(struct platform_device *pdev)
-{
- led_classdev_unregister(&sead3_pled);
- led_classdev_unregister(&sead3_fled);
- return 0;
-}
-
-static struct platform_driver sead3_led_driver = {
- .probe = sead3_led_probe,
- .remove = sead3_led_remove,
- .driver = {
- .name = "sead3-led",
- },
-};
-
-module_platform_driver(sead3_led_driver);
-
-MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
-MODULE_DESCRIPTION("SEAD3 LED driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 6bc0ee4b1070..2c041b535a64 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -111,7 +111,7 @@ CONFIG_SCSI_QLA_FC=m
CONFIG_SCSI_QLA_ISCSI=m
CONFIG_SCSI_LPFC=m
CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_ALUA=m
CONFIG_ATA=y
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 7991f37e5fe2..36871a4bfa54 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -114,7 +114,7 @@ CONFIG_SCSI_QLA_FC=m
CONFIG_SCSI_QLA_ISCSI=m
CONFIG_SCSI_LPFC=m
CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
CONFIG_SCSI_DH_ALUA=m
CONFIG_ATA=y
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
index 0dc42c5082b7..5f8229e24fe6 100644
--- a/arch/powerpc/include/asm/cache.h
+++ b/arch/powerpc/include/asm/cache.h
@@ -3,7 +3,6 @@
#ifdef __KERNEL__
-#include <asm/reg.h>
/* bytes per L1 cache line */
#if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
@@ -40,12 +39,6 @@ struct ppc64_caches {
};
extern struct ppc64_caches ppc64_caches;
-
-static inline void logmpp(u64 x)
-{
- asm volatile(PPC_LOGMPP(R1) : : "r" (x));
-}
-
#endif /* __powerpc64__ && ! __ASSEMBLY__ */
#if defined(__ASSEMBLY__)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 827a38d7a9db..887c259556df 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -297,8 +297,6 @@ struct kvmppc_vcore {
u32 arch_compat;
ulong pcr;
ulong dpdes; /* doorbell state (POWER8) */
- void *mpp_buffer; /* Micro Partition Prefetch buffer */
- bool mpp_buffer_is_valid;
ulong conferring_threads;
};
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index cab6753f1be5..3f191f573d4f 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -61,8 +61,13 @@ struct machdep_calls {
unsigned long addr,
unsigned char *hpte_slot_array,
int psize, int ssize, int local);
- /* special for kexec, to be called in real mode, linear mapping is
- * destroyed as well */
+ /*
+ * Special for kexec.
+ * To be called in real mode with interrupts disabled. No locks are
+ * taken as such, concurrent access on pre POWER5 hardware could result
+ * in a deadlock.
+ * The linear mapping is destroyed as well.
+ */
void (*hpte_clear_all)(void);
void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size,
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 790f5d1d9a46..7ab04fc59e24 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -141,7 +141,6 @@
#define PPC_INST_ISEL 0x7c00001e
#define PPC_INST_ISEL_MASK 0xfc00003e
#define PPC_INST_LDARX 0x7c0000a8
-#define PPC_INST_LOGMPP 0x7c0007e4
#define PPC_INST_LSWI 0x7c0004aa
#define PPC_INST_LSWX 0x7c00042a
#define PPC_INST_LWARX 0x7c000028
@@ -285,20 +284,6 @@
#define __PPC_EH(eh) 0
#endif
-/* POWER8 Micro Partition Prefetch (MPP) parameters */
-/* Address mask is common for LOGMPP instruction and MPPR SPR */
-#define PPC_MPPE_ADDRESS_MASK 0xffffffffc000ULL
-
-/* Bits 60 and 61 of MPP SPR should be set to one of the following */
-/* Aborting the fetch is indeed setting 00 in the table size bits */
-#define PPC_MPPR_FETCH_ABORT (0x0ULL << 60)
-#define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60)
-
-/* Bits 54 and 55 of register for LOGMPP instruction should be set to: */
-#define PPC_LOGMPP_LOG_L2 (0x02ULL << 54)
-#define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54)
-#define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54)
-
/* Deal with instructions that older assemblers aren't aware of */
#define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \
__PPC_RA(a) | __PPC_RB(b))
@@ -307,8 +292,6 @@
#define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \
___PPC_RT(t) | ___PPC_RA(a) | \
___PPC_RB(b) | __PPC_EH(eh))
-#define PPC_LOGMPP(b) stringify_in_c(.long PPC_INST_LOGMPP | \
- __PPC_RB(b))
#define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \
___PPC_RT(t) | ___PPC_RA(a) | \
___PPC_RB(b) | __PPC_EH(eh))
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index aa1cc5f015ee..a908ada8e0a5 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -226,7 +226,6 @@
#define CTRL_TE 0x00c00000 /* thread enable */
#define CTRL_RUNLATCH 0x1
#define SPRN_DAWR 0xB4
-#define SPRN_MPPR 0xB8 /* Micro Partition Prefetch Register */
#define SPRN_RPR 0xBA /* Relative Priority Register */
#define SPRN_CIABR 0xBB
#define CIABR_PRIV 0x3
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 59503ed98e5f..3f1472a78f39 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -303,7 +303,7 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
dev->coherent_dma_mask = mask;
return 0;
}
-EXPORT_SYMBOL_GPL(dma_set_coherent_mask);
+EXPORT_SYMBOL(dma_set_coherent_mask);
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 84bf934cf748..5a753fae8265 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -1043,6 +1043,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!rtas.entry)
+ return -EINVAL;
+
if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
return -EFAULT;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 228049786888..9c26c5a96ea2 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -36,7 +36,6 @@
#include <asm/reg.h>
#include <asm/cputable.h>
-#include <asm/cache.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
@@ -75,12 +74,6 @@
static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
-#if defined(CONFIG_PPC_64K_PAGES)
-#define MPP_BUFFER_ORDER 0
-#elif defined(CONFIG_PPC_4K_PAGES)
-#define MPP_BUFFER_ORDER 3
-#endif
-
static int dynamic_mt_modes = 6;
module_param(dynamic_mt_modes, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(dynamic_mt_modes, "Set of allowed dynamic micro-threading modes: 0 (= none), 2, 4, or 6 (= 2 or 4)");
@@ -1455,13 +1448,6 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
vcore->kvm = kvm;
INIT_LIST_HEAD(&vcore->preempt_list);
- vcore->mpp_buffer_is_valid = false;
-
- if (cpu_has_feature(CPU_FTR_ARCH_207S))
- vcore->mpp_buffer = (void *)__get_free_pages(
- GFP_KERNEL|__GFP_ZERO,
- MPP_BUFFER_ORDER);
-
return vcore;
}
@@ -1894,33 +1880,6 @@ static int on_primary_thread(void)
return 1;
}
-static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc)
-{
- phys_addr_t phy_addr, mpp_addr;
-
- phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer);
- mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
- mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT);
- logmpp(mpp_addr | PPC_LOGMPP_LOG_L2);
-
- vc->mpp_buffer_is_valid = true;
-}
-
-static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
-{
- phys_addr_t phy_addr, mpp_addr;
-
- phy_addr = virt_to_phys(vc->mpp_buffer);
- mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
- /* We must abort any in-progress save operations to ensure
- * the table is valid so that prefetch engine knows when to
- * stop prefetching. */
- logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT);
- mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
-}
-
/*
* A list of virtual cores for each physical CPU.
* These are vcores that could run but their runner VCPU tasks are
@@ -2471,14 +2430,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
srcu_idx = srcu_read_lock(&vc->kvm->srcu);
- if (vc->mpp_buffer_is_valid)
- kvmppc_start_restoring_l2_cache(vc);
-
__kvmppc_vcore_entry();
- if (vc->mpp_buffer)
- kvmppc_start_saving_l2_cache(vc);
-
srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
spin_lock(&vc->lock);
@@ -3073,14 +3026,8 @@ static void kvmppc_free_vcores(struct kvm *kvm)
{
long int i;
- for (i = 0; i < KVM_MAX_VCORES; ++i) {
- if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) {
- struct kvmppc_vcore *vc = kvm->arch.vcores[i];
- free_pages((unsigned long)vc->mpp_buffer,
- MPP_BUFFER_ORDER);
- }
+ for (i = 0; i < KVM_MAX_VCORES; ++i)
kfree(kvm->arch.vcores[i]);
- }
kvm->arch.online_vcores = 0;
}
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 13befa35d8a8..c8822af10a58 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -582,13 +582,21 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
* be when they isi), and we are the only one left. We rely on our kernel
* mapping being 0xC0's and the hardware ignoring those two real bits.
*
+ * This must be called with interrupts disabled.
+ *
+ * Taking the native_tlbie_lock is unsafe here due to the possibility of
+ * lockdep being on. On pre POWER5 hardware, not taking the lock could
+ * cause deadlock. POWER5 and newer not taking the lock is fine. This only
+ * gets called during boot before secondary CPUs have come up and during
+ * crashdump and all bets are off anyway.
+ *
* TODO: add batching support when enabled. remember, no dynamic memory here,
* athough there is the control page available...
*/
static void native_hpte_clear(void)
{
unsigned long vpn = 0;
- unsigned long slot, slots, flags;
+ unsigned long slot, slots;
struct hash_pte *hptep = htab_address;
unsigned long hpte_v;
unsigned long pteg_count;
@@ -596,13 +604,6 @@ static void native_hpte_clear(void)
pteg_count = htab_hash_mask + 1;
- local_irq_save(flags);
-
- /* we take the tlbie lock and hold it. Some hardware will
- * deadlock if we try to tlbie from two processors at once.
- */
- raw_spin_lock(&native_tlbie_lock);
-
slots = pteg_count * HPTES_PER_GROUP;
for (slot = 0; slot < slots; slot++, hptep++) {
@@ -614,8 +615,8 @@ static void native_hpte_clear(void)
hpte_v = be64_to_cpu(hptep->v);
/*
- * Call __tlbie() here rather than tlbie() since we
- * already hold the native_tlbie_lock.
+ * Call __tlbie() here rather than tlbie() since we can't take the
+ * native_tlbie_lock.
*/
if (hpte_v & HPTE_V_VALID) {
hpte_decode(hptep, slot, &psize, &apsize, &ssize, &vpn);
@@ -625,8 +626,6 @@ static void native_hpte_clear(void)
}
asm volatile("eieio; tlbsync; ptesync":::"memory");
- raw_spin_unlock(&native_tlbie_lock);
- local_irq_restore(flags);
}
/*
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 230f3a7cdea4..4296d55e88f3 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -487,9 +487,12 @@ int opal_machine_check(struct pt_regs *regs)
* PRD component would have already got notified about this
* error through other channels.
*
- * In any case, let us just fall through. We anyway heading
- * down to panic path.
+ * If hardware marked this as an unrecoverable MCE, we are
+ * going to panic anyway. Even if it didn't, it's not safe to
+ * continue at this point, so we should explicitly panic.
*/
+
+ panic("PowerNV Unrecovered Machine Check");
return 0;
}
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 8f70ba681a78..ca264833ee64 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -171,7 +171,26 @@ static void pnv_smp_cpu_kill_self(void)
* so clear LPCR:PECE1. We keep PECE2 enabled.
*/
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+
+ /*
+ * Hard-disable interrupts, and then clear irq_happened flags
+ * that we can safely ignore while off-line, since they
+ * are for things for which we do no processing when off-line
+ * (or in the case of HMI, all the processing we need to do
+ * is done in lower-level real-mode code).
+ */
+ hard_irq_disable();
+ local_paca->irq_happened &= ~(PACA_IRQ_DEC | PACA_IRQ_HMI);
+
while (!generic_check_cpu_restart(cpu)) {
+ /*
+ * Clear IPI flag, since we don't handle IPIs while
+ * offline, except for those when changing micro-threading
+ * mode, which are handled explicitly below, and those
+ * for coming online, which are handled via
+ * generic_check_cpu_restart() calls.
+ */
+ kvmppc_set_host_ipi(cpu, 0);
ppc64_runlatch_off();
@@ -196,20 +215,20 @@ static void pnv_smp_cpu_kill_self(void)
* having finished executing in a KVM guest, then srr1
* contains 0.
*/
- if ((srr1 & wmask) == SRR1_WAKEEE) {
+ if (((srr1 & wmask) == SRR1_WAKEEE) ||
+ (local_paca->irq_happened & PACA_IRQ_EE)) {
icp_native_flush_interrupt();
- local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
- smp_mb();
} else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
- kvmppc_set_host_ipi(cpu, 0);
}
+ local_paca->irq_happened &= ~(PACA_IRQ_EE | PACA_IRQ_DBELL);
+ smp_mb();
if (cpu_core_split_required())
continue;
- if (!generic_check_cpu_restart(cpu))
+ if (srr1 && !generic_check_cpu_restart(cpu))
DBG("CPU%d Unexpected exit while offline !\n", cpu);
}
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 09787139834d..3db53e8aff92 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -194,11 +194,6 @@ static const struct os_area_db_id os_area_db_id_rtc_diff = {
.key = OS_AREA_DB_KEY_RTC_DIFF
};
-static const struct os_area_db_id os_area_db_id_video_mode = {
- .owner = OS_AREA_DB_OWNER_LINUX,
- .key = OS_AREA_DB_KEY_VIDEO_MODE
-};
-
#define SECONDS_FROM_1970_TO_2000 946684800LL
/**
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index fe20d14ae051..ceb5201a30ed 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -59,6 +59,7 @@ pages_do_alias(unsigned long addr1, unsigned long addr2)
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
extern void copy_page(void *to, void *from);
+#define copy_user_page(to, from, vaddr, pg) __copy_user(to, from, PAGE_SIZE)
struct page;
struct vm_area_struct;
diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c
index 2e48eb8813ff..c90930de76ba 100644
--- a/arch/sparc/crypto/aes_glue.c
+++ b/arch/sparc/crypto/aes_glue.c
@@ -433,6 +433,7 @@ static struct crypto_alg algs[] = { {
.blkcipher = {
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
.setkey = aes_set_key,
.encrypt = cbc_encrypt,
.decrypt = cbc_decrypt,
@@ -452,6 +453,7 @@ static struct crypto_alg algs[] = { {
.blkcipher = {
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
.setkey = aes_set_key,
.encrypt = ctr_crypt,
.decrypt = ctr_crypt,
diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c
index 6bf2479a12fb..561a84d93cf6 100644
--- a/arch/sparc/crypto/camellia_glue.c
+++ b/arch/sparc/crypto/camellia_glue.c
@@ -274,6 +274,7 @@ static struct crypto_alg algs[] = { {
.blkcipher = {
.min_keysize = CAMELLIA_MIN_KEY_SIZE,
.max_keysize = CAMELLIA_MAX_KEY_SIZE,
+ .ivsize = CAMELLIA_BLOCK_SIZE,
.setkey = camellia_set_key,
.encrypt = cbc_encrypt,
.decrypt = cbc_decrypt,
diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c
index dd6a34fa6e19..61af794aa2d3 100644
--- a/arch/sparc/crypto/des_glue.c
+++ b/arch/sparc/crypto/des_glue.c
@@ -429,6 +429,7 @@ static struct crypto_alg algs[] = { {
.blkcipher = {
.min_keysize = DES_KEY_SIZE,
.max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
.setkey = des_set_key,
.encrypt = cbc_encrypt,
.decrypt = cbc_decrypt,
@@ -485,6 +486,7 @@ static struct crypto_alg algs[] = { {
.blkcipher = {
.min_keysize = DES3_EDE_KEY_SIZE,
.max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
.setkey = des3_ede_set_key,
.encrypt = cbc3_encrypt,
.decrypt = cbc3_decrypt,
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 098ab3333e7c..e3abe6f3156d 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -70,8 +70,8 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
$(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
- -D_FILE_OFFSET_BITS=64 -idirafter include \
- -D__KERNEL__ -D__UM_HOST__
+ -D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
+ -idirafter $(obj)/include -D__KERNEL__ -D__UM_HOST__
#This will adjust *FLAGS accordingly to the platform.
include $(ARCH_DIR)/Makefile-os-$(OS)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index d8a9fce6ee2e..98783dd0fa2e 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -220,7 +220,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
show_regs(container_of(regs, struct pt_regs, regs));
panic("Segfault with no mm");
}
- else if (!is_user && address < TASK_SIZE) {
+ else if (!is_user && address > PAGE_SIZE && address < TASK_SIZE) {
show_regs(container_of(regs, struct pt_regs, regs));
panic("Kernel tried to access user memory at addr 0x%lx, ip 0x%lx",
address, ip);
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index e3ee4a51ef63..3f02d4232812 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -96,7 +96,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
"ret = %d\n", -n);
ret = n;
}
- CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
+ CATCH_EINTR(waitpid(pid, NULL, __WALL));
}
out_free2:
@@ -129,7 +129,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
return err;
}
if (stack_out == NULL) {
- CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
+ CATCH_EINTR(pid = waitpid(pid, &status, __WALL));
if (pid < 0) {
err = -errno;
printk(UM_KERN_ERR "run_helper_thread - wait failed, "
@@ -148,7 +148,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
int helper_wait(int pid)
{
int ret, status;
- int wflags = __WCLONE;
+ int wflags = __WALL;
CATCH_EINTR(ret = waitpid(pid, &status, wflags));
if (ret < 0) {
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index ee1b6d346b98..db51c1f27446 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -667,6 +667,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
bool conout_found = false;
void *dummy = NULL;
u32 h = handles[i];
+ u32 current_fb_base;
status = efi_call_early(handle_protocol, h,
proto, (void **)&gop32);
@@ -678,7 +679,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
if (status == EFI_SUCCESS)
conout_found = true;
- status = __gop_query32(gop32, &info, &size, &fb_base);
+ status = __gop_query32(gop32, &info, &size, &current_fb_base);
if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
/*
* Systems that use the UEFI Console Splitter may
@@ -692,6 +693,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
pixel_format = info->pixel_format;
pixel_info = info->pixel_information;
pixels_per_scan_line = info->pixels_per_scan_line;
+ fb_base = current_fb_base;
/*
* Once we've found a GOP supporting ConOut,
@@ -770,6 +772,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
bool conout_found = false;
void *dummy = NULL;
u64 h = handles[i];
+ u32 current_fb_base;
status = efi_call_early(handle_protocol, h,
proto, (void **)&gop64);
@@ -781,7 +784,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
if (status == EFI_SUCCESS)
conout_found = true;
- status = __gop_query64(gop64, &info, &size, &fb_base);
+ status = __gop_query64(gop64, &info, &size, &current_fb_base);
if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
/*
* Systems that use the UEFI Console Splitter may
@@ -795,6 +798,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
pixel_format = info->pixel_format;
pixel_info = info->pixel_information;
pixels_per_scan_line = info->pixels_per_scan_line;
+ fb_base = current_fb_base;
/*
* Once we've found a GOP supporting ConOut,
diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c
index 80a0e4389c9a..bacaa13acac5 100644
--- a/arch/x86/crypto/camellia_aesni_avx_glue.c
+++ b/arch/x86/crypto/camellia_aesni_avx_glue.c
@@ -554,6 +554,11 @@ static int __init camellia_aesni_init(void)
{
const char *feature_name;
+ if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
+ pr_info("AVX or AES-NI instructions are not detected.\n");
+ return -ENODEV;
+ }
+
if (!cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, &feature_name)) {
pr_info("CPU feature '%s' is not supported.\n", feature_name);
return -ENODEV;
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 2beee0382088..3a36ee704c30 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1226,10 +1226,8 @@ void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
int kvm_is_in_guest(void);
-int __x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem);
-int x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem);
+int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size);
+int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size);
bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu);
bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index e4661196994e..ff8b9a17dc4b 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -27,12 +27,11 @@ static __always_inline void *__inline_memcpy(void *to, const void *from, size_t
function. */
#define __HAVE_ARCH_MEMCPY 1
+extern void *memcpy(void *to, const void *from, size_t len);
extern void *__memcpy(void *to, const void *from, size_t len);
#ifndef CONFIG_KMEMCHECK
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-extern void *memcpy(void *to, const void *from, size_t len);
-#else
+#if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
#define memcpy(dst, src, len) \
({ \
size_t __len = (len); \
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 5c60bb162622..4f2821527014 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2547,7 +2547,9 @@ void __init setup_ioapic_dest(void)
mask = apic->target_cpus();
chip = irq_data_get_irq_chip(idata);
- chip->irq_set_affinity(idata, mask, false);
+ /* Might be lapic_chip for irq 0 */
+ if (chip->irq_set_affinity)
+ chip->irq_set_affinity(idata, mask, false);
}
}
#endif
@@ -2907,6 +2909,7 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
struct irq_data *irq_data;
struct mp_chip_data *data;
struct irq_alloc_info *info = arg;
+ unsigned long flags;
if (!info || nr_irqs > 1)
return -EINVAL;
@@ -2939,11 +2942,14 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
cfg = irqd_cfg(irq_data);
add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
+
+ local_irq_save(flags);
if (info->ioapic_entry)
mp_setup_entry(cfg, data, info->ioapic_entry);
mp_register_handler(virq, data->trigger);
if (virq < nr_legacy_irqs())
legacy_pic->mask(virq);
+ local_irq_restore(flags);
apic_printk(APIC_VERBOSE, KERN_DEBUG
"IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n",
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 1b55de1267cf..cd99433b8ba1 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -131,11 +131,12 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr,
bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp)
{
+ if (!*dev)
+ *dev = &x86_dma_fallback_dev;
+
*gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
*gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp);
- if (!*dev)
- *dev = &x86_dma_fallback_dev;
if (!is_device_dma_capable(*dev))
return false;
return true;
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 39e585a554b7..9f7c21c22477 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -84,6 +84,9 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister);
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
memcpy(dst, src, arch_task_struct_size);
+#ifdef CONFIG_VM86
+ dst->thread.vm86 = NULL;
+#endif
return fpu__copy(&dst->thread.fpu, &src->thread.fpu);
}
@@ -550,14 +553,14 @@ unsigned long get_wchan(struct task_struct *p)
if (sp < bottom || sp > top)
return 0;
- fp = READ_ONCE(*(unsigned long *)sp);
+ fp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
do {
if (fp < bottom || fp > top)
return 0;
- ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long)));
+ ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long)));
if (!in_sched_functions(ip))
return ip;
- fp = READ_ONCE(*(unsigned long *)fp);
+ fp = READ_ONCE_NOCHECK(*(unsigned long *)fp);
} while (count++ < 16 && p->state != TASK_RUNNING);
return 0;
}
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index fdb7f2a2d328..a3cccbfc5f77 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1173,6 +1173,14 @@ void __init setup_arch(char **cmdline_p)
clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
swapper_pg_dir + KERNEL_PGD_BOUNDARY,
KERNEL_PGD_PTRS);
+
+ /*
+ * sync back low identity map too. It is used for example
+ * in the 32-bit EFI stub.
+ */
+ clone_pgd_range(initial_page_table,
+ swapper_pg_dir + KERNEL_PGD_BOUNDARY,
+ KERNEL_PGD_PTRS);
#endif
tboot_probe();
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index e0c198e5f920..892ee2e5ecbc 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -509,7 +509,7 @@ void __inquire_remote_apic(int apicid)
*/
#define UDELAY_10MS_DEFAULT 10000
-static unsigned int init_udelay = UDELAY_10MS_DEFAULT;
+static unsigned int init_udelay = INT_MAX;
static int __init cpu_init_udelay(char *str)
{
@@ -522,13 +522,16 @@ early_param("cpu_init_udelay", cpu_init_udelay);
static void __init smp_quirk_init_udelay(void)
{
/* if cmdline changed it from default, leave it alone */
- if (init_udelay != UDELAY_10MS_DEFAULT)
+ if (init_udelay != INT_MAX)
return;
/* if modern processor, use no delay */
if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
init_udelay = 0;
+
+ /* else, use legacy delay */
+ init_udelay = UDELAY_10MS_DEFAULT;
}
/*
@@ -657,7 +660,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
/*
* Give the other CPU some time to accept the IPI.
*/
- if (init_udelay)
+ if (init_udelay == 0)
+ udelay(10);
+ else
udelay(300);
pr_debug("Startup point 1\n");
@@ -668,7 +673,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
/*
* Give the other CPU some time to accept the IPI.
*/
- if (init_udelay)
+ if (init_udelay == 0)
+ udelay(10);
+ else
udelay(200);
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b372a7557c16..9da95b9daf8d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2418,7 +2418,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
u64 val, cr0, cr4;
u32 base3;
u16 selector;
- int i;
+ int i, r;
for (i = 0; i < 16; i++)
*reg_write(ctxt, i) = GET_SMSTATE(u64, smbase, 0x7ff8 - i * 8);
@@ -2460,13 +2460,17 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
dt.address = GET_SMSTATE(u64, smbase, 0x7e68);
ctxt->ops->set_gdt(ctxt, &dt);
+ r = rsm_enter_protected_mode(ctxt, cr0, cr4);
+ if (r != X86EMUL_CONTINUE)
+ return r;
+
for (i = 0; i < 6; i++) {
- int r = rsm_load_seg_64(ctxt, smbase, i);
+ r = rsm_load_seg_64(ctxt, smbase, i);
if (r != X86EMUL_CONTINUE)
return r;
}
- return rsm_enter_protected_mode(ctxt, cr0, cr4);
+ return X86EMUL_CONTINUE;
}
static int em_rsm(struct x86_emulate_ctxt *ctxt)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 06ef4908ba61..6a8bc64566ab 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4105,17 +4105,13 @@ static void seg_setup(int seg)
static int alloc_apic_access_page(struct kvm *kvm)
{
struct page *page;
- struct kvm_userspace_memory_region kvm_userspace_mem;
int r = 0;
mutex_lock(&kvm->slots_lock);
if (kvm->arch.apic_access_page_done)
goto out;
- kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
- kvm_userspace_mem.flags = 0;
- kvm_userspace_mem.guest_phys_addr = APIC_DEFAULT_PHYS_BASE;
- kvm_userspace_mem.memory_size = PAGE_SIZE;
- r = __x86_set_memory_region(kvm, &kvm_userspace_mem);
+ r = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
+ APIC_DEFAULT_PHYS_BASE, PAGE_SIZE);
if (r)
goto out;
@@ -4140,17 +4136,12 @@ static int alloc_identity_pagetable(struct kvm *kvm)
{
/* Called with kvm->slots_lock held. */
- struct kvm_userspace_memory_region kvm_userspace_mem;
int r = 0;
BUG_ON(kvm->arch.ept_identity_pagetable_done);
- kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
- kvm_userspace_mem.flags = 0;
- kvm_userspace_mem.guest_phys_addr =
- kvm->arch.ept_identity_map_addr;
- kvm_userspace_mem.memory_size = PAGE_SIZE;
- r = __x86_set_memory_region(kvm, &kvm_userspace_mem);
+ r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT,
+ kvm->arch.ept_identity_map_addr, PAGE_SIZE);
return r;
}
@@ -4949,14 +4940,9 @@ static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
{
int ret;
- struct kvm_userspace_memory_region tss_mem = {
- .slot = TSS_PRIVATE_MEMSLOT,
- .guest_phys_addr = addr,
- .memory_size = PAGE_SIZE * 3,
- .flags = 0,
- };
- ret = x86_set_memory_region(kvm, &tss_mem);
+ ret = x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, addr,
+ PAGE_SIZE * 3);
if (ret)
return ret;
kvm->arch.tss_addr = addr;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 92511d4b7236..9a9a19830321 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6453,6 +6453,12 @@ static inline int vcpu_block(struct kvm *kvm, struct kvm_vcpu *vcpu)
return 1;
}
+static inline bool kvm_vcpu_running(struct kvm_vcpu *vcpu)
+{
+ return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
+ !vcpu->arch.apf.halted);
+}
+
static int vcpu_run(struct kvm_vcpu *vcpu)
{
int r;
@@ -6461,8 +6467,7 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
for (;;) {
- if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
- !vcpu->arch.apf.halted)
+ if (kvm_vcpu_running(vcpu))
r = vcpu_enter_guest(vcpu);
else
r = vcpu_block(kvm, vcpu);
@@ -7474,34 +7479,66 @@ void kvm_arch_sync_events(struct kvm *kvm)
kvm_free_pit(kvm);
}
-int __x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem)
+int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
{
int i, r;
+ unsigned long hva;
+ struct kvm_memslots *slots = kvm_memslots(kvm);
+ struct kvm_memory_slot *slot, old;
/* Called with kvm->slots_lock held. */
- BUG_ON(mem->slot >= KVM_MEM_SLOTS_NUM);
+ if (WARN_ON(id >= KVM_MEM_SLOTS_NUM))
+ return -EINVAL;
+
+ slot = id_to_memslot(slots, id);
+ if (size) {
+ if (WARN_ON(slot->npages))
+ return -EEXIST;
+
+ /*
+ * MAP_SHARED to prevent internal slot pages from being moved
+ * by fork()/COW.
+ */
+ hva = vm_mmap(NULL, 0, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, 0);
+ if (IS_ERR((void *)hva))
+ return PTR_ERR((void *)hva);
+ } else {
+ if (!slot->npages)
+ return 0;
+ hva = 0;
+ }
+
+ old = *slot;
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
- struct kvm_userspace_memory_region m = *mem;
+ struct kvm_userspace_memory_region m;
- m.slot |= i << 16;
+ m.slot = id | (i << 16);
+ m.flags = 0;
+ m.guest_phys_addr = gpa;
+ m.userspace_addr = hva;
+ m.memory_size = size;
r = __kvm_set_memory_region(kvm, &m);
if (r < 0)
return r;
}
+ if (!size) {
+ r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
+ WARN_ON(r < 0);
+ }
+
return 0;
}
EXPORT_SYMBOL_GPL(__x86_set_memory_region);
-int x86_set_memory_region(struct kvm *kvm,
- const struct kvm_userspace_memory_region *mem)
+int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
{
int r;
mutex_lock(&kvm->slots_lock);
- r = __x86_set_memory_region(kvm, mem);
+ r = __x86_set_memory_region(kvm, id, gpa, size);
mutex_unlock(&kvm->slots_lock);
return r;
@@ -7516,16 +7553,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
* unless the the memory map has changed due to process exit
* or fd copying.
*/
- struct kvm_userspace_memory_region mem;
- memset(&mem, 0, sizeof(mem));
- mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
- x86_set_memory_region(kvm, &mem);
-
- mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
- x86_set_memory_region(kvm, &mem);
-
- mem.slot = TSS_PRIVATE_MEMSLOT;
- x86_set_memory_region(kvm, &mem);
+ x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, 0, 0);
+ x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, 0, 0);
+ x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0);
}
kvm_iommu_unmap_guest(kvm);
kfree(kvm->arch.vpic);
@@ -7628,27 +7658,6 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
const struct kvm_userspace_memory_region *mem,
enum kvm_mr_change change)
{
- /*
- * Only private memory slots need to be mapped here since
- * KVM_SET_MEMORY_REGION ioctl is no longer supported.
- */
- if ((memslot->id >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_CREATE)) {
- unsigned long userspace_addr;
-
- /*
- * MAP_SHARED to prevent internal slot pages from being moved
- * by fork()/COW.
- */
- userspace_addr = vm_mmap(NULL, 0, memslot->npages * PAGE_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_ANONYMOUS, 0);
-
- if (IS_ERR((void *)userspace_addr))
- return PTR_ERR((void *)userspace_addr);
-
- memslot->userspace_addr = userspace_addr;
- }
-
return 0;
}
@@ -7710,17 +7719,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
{
int nr_mmu_pages = 0;
- if (change == KVM_MR_DELETE && old->id >= KVM_USER_MEM_SLOTS) {
- int ret;
-
- ret = vm_munmap(old->userspace_addr,
- old->npages * PAGE_SIZE);
- if (ret < 0)
- printk(KERN_WARNING
- "kvm_vm_ioctl_set_memory_region: "
- "failed to munmap memory\n");
- }
-
if (!kvm->arch.n_requested_mmu_pages)
nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
@@ -7769,19 +7767,36 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
kvm_mmu_invalidate_zap_all_pages(kvm);
}
+static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
+{
+ if (!list_empty_careful(&vcpu->async_pf.done))
+ return true;
+
+ if (kvm_apic_has_events(vcpu))
+ return true;
+
+ if (vcpu->arch.pv.pv_unhalted)
+ return true;
+
+ if (atomic_read(&vcpu->arch.nmi_queued))
+ return true;
+
+ if (test_bit(KVM_REQ_SMI, &vcpu->requests))
+ return true;
+
+ if (kvm_arch_interrupt_allowed(vcpu) &&
+ kvm_cpu_has_interrupt(vcpu))
+ return true;
+
+ return false;
+}
+
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events)
kvm_x86_ops->check_nested_events(vcpu, false);
- return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
- !vcpu->arch.apf.halted)
- || !list_empty_careful(&vcpu->async_pf.done)
- || kvm_apic_has_events(vcpu)
- || vcpu->arch.pv.pv_unhalted
- || atomic_read(&vcpu->arch.nmi_queued) ||
- (kvm_arch_interrupt_allowed(vcpu) &&
- kvm_cpu_has_interrupt(vcpu));
+ return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu);
}
int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/um/ldt.c b/arch/x86/um/ldt.c
index 9701a4fd7bf2..836a1eb5df43 100644
--- a/arch/x86/um/ldt.c
+++ b/arch/x86/um/ldt.c
@@ -12,7 +12,10 @@
#include <skas.h>
#include <sysdep/tls.h>
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
+{
+ return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
static long write_ldt_entry(struct mm_id *mm_idp, int func,
struct user_desc *desc, void **addr, int done)