summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig65
-rw-r--r--arch/arm/boot/dts/Makefile1
-rw-r--r--arch/arm/boot/dts/exynos4210-origen.dts261
-rw-r--r--arch/arm/boot/dts/exynos4210-pinctrl.dtsi47
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi45
-rw-r--r--arch/arm/boot/dts/exynos5250-arndale.dts357
-rw-r--r--arch/arm/boot/dts/exynos5250-smdk5250.dts4
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi40
-rw-r--r--arch/arm/configs/android_origen_defconfig210
-rw-r--r--arch/arm/configs/arndale_ubuntu_defconfig129
-rw-r--r--arch/arm/configs/exynos4_defconfig127
-rw-r--r--arch/arm/configs/ubuntu_origen_defconfig241
-rw-r--r--arch/arm/include/asm/hugetlb-2level.h71
-rw-r--r--arch/arm/include/asm/hugetlb-3level.h61
-rw-r--r--arch/arm/include/asm/hugetlb.h87
-rw-r--r--arch/arm/include/asm/memory.h105
-rw-r--r--arch/arm/include/asm/mmzone.h49
-rw-r--r--arch/arm/include/asm/module.h7
-rw-r--r--arch/arm/include/asm/page.h2
-rw-r--r--arch/arm/include/asm/pgtable-2level.h152
-rw-r--r--arch/arm/include/asm/pgtable-3level-hwdef.h12
-rw-r--r--arch/arm/include/asm/pgtable-3level.h83
-rw-r--r--arch/arm/include/asm/pgtable.h34
-rw-r--r--arch/arm/include/asm/proc-fns.h28
-rw-r--r--arch/arm/include/asm/runtime-patch.h208
-rw-r--r--arch/arm/include/asm/tlb.h16
-rw-r--r--arch/arm/include/asm/tlbflush.h2
-rw-r--r--arch/arm/include/asm/topology.h15
-rw-r--r--arch/arm/include/asm/unistd.h2
-rw-r--r--arch/arm/include/uapi/asm/unistd.h1
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/armksyms.c4
-rw-r--r--arch/arm/kernel/calls.S1
-rw-r--r--arch/arm/kernel/head.S117
-rw-r--r--arch/arm/kernel/module.c13
-rw-r--r--arch/arm/kernel/runtime-patch.c268
-rw-r--r--arch/arm/kernel/setup.c22
-rw-r--r--arch/arm/kernel/smp.c11
-rw-r--r--arch/arm/kernel/vmlinux.lds.S13
-rw-r--r--arch/arm/mach-exynos/Kconfig8
-rw-r--r--arch/arm/mach-exynos/clock-exynos4.c228
-rw-r--r--arch/arm/mach-exynos/clock-exynos5.c27
-rw-r--r--arch/arm/mach-exynos/common.c120
-rw-r--r--arch/arm/mach-exynos/dev-ahci.c4
-rw-r--r--arch/arm/mach-exynos/dev-ohci.c4
-rw-r--r--arch/arm/mach-exynos/include/mach/irqs.h14
-rw-r--r--arch/arm/mach-exynos/include/mach/mali/config.h173
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h17
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-audss.h11
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-pmu.h7
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-sata.h29
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-usb-phy.h86
-rw-r--r--arch/arm/mach-exynos/include/mach/ump/config.h18
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c70
-rw-r--r--arch/arm/mach-exynos/mach-exynos5-dt.c46
-rw-r--r--arch/arm/mach-exynos/mach-origen.c223
-rw-r--r--arch/arm/mach-exynos/pm_domains.c5
-rw-r--r--arch/arm/mach-exynos/setup-usb-phy.c189
-rw-r--r--arch/arm/mm/Makefile8
-rw-r--r--arch/arm/mm/context.c9
-rw-r--r--arch/arm/mm/dma-mapping.c2
-rw-r--r--arch/arm/mm/fault.c6
-rw-r--r--arch/arm/mm/flush.c25
-rw-r--r--arch/arm/mm/fsr-3level.c2
-rw-r--r--arch/arm/mm/hugetlbpage-2level.c115
-rw-r--r--arch/arm/mm/hugetlbpage-3level.c190
-rw-r--r--arch/arm/mm/hugetlbpage.c65
-rw-r--r--arch/arm/mm/init.c200
-rw-r--r--arch/arm/mm/mmu.c46
-rw-r--r--arch/arm/mm/numa.c278
-rw-r--r--arch/arm/mm/proc-v7-3level.S41
-rw-r--r--arch/arm/plat-samsung/Kconfig5
-rw-r--r--arch/arm/plat-samsung/devs.c21
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s5p.h2
-rw-r--r--arch/arm/plat-samsung/include/plat/usb-phy.h8
-rw-r--r--arch/arm/plat-samsung/s5p-dev-mfc.c51
77 files changed, 4781 insertions, 486 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9a9b1ca0886..00f04f64cbb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -56,6 +56,7 @@ config ARM
select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
select MODULES_USE_ELF_REL
select CLONE_BACKWARDS
+ select HAVE_MEMBLOCK_NODE_MAP
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
@@ -67,6 +68,9 @@ config ARM
config ARM_HAS_SG_CHAIN
bool
+config ARM_RUNTIME_PATCH
+ bool
+
config NEED_SG_DMA_LENGTH
bool
@@ -197,6 +201,7 @@ config ARM_PATCH_PHYS_VIRT
default y
depends on !XIP_KERNEL && MMU
depends on !ARCH_REALVIEW || !SPARSEMEM
+ select ARM_RUNTIME_PATCH
help
Patch phys-to-virt and virt-to-phys translation functions at
boot and module load time according to the position of the
@@ -216,6 +221,18 @@ config NEED_MACH_GPIO_H
definitions for this platform. The need for mach/gpio.h should
be avoided when possible.
+config ARM_RUNTIME_PATCH_TEST
+ bool "Self test runtime patching mechanism" if ARM_RUNTIME_PATCH
+ default y
+ help
+ Select this to enable init time self checking for the runtime kernel
+ patching mechanism. This enables an ISA specific set of tests that
+ ensure that the instructions generated by the patch process are
+ consistent with those generated by the assembler at compile time.
+
+ Only disable this option if you need to shrink the kernel to the
+ minimal size.
+
config NEED_MACH_IO_H
bool
help
@@ -1163,8 +1180,48 @@ config ARM_TIMER_SP804
select CLKSRC_MMIO
select HAVE_SCHED_CLOCK
+config ARCH_FLATMEM_ENABLE
+ bool
+ depends on MMU
+ default y
+
+config ARCH_DISCONTIGMEM_ENABLE
+ bool
+ depends on MMU
+ default y
+
source arch/arm/mm/Kconfig
+config NUMA
+ bool "NUMA Support (EXPERIMENTAL)"
+ depends on MMU && !FLATMEM && EXPERIMENTAL
+ help
+ Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+ Access). At the moment, one has to specify the number of nodes using
+ the commandline:
+ numa=fake=x,[size0],[size1],...,[sizeN-1],[usetopology]
+ where x is the number of nodes, and sizeY is the size of node Y in
+ bytes (one can suffix m or g for megabytes or gigabytes). If no sizes
+ are specified, the memory is distributed roughly evenly between nodes.
+ If "usetopology" is specified, the "topology_physical_package_id" is
+ used to assign CPUs to nodes (so for instance on the TC2, the A7s are
+ grouped together in one node and the A15s are grouped together in
+ another node).
+
+config NODES_SHIFT
+ int "Maximum NUMA Nodes (as a power of 2)" if NUMA
+ range 1 10
+ default "1"
+ depends on NEED_MULTIPLE_NODES
+ ---help---
+ Specify the maximum number of NUMA Nodes available on the target
+ system. Increases memory reserved to accommodate various tables.
+
+config NUMA_ALLOC_NODES
+ bool
+ depends on DISCONTIGMEM || NUMA
+ default y
+
config ARM_NR_BANKS
int
default 16 if ARCH_EP93XX
@@ -1869,6 +1926,14 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
+config SYS_SUPPORTS_HUGETLBFS
+ def_bool y
+ depends on ARM_LPAE || (!CPU_USE_DOMAINS && !MEMORY_FAILURE)
+
+config HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ def_bool y
+ depends on SYS_SUPPORTS_HUGETLBFS
+
source "mm/Kconfig"
config FORCE_MAX_ZONEORDER
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 6dbebeeb820..c043aea9340 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -44,6 +44,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
exynos4210-trats.dtb \
exynos4412-smdk4412.dtb \
exynos5250-smdk5250.dtb \
+ exynos5250-arndale.dtb \
exynos5250-snow.dtb \
exynos5440-ssdk5440.dtb
dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index f2710018e84..14bc7359e74 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -73,6 +73,209 @@
status = "okay";
};
+ lcd_fimd0: lcd_panel0 {
+ compatible = "lcd-powercontrol";
+ vcc-lcd-supply = <&buck7_reg>;
+ lcd-reset-gpio = <&gpe3 4 0>;
+ lcd-htiming = <64 16 48 1024>;
+ lcd-vtiming = <64 16 3 600>;
+ };
+
+ fimd@11C00000 {
+ samsung,fimd-display = <&lcd_fimd0>;
+ samsung,fimd-vidout-rgb;
+ samsung,fimd-inv-hsync;
+ samsung,fimd-inv-vsync;
+ samsung,fimd-inv-vclk;
+ samsung,fimd-frame-rate = <60>;
+
+ samsung,power-domain = <&pd_lcd0>;
+
+ pinctrl-0 = <&lcd0_sync &lcd0_clk &lcd0_en &lcd0_data &pwm0_out>;
+ pinctrl-names = "default";
+
+ window0 {
+ samsung,fimd-win-id = <0>;
+ samsung,fimd-win-bpp = <32 24>;
+ samsung,fimd-win-res = <1024 600>;
+ samsung,fimd-win-vres = <1024 600>;
+ };
+
+ window1 {
+ samsung,fimd-win-id = <1>;
+ samsung,fimd-win-bpp = <32 24>;
+ samsung,fimd-win-res = <1024 600>;
+ samsung,fimd-win-vres = <1024 600>;
+ };
+ };
+
+ i2c@13860000 {
+ status = "okay";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ pinctrl-0 = <&i2c0_bus>;
+ pinctrl-names = "default";
+
+ max8997_pmic@66 {
+ compatible = "maxim,max8997-pmic";
+ reg = <0x66>;
+ interrupt-parent = <&gpx0>;
+ interrupts = <4 0>, <3 0>;
+
+ max8997,pmic-buck1-dvs-voltage = <1350000>;
+ max8997,pmic-buck2-dvs-voltage = <1100000>;
+ max8997,pmic-buck5-dvs-voltage = <1200000>;
+
+ regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ABB_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "VDD_ALIVE_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "VMIPI_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "VDD_RTC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "VMIPI_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "VDD_AUD_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo8_reg: LDO8 {
+ regulator-name = "VADC_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo9_reg: LDO9 {
+ regulator-name = "DVDD_SWB_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-name = "VDD_PLL_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-name = "VDD_AUD_3V";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-name = "AVDD18_SWB_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-name = "VDD_SWB_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ ldo21_reg: LDO21 {
+ regulator-name = "VDD_MIF_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "VDD_ARM_1.2V";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "VDD_INT_1.1V";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "VDD_G3D_1.1V";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ buck5_reg: BUCK5 {
+ regulator-name = "VDDQ_M1M2_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
+
+ buck7_reg: BUCK7 {
+ regulator-name = "VDD_LCD_3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+ };
+ };
+
+ unidisplay_ts@41 {
+ compatible = "pixcir,unidisplay-ts";
+ reg = <0x41>;
+ interrupt-parent = <&gpx3>;
+ interrupts = <1 0>;
+ };
+ };
+
+ i2c@13870000 {
+ status = "okay";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ pinctrl-0 = <&i2c1_bus>;
+ pinctrl-names = "default";
+
+ codec: alc5625@1e {
+ compatible = "realtek,alc5625";
+ reg = <0x1e>;
+ };
+ };
+
gpio_keys {
compatible = "gpio-keys";
#address-cells = <1>;
@@ -121,4 +324,62 @@
linux,default-trigger = "heartbeat";
};
};
+
+ usb@12480000 {
+ vusb_a-supply = <&ldo3_reg>;
+ vusb_d-supply = <&ldo8_reg>;
+ };
+
+ i2c@138e0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "samsung,s3c2440-hdmiphy-i2c";
+ samsung,i2c-quirk-hdmiphy;
+ samsung,i2c-no-gpio;
+ reg = <0x138e0000 0x1000>;
+ interrupts = <0 93 0>;
+ status = "okay";
+
+ hdmiphy: phy@38 {
+ compatible = "samsung,hdmiphy-exynos4210";
+ reg = <0x38>;
+ };
+ };
+
+ tvmixer: tvmixer@12c10000 {
+ compatible = "samsung,s5pv210-tvmixer";
+ reg = <0x12c10000 0x10000>, <0x12c00000 0x10000>;
+ reg-names = "mxr", "vp";
+ interrupts = <0 91 0>;
+ interrupt-names = "irq";
+ samsung,power-domain = <&pd_tv>;
+ };
+
+ hdmi: hdmi@12d00000 {
+ compatible = "samsung,s5pv210-hdmi";
+ reg = <0x12d00000 0x100000>;
+ interrupts = <0 92 0>;
+ phy = <&hdmiphy>;
+ samsung,power-domain = <&pd_tv>;
+
+ vdd_osc-supply = <&ldo8_reg>;
+ vdd_pll-supply = <&ldo3_reg>;
+ vdd-supply = <&ldo3_reg>;
+ };
+
+ reg_hdmi_en: fixedregulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "hdmi-en";
+ };
+
+ i2s_0: i2s@03830000 {
+ pinctrl-0 = <&i2s0_bus>;
+ pinctrl-names = "default";
+ idma-addr = <0x03000000>;
+ };
+
+ asoc_dma {
+ compatible = "samsung,audio-dma";
+ };
+
};
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
index 55a2efb763d..8e1bb58212f 100644
--- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -330,6 +330,53 @@
samsung,pin-pud = <3>;
samsung,pin-drv = <0>;
};
+
+ pwm0_out: pwm0-out {
+ samsung,pins = "gpd0-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd0_sync: lcd0-sync {
+ samsung,pins = "gpf0-0", "gpf0-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd0_clk: lcd0-clk {
+ samsung,pins = "gpf0-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd0_en: lcd0-en {
+ samsung,pins = "gpf0-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcd0_data: lcd0-data {
+ samsung,pins = "gpf0-4", "gpf0-5", "gpf0-6", "gpf0-7",
+ "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3",
+ "gpf1-4", "gpf1-5", "gpf1-6", "gpf1-7",
+ "gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3",
+ "gpf2-4", "gpf2-5", "gpf2-6", "gpf2-7",
+ "gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
+
+ lcdpanel_en: lcdpanel-en {
+ samsung,pins = "gpe3-4";
+ samsung,pin-function = <1>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <0>;
+ };
};
pinctrl@11000000 {
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index e31bfc4a6f0..a9a8cc4de04 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -29,6 +29,7 @@
pinctrl0 = &pinctrl_0;
pinctrl1 = &pinctrl_1;
pinctrl2 = &pinctrl_2;
+ i2s0 = &i2s_0;
};
pd_lcd1: lcd1-power-domain@10023CA0 {
@@ -47,6 +48,12 @@
<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
};
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupt-parent = <&combiner>;
+ interrupts = <2 2>, <3 2>;
+ };
+
pinctrl_0: pinctrl@11400000 {
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11400000 0x1000>;
@@ -57,8 +64,8 @@
compatible = "samsung,pinctrl-exynos4210";
reg = <0x11000000 0x1000>;
interrupts = <0 46 0>;
-
wakup_eint: wakeup-interrupt-controller {
+
compatible = "samsung,exynos4210-wakeup-eint";
interrupt-parent = <&gic>;
interrupts = <0 32 0>;
@@ -76,4 +83,40 @@
reg = <0x100C0000 0x100>;
interrupts = <2 4>;
};
+
+ fimd@11C00000 {
+ compatible = "samsung,exynos4210-fimd";
+ interrupt-parent = <&combiner>;
+ reg = <0x11C00000 0x8000>;
+ interrupts = <11 1>, <11 0>, <11 2>;
+ };
+
+ usb@12580000 {
+ compatible = "samsung,exynos-ehci", "usb-ehci";
+ reg = <0x12580000 0x100>;
+ interrupts = <0 70 0>;
+ };
+
+ usb@12590000 {
+ compatible = "samsung,exynos-ohci", "usb-ohci";
+ reg = <0x12590000 0x100>;
+ interrupts = <0 70 0>;
+ };
+
+ usb@12480000 {
+ compatible = "samsung,exynos-hsotg";
+ reg = <0x12480000 0x20000>;
+ interrupts = <0 71 0>;
+ };
+
+ i2s_0: i2s@03830000 {
+ compatible = "samsung,samsung-i2s";
+ reg = <0x03830000 0x100>;
+ tx-dma-channel-secondary = <&pdma0 10>;
+ tx-dma-channel = <&pdma0 12>;
+ rx-dma-channel = <&pdma0 11>;
+ supports-6ch;
+ supports-rstclr;
+ supports-secdai;
+ };
};
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
new file mode 100644
index 00000000000..92a6955eeb1
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -0,0 +1,357 @@
+/*
+ * SAMSUNG ARNDALE5250 board device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.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.
+*/
+
+/dts-v1/;
+/include/ "exynos5250.dtsi"
+
+/ {
+ model = "SAMSUNG ARNDALE board based on EXYNOS5250";
+ compatible = "samsung,arndale", "samsung,exynos5250";
+
+ aliases {
+ mshc0 = &dwmmc_0;
+ mshc1 = &dwmmc_1;
+ mshc2 = &dwmmc_2;
+ mshc3 = &dwmmc_3;
+ };
+
+ memory {
+ reg = <0x40000000 0x80000000>;
+ };
+
+ chosen {
+ bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
+ };
+
+ i2c@12C60000 {
+ status = "okay";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ samsung,i2c-slave-addr = <0x66>;
+ gpios = <&gpb3 0 2 3 0>,
+ <&gpb3 1 2 3 0>;
+
+ s5m8767_pmic@66 {
+ compatible = "samsung,s5m8767-pmic";
+ reg = <0x66>;
+
+ s5m8767,pmic-buck2-dvs-voltage = <1300000>;
+ s5m8767,pmic-buck3-dvs-voltage = <1100000>;
+ s5m8767,pmic-buck4-dvs-voltage = <1200000>;
+ s5m8767,pmic-buck-dvs-gpios = <&gpd1 0 1 0 0>, /* DVS1 */
+ <&gpd1 1 1 0 0>, /* DVS2 */
+ <&gpd1 2 1 0 0>; /* DVS3 */
+ s5m8767,pmic-buck-ds-gpios = <&gpx2 3 1 0 0>, /* SET1 */
+ <&gpx2 4 1 0 0>, /* SET2 */
+ <&gpx2 5 1 0 0>; /* SET3 */
+ regulators {
+ ldo1_reg: LDO1 {
+ regulator-name = "VDD_ALIVE_1.0V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "VDD_28IO_DP_1.35V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "VDD_COMMON1_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "VDD_IOPERI_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-name = "VDD_EXT_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "VDD_MPLL_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo7_reg: LDO7 {
+ regulator-name = "VDD_XPLL_1.1V";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo8_reg: LDO8 {
+ regulator-name = "VDD_COMMON2_1.0V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo9_reg: LDO9 {
+ regulator-name = "VDD_33ON_3.0V";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-name = "VDD_COMMON3_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo11_reg: LDO11 {
+ regulator-name = "VDD_ABB2_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo12_reg: LDO12 {
+ regulator-name = "VDD_USB_3.0V";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo13_reg: LDO13 {
+ regulator-name = "VDDQ_C2C_W_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo14_reg: LDO14 {
+ regulator-name = "VDD18_ABB0/3_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo15_reg: LDO15 {
+ regulator-name = "VDD10_COMMON4_1.0V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo16_reg: LDO16 {
+ regulator-name = "VDD18_HSIC_1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo17_reg: LDO17 {
+ regulator-name = "VDDQ_MMC2/3_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ ldo18_reg: LDO18 {
+ regulator-name = "VDD_33ON_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck1_reg: BUCK1 {
+ regulator-name = "VDD_MIF_1.2V";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck3_reg: BUCK3 {
+ regulator-name = "VDD_INT_1.0V";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck4_reg: BUCK4 {
+ regulator-name = "VDD_G3D_1.0V";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ buck5_reg: BUCK5 {
+ regulator-name = "VDD_MEM_1.35V";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1355000>;
+ regulator-always-on;
+ regulator-boot-on;
+ op_mode = <1>; /* Normal Mode */
+ };
+
+ };
+ };
+ };
+
+ i2c@12C70000 {
+ status = "disabled";
+ };
+
+ i2c@12C80000 {
+ status = "disabled";
+ };
+
+ i2c@12C90000 {
+ status = "disabled";
+ };
+
+ i2c@12CA0000 {
+ status = "disabled";
+ };
+
+ i2c@12CB0000 {
+ status = "disabled";
+ };
+
+ i2c@12CC0000 {
+ status = "disabled";
+ };
+
+ i2c@12CD0000 {
+ status = "disabled";
+ };
+
+ i2c@121D0000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <40000>;
+ samsung,i2c-slave-addr = <0x38>;
+
+ sata-phy {
+ compatible = "samsung,sata-phy";
+ reg = <0x38>;
+ };
+ };
+
+ sata@122F0000 {
+ samsung,sata-freq = <66>;
+ };
+
+ dwmmc_0: dwmmc0@12200000 {
+ num-slots = <1>;
+ supports-highspeed;
+ broken-cd;
+ fifo-depth = <0x80>;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <8>;
+ gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+ <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+ <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
+ <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+ <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
+ };
+ };
+
+ dwmmc_1: dwmmc1@12210000 {
+ status = "disabled";
+ };
+ dwmmc_2: dwmmc2@12220000 {
+ num-slots = <1>;
+ supports-highspeed;
+ fifo-depth = <0x80>;
+ card-detect-delay = <200>;
+ samsung,dw-mshc-ciu-div = <3>;
+ samsung,dw-mshc-sdr-timing = <2 3>;
+ samsung,dw-mshc-ddr-timing = <1 2>;
+
+ slot@0 {
+ reg = <0>;
+ bus-width = <4>;
+ samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>;
+ gpios = <&gpc3 0 2 0 3>, <&gpc3 1 2 0 3>,
+ <&gpc3 3 2 3 3>, <&gpc3 4 2 3 3>,
+ <&gpc3 5 2 3 3>, <&gpc3 6 2 3 3>,
+ <&gpc4 3 3 3 3>, <&gpc4 3 3 3 3>,
+ <&gpc4 5 3 3 3>, <&gpc4 6 3 3 3>;
+ };
+ };
+
+ dwmmc_3: dwmmc3@12230000 {
+ status = "disabled";
+ };
+
+ spi_0: spi@12d20000 {
+ status = "disabled";
+ };
+
+ spi_1: spi@12d30000 {
+ status = "disabled";
+ };
+
+ spi_2: spi@12d40000 {
+ status = "disabled";
+ };
+
+ ehci {
+ samsung,hub-reset = <&gpx3 5 1 0 3>;
+ samsung,hub-connect = <&gpd1 7 1 0 3>;
+ };
+};
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 942d5761ca9..c5115c88941 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -204,4 +204,8 @@
samsung,mfc-r = <0x43000000 0x800000>;
samsung,mfc-l = <0x51000000 0x800000>;
};
+
+ ehci {
+ samsung,vbus-gpio = <&gpx2 6 1 3 3>;
+ };
};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 3acf594ea60..d166e61c754 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -69,6 +69,12 @@
<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
};
+ pmu {
+ compatible = "arm,cortex-a15-pmu";
+ interrupt-parent = <&combiner>;
+ interrupts = <1 2>, <22 4>;
+ };
+
watchdog {
compatible = "samsung,s3c2410-wdt";
reg = <0x101D0000 0x100>;
@@ -81,6 +87,29 @@
interrupts = <0 96 0>;
};
+ usbphy {
+ compatible = "samsung,exynos5250-usbphy";
+ reg = <0x12130000 0x100>, <0x12100000 0x100>;
+ };
+
+ usb@12000000 {
+ compatible = "samsung,exynos-dwc3";
+ reg = <0x12000000 0x10000>;
+ interrupts = <0 72 0>;
+ };
+
+ ohci {
+ compatible = "samsung,exynos-ohci";
+ reg = <0x12120000 0x100>;
+ interrupts = <0 71 0>;
+ };
+
+ ehci {
+ compatible = "samsung,exynos-ehci";
+ reg = <0x12110000 0x100>;
+ interrupts = <0 71 0>;
+ };
+
rtc {
compatible = "samsung,s3c6410-rtc";
reg = <0x101E0000 0x100>;
@@ -200,11 +229,11 @@
#size-cells = <0>;
};
- i2c@121D0000 {
- compatible = "samsung,exynos5-sata-phy-i2c";
- reg = <0x121D0000 0x100>;
- #address-cells = <1>;
- #size-cells = <0>;
+ i2c_sataphy: i2c@121D0000 {
+ compatible = "samsung,exynos5-sata-phy-i2c";
+ reg = <0x121D0000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
};
spi_0: spi@12d20000 {
@@ -269,6 +298,7 @@
#size-cells = <0>;
};
+
amba {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/configs/android_origen_defconfig b/arch/arm/configs/android_origen_defconfig
new file mode 100644
index 00000000000..eab7b5a5293
--- /dev/null
+++ b/arch/arm/configs/android_origen_defconfig
@@ -0,0 +1,210 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PERF_COUNTERS=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_GCOV_KERNEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S3C24XX_PWM=y
+CONFIG_MACH_SMDKC210=y
+CONFIG_MACH_ARMLEX4210=y
+CONFIG_MACH_UNIVERSAL_C210=y
+CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=y
+CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_ACCT=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UNIDISPLAY_TS=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_S3C2410=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_SENSORS_EXYNOS4_TMU=y
+CONFIG_MFD_MAX8997=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_FIMC=y
+CONFIG_VIDEO_S5P_FIMC=y
+CONFIG_VIDEO_SAMSUNG_S5P_TV=y
+CONFIG_VIDEO_SAMSUNG_S5P_HDMI=y
+CONFIG_VIDEO_SAMSUNG_S5P_SDO=y
+CONFIG_VIDEO_SAMSUNG_S5P_MIXER=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=y
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=y
+CONFIG_DRM=y
+CONFIG_ION=y
+CONFIG_MALI400MP=y
+CONFIG_USING_PMM=y
+CONFIG_UMP=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LCD_PWRCTRL=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_HID_KYE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_S3C_HSOTG=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_PERSISTENT_TRACER=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_SWITCH=y
+CONFIG_SND_SOC_ORIGEN_ALC5625=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_PSTORE=y
+CONFIG_PSTORE_RAM=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/arndale_ubuntu_defconfig b/arch/arm/configs/arndale_ubuntu_defconfig
new file mode 100644
index 00000000000..230ca41d786
--- /dev/null
+++ b/arch/arm/configs/arndale_ubuntu_defconfig
@@ -0,0 +1,129 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+# CONFIG_ARCH_EXYNOS4 is not set
+CONFIG_ARCH_EXYNOS5=y
+CONFIG_ARM_LPAE=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=2
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init= mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IPV6=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_IPV6_SIT=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_EXYNOS=y
+CONFIG_NETDEVICES=y
+CONFIG_AX88796=y
+CONFIG_AX88796_93CX6=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+CONFIG_USB_USBNET=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_EXYNOS_THERMAL=y
+CONFIG_MFD_SEC_CORE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_HID_LOGITECH_DJ=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_SAMSUNG_USBPHY=y
+CONFIG_USB_GADGET=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_DW_EXYNOS=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_DEBUG=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_S3C_UART2=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig
index bffe68e190a..62dd948ecac 100644
--- a/arch/arm/configs/exynos4_defconfig
+++ b/arch/arm/configs/exynos4_defconfig
@@ -5,43 +5,154 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_EXYNOS=y
-CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S3C24XX_PWM=y
CONFIG_MACH_SMDKC210=y
CONFIG_MACH_ARMLEX4210=y
CONFIG_MACH_UNIVERSAL_C210=y
CONFIG_MACH_NURI=y
CONFIG_MACH_ORIGEN=y
CONFIG_MACH_SMDK4412=y
+CONFIG_MACH_EXYNOS4_DT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
CONFIG_NR_CPUS=2
CONFIG_PREEMPT=y
CONFIG_AEABI=y
-CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IPV6=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UNIDISPLAY_TS=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_I2C=y
+CONFIG_I2C_S3C2410=y
+CONFIG_POWER_SUPPLY=y
# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_MFD_MAX8997=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_FIMC=y
+CONFIG_VIDEO_S5P_FIMC=y
+CONFIG_VIDEO_SAMSUNG_S5P_TV=y
+CONFIG_VIDEO_SAMSUNG_S5P_HDMI=y
+CONFIG_VIDEO_SAMSUNG_S5P_SDO=y
+CONFIG_VIDEO_SAMSUNG_S5P_MIXER=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=y
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LCD_PWRCTRL=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_S3C_HSOTG=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_G_DBGP_PRINTK=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_STAGING=y
+CONFIG_SND_SOC_ORIGEN_ALC5625=y
CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
@@ -54,7 +165,9 @@ CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_RT_MUTEXES=y
@@ -63,6 +176,4 @@ CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_INFO=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/ubuntu_origen_defconfig b/arch/arm/configs/ubuntu_origen_defconfig
new file mode 100644
index 00000000000..6bcf64c06db
--- /dev/null
+++ b/arch/arm/configs/ubuntu_origen_defconfig
@@ -0,0 +1,241 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_S3C24XX_PWM=y
+CONFIG_MACH_SMDKC210=y
+CONFIG_MACH_ARMLEX4210=y
+CONFIG_MACH_UNIVERSAL_C210=y
+CONFIG_MACH_NURI=y
+CONFIG_MACH_ORIGEN=y
+CONFIG_MACH_SMDK4412=y
+CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_NR_CPUS=2
+CONFIG_THUMB2_KERNEL=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_NETLABEL=y
+CONFIG_NETFILTER=y
+CONFIG_CFG80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_NAND=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_ATH_COMMON=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_PLATFORM_DATA=y
+CONFIG_ATH6KL_POLL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_UNIDISPLAY_TS=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_S3C2410=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_SENSORS_EXYNOS4_TMU=y
+CONFIG_MFD_MAX8997=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_MAX8997=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_FIMC=y
+CONFIG_VIDEO_S5P_FIMC=y
+CONFIG_VIDEO_SAMSUNG_S5P_TV=y
+CONFIG_VIDEO_SAMSUNG_S5P_HDMI=y
+CONFIG_VIDEO_SAMSUNG_S5P_SDO=y
+CONFIG_VIDEO_SAMSUNG_S5P_MIXER=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_G2D=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=y
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=y
+CONFIG_FB=y
+CONFIG_FB_S3C=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_LCD_PWRCTRL=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_S3C_HSOTG=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_G_DBGP_PRINTK=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_STAGING=y
+CONFIG_SND_SOC_ORIGEN_ALC5625=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_BTRFS_FS=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_DEBUG_USER=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_LSM_MMAP_MIN_ADDR=0
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_DEFAULT_SECURITY_APPARMOR=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC7=y
diff --git a/arch/arm/include/asm/hugetlb-2level.h b/arch/arm/include/asm/hugetlb-2level.h
new file mode 100644
index 00000000000..3532b54bcfd
--- /dev/null
+++ b/arch/arm/include/asm/hugetlb-2level.h
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/include/asm/hugetlb-2level.h
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * Based on arch/x86/include/asm/hugetlb.h and Bill Carson's patches
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ASM_ARM_HUGETLB_2LEVEL_H
+#define _ASM_ARM_HUGETLB_2LEVEL_H
+
+
+pte_t huge_ptep_get(pte_t *ptep);
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+
+static inline pte_t pte_mkhuge(pte_t pte) { return pte; }
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *) ptep;
+ set_pmd_at(mm, addr, pmdp, pmd_wrprotect(*pmdp));
+}
+
+
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t *)ptep;
+ pte_t pte = huge_ptep_get(ptep);
+ pmd_clear(pmdp);
+
+ return pte;
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ int changed = !pte_same(huge_ptep_get(ptep), pte);
+
+ if (changed) {
+ set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+ huge_ptep_clear_flush(vma, addr, &pte);
+ }
+
+ return changed;
+}
+
+#endif /* _ASM_ARM_HUGETLB_2LEVEL_H */
diff --git a/arch/arm/include/asm/hugetlb-3level.h b/arch/arm/include/asm/hugetlb-3level.h
new file mode 100644
index 00000000000..486806445c3
--- /dev/null
+++ b/arch/arm/include/asm/hugetlb-3level.h
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/include/asm/hugetlb-3level.h
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * Based on arch/x86/include/asm/hugetlb.h.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ASM_ARM_HUGETLB_3LEVEL_H
+#define _ASM_ARM_HUGETLB_3LEVEL_H
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+ return *ptep;
+}
+
+static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ set_pte_at(mm, addr, ptep, pte);
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ ptep_clear_flush(vma, addr, ptep);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ ptep_set_wrprotect(mm, addr, ptep);
+}
+
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ return ptep_get_and_clear(mm, addr, ptep);
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+}
+
+#endif /* _ASM_ARM_HUGETLB_3LEVEL_H */
diff --git a/arch/arm/include/asm/hugetlb.h b/arch/arm/include/asm/hugetlb.h
new file mode 100644
index 00000000000..1e92975f6c1
--- /dev/null
+++ b/arch/arm/include/asm/hugetlb.h
@@ -0,0 +1,87 @@
+/*
+ * arch/arm/include/asm/hugetlb.h
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * Based on arch/x86/include/asm/hugetlb.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _ASM_ARM_HUGETLB_H
+#define _ASM_ARM_HUGETLB_H
+
+#include <asm/page.h>
+
+#ifdef CONFIG_ARM_LPAE
+#include <asm/hugetlb-3level.h>
+#else
+#include <asm/hugetlb-2level.h>
+#endif
+
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
+ unsigned long addr, unsigned long end,
+ unsigned long floor,
+ unsigned long ceiling)
+{
+ free_pgd_range(tlb, addr, end, floor, ceiling);
+}
+
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+ unsigned long addr, unsigned long len)
+{
+ return 0;
+}
+
+static inline int prepare_hugepage_range(struct file *file,
+ unsigned long addr, unsigned long len)
+{
+ struct hstate *h = hstate_file(file);
+ if (len & ~huge_page_mask(h))
+ return -EINVAL;
+ if (addr & ~huge_page_mask(h))
+ return -EINVAL;
+ return 0;
+}
+
+static inline void hugetlb_prefault_arch_hook(struct mm_struct *mm)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+ return pte_none(pte);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+ return pte_wrprotect(pte);
+}
+
+static inline int arch_prepare_hugepage(struct page *page)
+{
+ return 0;
+}
+
+static inline void arch_release_hugepage(struct page *page)
+{
+}
+
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+ clear_bit(PG_dcache_clean, &page->flags);
+}
+
+#endif /* _ASM_ARM_HUGETLB_H */
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 73cf03aa981..485c3154ba8 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -18,6 +18,9 @@
#include <linux/types.h>
#include <linux/sizes.h>
+#include <asm/cache.h>
+#include <asm/runtime-patch.h>
+
#ifdef CONFIG_NEED_MACH_MEMORY_H
#include <mach/memory.h>
#endif
@@ -99,11 +102,11 @@
#endif
#ifndef PHYS_OFFSET
-#define PHYS_OFFSET UL(CONFIG_DRAM_BASE)
+#define PHYS_OFFSET UL(CONFIG_DRAM_BASE)
#endif
#ifndef END_MEM
-#define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
+#define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
#endif
#ifndef PAGE_OFFSET
@@ -141,6 +144,20 @@
#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
+/*
+ * Minimum guaranted alignment in pgd_alloc(). The page table pointers passed
+ * around in head.S and proc-*.S are shifted by this amount, in order to
+ * leave spare high bits for systems with physical address extension. This
+ * does not fully accomodate the 40-bit addressing capability of ARM LPAE, but
+ * gives us about 38-bits or so.
+ */
+#ifdef CONFIG_ARM_LPAE
+#define ARCH_PGD_SHIFT L1_CACHE_SHIFT
+#else
+#define ARCH_PGD_SHIFT 0
+#endif
+#define ARCH_PGD_MASK ((1 << ARCH_PGD_SHIFT) - 1)
+
#ifndef __ASSEMBLY__
/*
@@ -151,40 +168,70 @@
#ifndef __virt_to_phys
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
-/*
- * Constants used to force the right instruction encodings and shifts
- * so that all we need to do is modify the 8-bit constant field.
- */
-#define __PV_BITS_31_24 0x81000000
+extern unsigned long __pv_offset;
+extern phys_addr_t __pv_phys_offset;
+#define PHYS_OFFSET __virt_to_phys(PAGE_OFFSET)
-extern unsigned long __pv_phys_offset;
-#define PHYS_OFFSET __pv_phys_offset
+static inline phys_addr_t __virt_to_phys(unsigned long x)
+{
+ phys_addr_t t;
-#define __pv_stub(from,to,instr,type) \
- __asm__("@ __pv_stub\n" \
- "1: " instr " %0, %1, %2\n" \
- " .pushsection .pv_table,\"a\"\n" \
- " .long 1b\n" \
- " .popsection\n" \
- : "=r" (to) \
- : "r" (from), "I" (type))
+#ifndef CONFIG_ARM_LPAE
+ early_patch_imm8("add", t, x, __pv_offset, 0);
+#else
+ unsigned long __tmp;
-static inline unsigned long __virt_to_phys(unsigned long x)
-{
- unsigned long t;
- __pv_stub(x, t, "add", __PV_BITS_31_24);
+#ifndef __ARMEB__
+#define PV_PHYS_HIGH "(__pv_phys_offset + 4)"
+#else
+#define PV_PHYS_HIGH "__pv_phys_offset"
+#endif
+
+ early_patch_stub(
+ /* type */ PATCH_IMM8,
+ /* code */
+ "ldr %[tmp], =__pv_offset\n"
+ "ldr %[tmp], [%[tmp]]\n"
+ "add %Q[to], %[from], %[tmp]\n"
+ "ldr %[tmp], =" PV_PHYS_HIGH "\n"
+ "ldr %[tmp], [%[tmp]]\n"
+ "mov %R[to], %[tmp]\n",
+ /* pad */ 4,
+ /* patch_data */
+ ".long __pv_offset\n"
+ "add %Q[to], %[from], %[imm]\n"
+ ".long " PV_PHYS_HIGH "\n"
+ "mov %R[to], %[imm]\n",
+ /* operands */
+ : [to] "=r" (t),
+ [tmp] "=&r" (__tmp)
+ : [from]"r" (x),
+ [imm] "I" (__IMM8),
+ "i" (&__pv_offset),
+ "i" (&__pv_phys_offset));
+#endif
return t;
}
-static inline unsigned long __phys_to_virt(unsigned long x)
+static inline unsigned long __phys_to_virt(phys_addr_t x)
{
- unsigned long t;
- __pv_stub(x, t, "sub", __PV_BITS_31_24);
+ unsigned long t, xlo = x;
+ early_patch_imm8("sub", t, xlo, __pv_offset, 0);
return t;
}
+
#else
-#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
-#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
+
+static inline phys_addr_t __virt_to_phys(unsigned long x)
+{
+ return (phys_addr_t)x - PAGE_OFFSET + PHYS_OFFSET;
+}
+
+static inline unsigned long __phys_to_virt(phys_addr_t x)
+{
+ return x - PHYS_OFFSET + PAGE_OFFSET;
+}
+
#endif
#endif
#endif /* __ASSEMBLY__ */
@@ -222,14 +269,14 @@ static inline phys_addr_t virt_to_phys(const volatile void *x)
static inline void *phys_to_virt(phys_addr_t x)
{
- return (void *)(__phys_to_virt((unsigned long)(x)));
+ return (void *)__phys_to_virt(x);
}
/*
* Drivers should NOT use these either.
*/
#define __pa(x) __virt_to_phys((unsigned long)(x))
-#define __va(x) ((void *)__phys_to_virt((unsigned long)(x)))
+#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x)))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
/*
@@ -279,4 +326,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#include <asm-generic/memory_model.h>
+#define ARCH_LOW_ADDRESS_LIMIT PHYS_MASK
+
#endif
diff --git a/arch/arm/include/asm/mmzone.h b/arch/arm/include/asm/mmzone.h
new file mode 100644
index 00000000000..628e5035659
--- /dev/null
+++ b/arch/arm/include/asm/mmzone.h
@@ -0,0 +1,49 @@
+/*
+ * Discontiguous memory and NUMA support, based on the PowerPC implementation.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __ASM_ARM_MMZONE_H_
+#define __ASM_ARM_MMZONE_H_
+#ifdef __KERNEL__
+
+#include <linux/cpumask.h>
+
+#ifdef CONFIG_NUMA_ALLOC_NODES
+#define NODE_DATA(nid) (node_data[nid])
+extern void __init arm_numa_alloc_nodes(unsigned long max_low);
+extern struct pglist_data *node_data[];
+#else
+#define arm_numa_alloc_nodes(_mlow) do {} while (0)
+#endif
+
+#ifdef CONFIG_NUMA
+extern cpumask_var_t *node_to_cpumask_map;
+extern int numa_cpu_lookup_table[];
+extern int pfn_to_nid(unsigned long pfn);
+extern void __init arm_setup_nodes(unsigned long min, unsigned long max_high);
+extern void __init arm_numa_alloc_cpumask(unsigned long max_low);
+#else
+#define pfn_to_nid(pfn) (0)
+#define arm_setup_nodes(min, max_high) memblock_set_node( \
+ __pfn_to_phys(min), \
+ __pfn_to_phys(max_high - min), 0)
+#define arm_numa_alloc_cpumask(max_low) do {} while (0)
+#endif /* CONFIG_NUMA */
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_ARM_MMZONE_H_ */
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 0d3a28dbc8e..c4ebe522ca4 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -39,9 +39,16 @@ struct mod_arch_specific {
#define MODULE_ARCH_VERMAGIC_ARMTHUMB ""
#endif
+#ifdef CONFIG_ARM_RUNTIME_PATCH
+#define MODULE_ARCH_VERMAGIC_RT_PATCH "rt-patch "
+#else
+#define MODULE_ARCH_VERMAGIC_RT_PATCH ""
+#endif
+
#define MODULE_ARCH_VERMAGIC \
MODULE_ARCH_VERMAGIC_ARMVSN \
MODULE_ARCH_VERMAGIC_ARMTHUMB \
+ MODULE_ARCH_VERMAGIC_RT_PATCH \
MODULE_ARCH_VERMAGIC_P2V
#endif /* _ASM_ARM_MODULE_H */
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index 812a4944e78..6363f3d1d50 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -13,7 +13,7 @@
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index f97ee02386e..eb1640ed2a5 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -127,6 +127,11 @@
#define L_PTE_NONE (_AT(pteval_t, 1) << 11)
/*
+ * for 2 levels of paging we don't mask off any bits when comparing present ptes
+ */
+#define L_PTE_CMP_MASKOFF 0
+
+/*
* These are the memory types, defined to be compatible with
* pre-ARMv6 CPUs cacheable and bufferable bits: XXCB
*/
@@ -160,7 +165,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
return (pmd_t *)pud;
}
-#define pmd_bad(pmd) (pmd_val(pmd) & 2)
+#define pmd_bad(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_FAULT)
#define copy_pmd(pmdpd,pmdps) \
do { \
@@ -176,11 +181,156 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
clean_pmd_entry(pmdp); \
} while (0)
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define _PMD_HUGE(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+#else
+#define _PMD_HUGE(pmd) (0)
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
/* we don't need complex calculations here as the pmd is folded into the pgd */
#define pmd_addr_end(addr,end) (end)
+#define pmd_present(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) != PMD_TYPE_FAULT)
+
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
+
+#ifdef CONFIG_SYS_SUPPORTS_HUGETLBFS
+
+/*
+ * now follows some of the definitions to allow huge page support, we can't put
+ * these in the hugetlb source files as they are also required for transparent
+ * hugepage support.
+ */
+
+#define HPAGE_SHIFT PMD_SHIFT
+#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+
+#define HUGE_LINUX_PTE_COUNT (PAGE_OFFSET >> HPAGE_SHIFT)
+#define HUGE_LINUX_PTE_SIZE (HUGE_LINUX_PTE_COUNT * sizeof(pte_t *))
+#define HUGE_LINUX_PTE_INDEX(addr) (addr >> HPAGE_SHIFT)
+
+/*
+ * We re-purpose the following domain bits in the section descriptor
+ */
+#define PMD_DSECT_DIRTY (_AT(pmdval_t, 1) << 5)
+#define PMD_DSECT_AF (_AT(pmdval_t, 1) << 6)
+#define PMD_DSECT_SPLITTING (_AT(pmdval_t, 1) << 7)
+
+#define PMD_BIT_FUNC(fn,op) \
+static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
+
+PMD_BIT_FUNC(wrprotect, &= ~PMD_SECT_AP_WRITE);
+
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd)
+{
+ /*
+ * we can sometimes be passed a pmd pointing to a level 2 descriptor
+ * from collapse_huge_page.
+ */
+ if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) {
+ pmdp[0] = __pmd(pmd_val(pmd));
+ pmdp[1] = __pmd(pmd_val(pmd) + 256 * sizeof(pte_t));
+ } else {
+ pmdp[0] = __pmd(pmd_val(pmd)); /* first 1M section */
+ pmdp[1] = __pmd(pmd_val(pmd) + SECTION_SIZE); /* second 1M section */
+ }
+
+ flush_pmd_entry(pmdp);
+}
+
+#define HPMD_XLATE(res, cmp, from, to) do { if (cmp & from) res |= to; \
+ else res &= ~to; \
+ } while (0)
+
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+ pmdval_t pmdval = pmd_val(pmd);
+ pteval_t newprotval = pgprot_val(newprot);
+
+ HPMD_XLATE(pmdval, newprotval, L_PTE_XN, PMD_SECT_XN);
+ HPMD_XLATE(pmdval, newprotval, L_PTE_SHARED, PMD_SECT_S);
+ HPMD_XLATE(pmdval, newprotval, L_PTE_YOUNG, PMD_DSECT_AF);
+ HPMD_XLATE(pmdval, newprotval, L_PTE_DIRTY, PMD_DSECT_DIRTY);
+
+ /* preserve bits C & B */
+ pmdval |= (newprotval & (3 << 2));
+
+ /* Linux PTE bit 4 corresponds to PMD TEX bit 0 */
+ HPMD_XLATE(pmdval, newprotval, 1 << 4, PMD_SECT_TEX(1));
+
+ if (newprotval & L_PTE_RDONLY)
+ pmdval &= ~PMD_SECT_AP_WRITE;
+ else
+ pmdval |= PMD_SECT_AP_WRITE;
+
+ return __pmd(pmdval);
+}
+
+#else
+#define HPAGE_SIZE 0
+#endif /* CONFIG_SYS_SUPPORTS_HUGETLBFS */
+
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define pmd_mkhuge(pmd) (__pmd((pmd_val(pmd) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT))
+
+PMD_BIT_FUNC(mkold, &= ~PMD_DSECT_AF);
+PMD_BIT_FUNC(mksplitting, |= PMD_DSECT_SPLITTING);
+PMD_BIT_FUNC(mkdirty, |= PMD_DSECT_DIRTY);
+PMD_BIT_FUNC(mkyoung, |= PMD_DSECT_AF);
+PMD_BIT_FUNC(mkwrite, |= PMD_SECT_AP_WRITE);
+PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
+
+#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_DSECT_SPLITTING)
+#define pmd_young(pmd) (pmd_val(pmd) & PMD_DSECT_AF)
+#define pmd_write(pmd) (pmd_val(pmd) & PMD_SECT_AP_WRITE)
+#define pmd_trans_huge(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+ /*
+ * for a section, we need to mask off more of the pmd
+ * before looking up the pfn
+ */
+ if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+ return __phys_to_pfn(pmd_val(pmd) & HPAGE_MASK);
+ else
+ return __phys_to_pfn(pmd_val(pmd) & PHYS_MASK);
+}
+
+static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
+{
+ pmd_t pmd = __pmd(__pfn_to_phys(pfn) | PMD_SECT_AP_READ | PMD_SECT_nG);
+
+ return pmd_modify(pmd, prot);
+}
+
+#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot);
+
+static inline int has_transparent_hugepage(void)
+{
+ return 1;
+}
+
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
+static inline struct page *pmd_page(pmd_t pmd)
+{
+ /*
+ * for a section, we need to mask off more of the pmd
+ * before looking up the page as it is a section descriptor.
+ */
+ if (_PMD_HUGE(pmd))
+ return phys_to_page(pmd_val(pmd) & HPAGE_MASK);
+
+ return phys_to_page(pmd_val(pmd) & PHYS_MASK);
+}
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_PGTABLE_2LEVEL_H */
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h
index d7952824c5c..bf1707f0239 100644
--- a/arch/arm/include/asm/pgtable-3level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-3level-hwdef.h
@@ -38,6 +38,8 @@
*/
#define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2)
#define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3)
+#define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */
+#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */
#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
#define PMD_SECT_AF (_AT(pmdval_t, 1) << 10)
#define PMD_SECT_nG (_AT(pmdval_t, 1) << 11)
@@ -74,4 +76,14 @@
#define PHYS_MASK_SHIFT (40)
#define PHYS_MASK ((1ULL << PHYS_MASK_SHIFT) - 1)
+#if defined CONFIG_VMSPLIT_2G
+#define TTBR1_OFFSET (1 << 4) /* skip two L1 entries */
+#elif defined CONFIG_VMSPLIT_3G
+#define TTBR1_OFFSET (4096 * (1 + 3)) /* only L2, skip pgd + 3*pmd */
+#else
+#define TTBR1_OFFSET 0
+#endif
+
+#define TTBR1_SIZE (((PAGE_OFFSET >> 30) - 1) << 16)
+
#endif
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index a3f37929940..3c2432fe5e6 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -48,20 +48,28 @@
#define PMD_SHIFT 21
#define PMD_SIZE (1UL << PMD_SHIFT)
-#define PMD_MASK (~(PMD_SIZE-1))
+#define PMD_MASK (~((1 << PMD_SHIFT) - 1))
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
+#define PGDIR_MASK (~((1 << PGDIR_SHIFT) - 1))
/*
* section address mask and size definitions.
*/
#define SECTION_SHIFT 21
#define SECTION_SIZE (1UL << SECTION_SHIFT)
-#define SECTION_MASK (~(SECTION_SIZE-1))
+#define SECTION_MASK (~((1 << SECTION_SHIFT) - 1))
#define USER_PTRS_PER_PGD (PAGE_OFFSET / PGDIR_SIZE)
/*
+ * Hugetlb definitions.
+ */
+#define HPAGE_SHIFT PMD_SHIFT
+#define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+
+/*
* "Linux" PTE definitions for LPAE.
*
* These bits overlap with the hardware bits but the naming is preserved for
@@ -79,6 +87,9 @@
#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */
#define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */
+#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
+#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57)
+
/*
* To be used in assembly code with the upper page attributes.
*/
@@ -86,6 +97,11 @@
#define L_PTE_DIRTY_HIGH (1 << (55 - 32))
/*
+ * we need to mask off PTE_EXT_NG when comparing present ptes.
+ */
+#define L_PTE_CMP_MASKOFF PTE_EXT_NG
+
+/*
* AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
*/
#define L_PTE_MT_UNCACHED (_AT(pteval_t, 0) << 2) /* strongly ordered */
@@ -150,6 +166,67 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,__pte(pte_val(pte)|(ext)))
+#define pte_huge(pte) ((pte_val(pte) & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+
+#define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT))
+
+
+#define pmd_present(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) != PMD_TYPE_FAULT)
+#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF)
+
+#define __HAVE_ARCH_PMD_WRITE
+#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY))
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define pmd_trans_huge(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
+#endif
+
+#define PMD_BIT_FUNC(fn,op) \
+static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
+
+PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY);
+PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
+PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
+PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY);
+PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY);
+PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
+PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
+
+#define pmd_mkhuge(pmd) (__pmd((pmd_val(pmd) & ~PMD_TYPE_MASK) | PMD_TYPE_SECT))
+
+#define pmd_pfn(pmd) ((pmd_val(pmd) & PHYS_MASK) >> PAGE_SHIFT)
+#define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
+
+#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
+
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+ const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY;
+ pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
+ return pmd;
+}
+
+static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+ *pmdp = pmd;
+}
+
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd)
+{
+ BUG_ON(addr >= TASK_SIZE);
+ pmd = __pmd(pmd_val(pmd) | PMD_SECT_nG);
+ set_pmd(pmdp, pmd);
+ flush_pmd_entry(pmdp);
+}
+
+static inline int has_transparent_hugepage(void)
+{
+ return 1;
+}
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_PGTABLE_3LEVEL_H */
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 9c82f988c0e..529ceae8d98 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -24,6 +24,9 @@
#include <asm/memory.h>
#include <asm/pgtable-hwdef.h>
+
+#include <asm/tlbflush.h>
+
#ifdef CONFIG_ARM_LPAE
#include <asm/pgtable-3level.h>
#else
@@ -163,15 +166,17 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
#define pmd_none(pmd) (!pmd_val(pmd))
-#define pmd_present(pmd) (pmd_val(pmd))
static inline pte_t *pmd_page_vaddr(pmd_t pmd)
{
+#ifdef SYS_SUPPORTS_HUGETLBFS
+ if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+ return __va(pmd_val(pmd) & HPAGE_MASK);
+#endif
+
return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
}
-#define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
-
#ifndef CONFIG_HIGHPTE
#define __pte_map(pmd) pmd_page_vaddr(*(pmd))
#define __pte_unmap(pte) do { } while (0)
@@ -246,6 +251,29 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
}
/*
+ * For 3 levels of paging the PTE_EXT_NG bit will be set for user address ptes
+ * that are written to a page table but not for ptes created with mk_pte.
+ *
+ * This can cause some comparison tests made by pte_same to fail spuriously and
+ * lead to other problems.
+ *
+ * To correct this behaviour, we mask off PTE_EXT_NG for any pte that is
+ * present before running the comparison.
+ */
+#define __HAVE_ARCH_PTE_SAME
+static inline int pte_same(pte_t pte_a, pte_t pte_b)
+{
+ pteval_t vala = pte_val(pte_a), valb = pte_val(pte_b);
+ if (pte_present(pte_a))
+ vala &= ~L_PTE_CMP_MASKOFF;
+
+ if (pte_present(pte_b))
+ valb &= ~L_PTE_CMP_MASKOFF;
+
+ return vala == valb;
+}
+
+/*
* Encode and decode a swap entry. Swap entries are stored in the Linux
* page tables as follows:
*
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index f3628fb3d2b..2d270b8c6e1 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -60,7 +60,7 @@ extern struct processor {
/*
* Set the page table
*/
- void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
+ void (*switch_mm)(phys_addr_t pgd_phys, struct mm_struct *mm);
/*
* Set a possibly extended PTE. Non-extended PTEs should
* ignore 'ext'.
@@ -82,7 +82,7 @@ extern void cpu_proc_init(void);
extern void cpu_proc_fin(void);
extern int cpu_do_idle(void);
extern void cpu_dcache_clean_area(void *, int);
-extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
#ifdef CONFIG_ARM_LPAE
extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
#else
@@ -116,13 +116,27 @@ extern void cpu_resume(void);
#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
#ifdef CONFIG_ARM_LPAE
+
+#define cpu_get_ttbr(nr) \
+ ({ \
+ u64 ttbr; \
+ __asm__("mrrc p15, " #nr ", %Q0, %R0, c2" \
+ : "=r" (ttbr) \
+ : : ); \
+ ttbr; \
+ })
+
+#define cpu_set_ttbr(nr, val) \
+ do { \
+ u64 ttbr = val; \
+ __asm__("mcrr p15, " #nr ", %Q0, %R0, c2" \
+ : : "r" (ttbr) \
+ : "cc"); \
+ } while (0)
+
#define cpu_get_pgd() \
({ \
- unsigned long pg, pg2; \
- __asm__("mrrc p15, 0, %0, %1, c2" \
- : "=r" (pg), "=r" (pg2) \
- : \
- : "cc"); \
+ u64 pg = cpu_get_ttbr(0); \
pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \
(pgd_t *)phys_to_virt(pg); \
})
diff --git a/arch/arm/include/asm/runtime-patch.h b/arch/arm/include/asm/runtime-patch.h
new file mode 100644
index 00000000000..366444d7eef
--- /dev/null
+++ b/arch/arm/include/asm/runtime-patch.h
@@ -0,0 +1,208 @@
+/*
+ * arch/arm/include/asm/runtime-patch.h
+ * Note: this file should not be included by non-asm/.h files
+ *
+ * Copyright 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_RUNTIME_PATCH_H
+#define __ASM_ARM_RUNTIME_PATCH_H
+
+#include <linux/stringify.h>
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_ARM_RUNTIME_PATCH
+
+struct patch_info {
+ void *insn;
+ u16 type;
+ u8 insn_size;
+ u8 data_size;
+ u32 data[0];
+};
+
+#define PATCH_IMM8 0x0001
+struct patch_info_imm8 {
+ u32 *imm;
+ u32 insn;
+};
+
+#define patch_next(p) ((void *)(p) + sizeof(*(p)) + (p)->data_size)
+#define patch_data(p) ((void *)&(p)->data[0])
+
+#define patch_stub(type, code, patch_data, ...) \
+ __asm__("@ patch stub\n" \
+ "1:\n" \
+ code \
+ "2:\n" \
+ " .pushsection .runtime.patch.table, \"a\"\n" \
+ "3:\n" \
+ " .word 1b\n" \
+ " .hword (" __stringify(type) ")\n" \
+ " .byte (2b-1b)\n" \
+ " .byte (5f-4f)\n" \
+ "4:\n" \
+ patch_data \
+ " .align\n" \
+ "5:\n" \
+ " .popsection\n" \
+ __VA_ARGS__)
+
+#define early_patch_stub(type, code, pad, patch_data, ...) \
+ __asm__("@ patch stub\n" \
+ "1:\n" \
+ " b 6f\n" \
+ " .fill " __stringify(pad) ", 1, 0\n" \
+ "2:\n" \
+ " .pushsection .runtime.patch.table, \"a\"\n" \
+ "3:\n" \
+ " .word 1b\n" \
+ " .hword (" __stringify(type) ")\n" \
+ " .byte (2b-1b)\n" \
+ " .byte (5f-4f)\n" \
+ "4:\n" \
+ patch_data \
+ " .align\n" \
+ "5:\n" \
+ " .popsection\n" \
+ " .pushsection .runtime.patch.code, \"ax\"\n" \
+ "6:\n" \
+ code \
+ " b 2b\n" \
+ " .popsection\n" \
+ __VA_ARGS__)
+
+/* constant used to force encoding */
+#define __IMM8 (0x81 << 24)
+
+/*
+ * patch_imm8() - init-time specialized binary operation (imm8 operand)
+ * This effectively does: to = from "insn" sym,
+ * where the value of sym is fixed at init-time, and is patched
+ * in as an immediate operand. This value must be
+ * representible as an 8-bit quantity with an optional
+ * rotation.
+ *
+ * The stub code produced by this variant is non-functional
+ * prior to patching. Use early_patch_imm8() if you need the
+ * code to be functional early on in the init sequence.
+ */
+#define patch_imm8(_insn, _to, _from, _sym, _ofs) \
+ patch_stub( \
+ /* type */ \
+ PATCH_IMM8, \
+ /* code */ \
+ _insn " %[to], %[from], %[imm]\n", \
+ /* patch_data */ \
+ ".long " __stringify(_sym + _ofs) "\n" \
+ _insn " %[to], %[from], %[imm]\n", \
+ /* operands */ \
+ : [to] "=r" (_to) \
+ : [from] "r" (_from), \
+ [imm] "I" (__IMM8), \
+ "i" (&(_sym)) \
+ : "cc")
+
+/*
+ * patch_imm8_mov() - same as patch_imm8(), but for mov/mvn instructions
+ */
+#define patch_imm8_mov(_insn, _to, _sym, _ofs) \
+ patch_stub( \
+ /* type */ \
+ PATCH_IMM8, \
+ /* code */ \
+ _insn " %[to], %[imm]\n", \
+ /* patch_data */ \
+ ".long " __stringify(_sym + _ofs) "\n" \
+ _insn " %[to], %[imm]\n", \
+ /* operands */ \
+ : [to] "=r" (_to) \
+ : [imm] "I" (__IMM8), \
+ "i" (&(_sym)) \
+ : "cc")
+
+/*
+ * early_patch_imm8() - early functional variant of patch_imm8() above. The
+ * same restrictions on the constant apply here. This
+ * version emits workable (albeit inefficient) code at
+ * compile-time, and therefore functions even prior to
+ * patch application.
+ */
+#define early_patch_imm8(_insn, _to, _from, _sym, _ofs) \
+do { \
+ unsigned long __tmp; \
+ early_patch_stub( \
+ /* type */ \
+ PATCH_IMM8, \
+ /* code */ \
+ "ldr %[tmp], =" __stringify(_sym + _ofs) "\n"\
+ "ldr %[tmp], [%[tmp]]\n" \
+ _insn " %[to], %[from], %[tmp]\n", \
+ /* pad */ \
+ 0, \
+ /* patch_data */ \
+ ".long " __stringify(_sym + _ofs) "\n" \
+ _insn " %[to], %[from], %[imm]\n", \
+ /* operands */ \
+ : [to] "=r" (_to), \
+ [tmp] "=&r" (__tmp) \
+ : [from] "r" (_from), \
+ [imm] "I" (__IMM8), \
+ "i" (&(_sym)) \
+ : "cc"); \
+} while (0)
+
+#define early_patch_imm8_mov(_insn, _to, _sym, _ofs) \
+do { \
+ unsigned long __tmp; \
+ early_patch_stub( \
+ /* type */ \
+ PATCH_IMM8 \
+ /* code */ \
+ "ldr %[tmp], =" __stringify(_sym + _ofs) "\n"\
+ "ldr %[tmp], [%[tmp]]\n" \
+ _insn " %[to], %[tmp]\n", \
+ /* pad */ \
+ 0, \
+ /* patch_data */ \
+ ".long " __stringify(_sym + _ofs) "\n" \
+ _insn " %[to], %[imm]\n", \
+ /* operands */ \
+ : [to] "=r" (_to), \
+ [tmp] "=&r" (__tmp) \
+ : [imm] "I" (__IMM8), \
+ "i" (&(_sym)) \
+ : "cc"); \
+} while (0)
+
+int runtime_patch(const void *table, unsigned size);
+void runtime_patch_kernel(void);
+
+#else
+
+static inline int runtime_patch(const void *table, unsigned size)
+{
+ return 0;
+}
+
+static inline void runtime_patch_kernel(void)
+{
+}
+
+#endif /* CONFIG_ARM_RUNTIME_PATCH */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARM_RUNTIME_PATCH_H */
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index 99a19512ee2..0fc2d9d3503 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -92,10 +92,16 @@ static inline void tlb_flush(struct mmu_gather *tlb)
static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr)
{
if (!tlb->fullmm) {
+ unsigned long size = PAGE_SIZE;
+
if (addr < tlb->range_start)
tlb->range_start = addr;
- if (addr + PAGE_SIZE > tlb->range_end)
- tlb->range_end = addr + PAGE_SIZE;
+
+ if (tlb->vma && is_vm_hugetlb_page(tlb->vma))
+ size = HPAGE_SIZE;
+
+ if (addr + size > tlb->range_end)
+ tlb->range_end = addr + size;
}
}
@@ -223,6 +229,12 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
#endif
}
+static inline void
+tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp, unsigned long addr)
+{
+ tlb_add_flush(tlb, addr);
+}
+
#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr)
#define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr)
#define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp)
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 6e924d3a77e..907cede92e8 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -505,6 +505,8 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
}
#endif
+#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
+
#endif
#endif /* CONFIG_MMU */
diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h
index 983fa7c153a..5357eb195d1 100644
--- a/arch/arm/include/asm/topology.h
+++ b/arch/arm/include/asm/topology.h
@@ -68,6 +68,21 @@ static inline int cluster_to_logical_mask(unsigned int socket_id,
#endif
+#ifdef CONFIG_NUMA
+
+static inline int cpu_to_node(int cpu)
+{
+ return numa_cpu_lookup_table[cpu];
+}
+
+#define cpumask_of_node(node) ((node) == -1 ? \
+ cpu_all_mask : \
+ node_to_cpumask_map[node])
+
+#define parent_node(node) (node)
+
+#endif /* CONFIG_NUMA */
+
#include <asm-generic/topology.h>
#endif /* _ASM_ARM_TOPOLOGY_H */
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 21a2700d295..16f45f673f6 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -15,7 +15,7 @@
#include <uapi/asm/unistd.h>
-#define __NR_syscalls (380)
+#define __NR_syscalls (384)
#define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0)
#define __ARCH_WANT_STAT64
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index 4da7cde70b5..3d97a64aede 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -406,6 +406,7 @@
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
/* 378 for kcmp */
#define __NR_finit_module (__NR_SYSCALL_BASE+379)
+#define __NR_migrate_pages (__NR_SYSCALL_BASE+380)
/*
* This may need to be greater than __NR_last_syscall+1 in order to
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5bbec7b8183..47868ae4e48 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -80,6 +80,7 @@ endif
head-y := head$(MMUEXT).o
obj-$(CONFIG_DEBUG_LL) += debug.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_ARM_RUNTIME_PATCH) += runtime-patch.o patch.o
obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 60d3b738d42..6b388f88116 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -152,7 +152,3 @@ EXPORT_SYMBOL(mcount);
#endif
EXPORT_SYMBOL(__gnu_mcount_nc);
#endif
-
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
-EXPORT_SYMBOL(__pv_phys_offset);
-#endif
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index a4fda4e7a37..d2fd9d4e5d2 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -389,6 +389,7 @@
CALL(sys_process_vm_writev)
CALL(sys_ni_syscall) /* reserved for sys_kcmp */
CALL(sys_finit_module)
+ CALL(sys_migrate_pages)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 4eee351f466..fefa44070a5 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -121,7 +121,7 @@ ENTRY(stext)
bl __fixup_smp
#endif
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
- bl __fixup_pv_table
+ bl __fixup_pv_offsets
#endif
bl __create_page_tables
@@ -156,7 +156,7 @@ ENDPROC(stext)
*
* Returns:
* r0, r3, r5-r7 corrupted
- * r4 = physical page table address
+ * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
*/
__create_page_tables:
pgtbl r4, r8 @ page table address
@@ -310,6 +310,7 @@ __create_page_tables:
#endif
#ifdef CONFIG_ARM_LPAE
sub r4, r4, #0x1000 @ point to the PGD table
+ mov r4, r4, lsr #ARCH_PGD_SHIFT
#endif
mov pc, lr
ENDPROC(__create_page_tables)
@@ -387,7 +388,7 @@ __secondary_data:
* r0 = cp#15 control register
* r1 = machine ID
* r2 = atags or dtb pointer
- * r4 = page table pointer
+ * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)
* r9 = processor ID
* r13 = *virtual* address to jump to upon completion
*/
@@ -406,17 +407,22 @@ __enable_mmu:
#ifdef CONFIG_CPU_ICACHE_DISABLE
bic r0, r0, #CR_I
#endif
-#ifdef CONFIG_ARM_LPAE
- mov r5, #0
- mcrr p15, 0, r4, r5, c2 @ load TTBR0
-#else
+#ifndef CONFIG_ARM_LPAE
+#ifndef CONFIG_SYS_SUPPORTS_HUGETLBFS
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
+#else
+ @ set ourselves as the client in all domains
+ @ this allows us to then use the 4 domain bits in the
+ @ section descriptors in our transparent huge pages
+ ldr r5, =0x55555555
+#endif /* CONFIG_SYS_SUPPORTS_HUGETLBFS */
+
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
-#endif
+#endif /* CONFIG_ARM_LPAE */
b __turn_mmu_on
ENDPROC(__enable_mmu)
@@ -519,92 +525,33 @@ ENDPROC(fixup_smp)
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
-/* __fixup_pv_table - patch the stub instructions with the delta between
- * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and
- * can be expressed by an immediate shifter operand. The stub instruction
- * has a form of '(add|sub) rd, rn, #imm'.
+/*
+ * __fixup_pv_offsets - update __pv_offset and __pv_phys_offset based on the
+ * runtime location of the kernel.
*/
__HEAD
-__fixup_pv_table:
+__fixup_pv_offsets:
adr r0, 1f
- ldmia r0, {r3-r5, r7}
+ ldmia r0, {r3-r6}
sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
- add r4, r4, r3 @ adjust table start address
- add r5, r5, r3 @ adjust table end address
- add r7, r7, r3 @ adjust __pv_phys_offset address
- str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset
- mov r6, r3, lsr #24 @ constant for add/sub instructions
- teq r3, r6, lsl #24 @ must be 16MiB aligned
-THUMB( it ne @ cross section branch )
- bne __error
- str r6, [r7, #4] @ save to __pv_offset
- b __fixup_a_pv_table
-ENDPROC(__fixup_pv_table)
+ add r4, r4, r3 @ virt_to_phys(__pv_phys_offset)
+ add r5, r5, r3 @ virt_to_phys(__pv_offset)
+ add r6, r6, r3 @ virt_to_phys(PAGE_OFFSET) = PHYS_OFFSET
+ str r6, [r4] @ save __pv_phys_offset
+ str r3, [r5] @ save __pv_offset
+ mov pc, lr
+ENDPROC(__fixup_pv_offsets)
.align
1: .long .
- .long __pv_table_begin
- .long __pv_table_end
-2: .long __pv_phys_offset
-
- .text
-__fixup_a_pv_table:
-#ifdef CONFIG_THUMB2_KERNEL
- lsls r6, #24
- beq 2f
- clz r7, r6
- lsr r6, #24
- lsl r6, r7
- bic r6, #0x0080
- lsrs r7, #1
- orrcs r6, #0x0080
- orr r6, r6, r7, lsl #12
- orr r6, #0x4000
- b 2f
-1: add r7, r3
- ldrh ip, [r7, #2]
- and ip, 0x8f00
- orr ip, r6 @ mask in offset bits 31-24
- strh ip, [r7, #2]
-2: cmp r4, r5
- ldrcc r7, [r4], #4 @ use branch for delay slot
- bcc 1b
- bx lr
+#if defined(CONFIG_ARM_LPAE) && defined(__ARMEB__)
+ .long __pv_phys_offset + 4
#else
- b 2f
-1: ldr ip, [r7, r3]
- bic ip, ip, #0x000000ff
- orr ip, ip, r6 @ mask in offset bits 31-24
- str ip, [r7, r3]
-2: cmp r4, r5
- ldrcc r7, [r4], #4 @ use branch for delay slot
- bcc 1b
- mov pc, lr
+ .long __pv_phys_offset
#endif
-ENDPROC(__fixup_a_pv_table)
-
-ENTRY(fixup_pv_table)
- stmfd sp!, {r4 - r7, lr}
- ldr r2, 2f @ get address of __pv_phys_offset
- mov r3, #0 @ no offset
- mov r4, r0 @ r0 = table start
- add r5, r0, r1 @ r1 = table size
- ldr r6, [r2, #4] @ get __pv_offset
- bl __fixup_a_pv_table
- ldmfd sp!, {r4 - r7, pc}
-ENDPROC(fixup_pv_table)
-
- .align
-2: .long __pv_phys_offset
-
- .data
- .globl __pv_phys_offset
- .type __pv_phys_offset, %object
-__pv_phys_offset:
- .long 0
- .size __pv_phys_offset, . - __pv_phys_offset
-__pv_offset:
- .long 0
+ .long __pv_offset
+ .long PAGE_OFFSET
#endif
+
#include "head-common.S"
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 1e9be5d25e5..bd8a860422a 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -24,6 +24,7 @@
#include <asm/sections.h>
#include <asm/smp_plat.h>
#include <asm/unwind.h>
+#include <asm/runtime-patch.h>
#ifdef CONFIG_XIP_KERNEL
/*
@@ -272,6 +273,7 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
struct module *mod)
{
const Elf_Shdr *s = NULL;
+ int err;
#ifdef CONFIG_ARM_UNWIND
const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum;
@@ -316,11 +318,12 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
maps[i].txt_sec->sh_addr,
maps[i].txt_sec->sh_size);
#endif
-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
- s = find_mod_section(hdr, sechdrs, ".pv_table");
- if (s)
- fixup_pv_table((void *)s->sh_addr, s->sh_size);
-#endif
+ s = find_mod_section(hdr, sechdrs, ".runtime.patch.table");
+ if (s) {
+ err = runtime_patch((void *)s->sh_addr, s->sh_size);
+ if (err)
+ return err;
+ }
s = find_mod_section(hdr, sechdrs, ".alt.smp.init");
if (s && !is_smp())
#ifdef CONFIG_SMP_ON_UP
diff --git a/arch/arm/kernel/runtime-patch.c b/arch/arm/kernel/runtime-patch.c
new file mode 100644
index 00000000000..0be9ef314a3
--- /dev/null
+++ b/arch/arm/kernel/runtime-patch.c
@@ -0,0 +1,268 @@
+/*
+ * arch/arm/kernel/runtime-patch.c
+ *
+ * Copyright 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/opcodes.h>
+#include <asm/cacheflush.h>
+#include <asm/runtime-patch.h>
+
+#include "patch.h"
+
+static inline void flush_icache_insn(void *insn_ptr, int bytes)
+{
+ unsigned long insn_addr = (unsigned long)insn_ptr;
+ flush_icache_range(insn_addr, insn_addr + bytes - 1);
+}
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+static int do_patch_imm8(u32 insn, u32 imm, u32 *ninsn)
+{
+ u32 op, rot, val;
+ const u32 supported_ops = (BIT(0) | /* and */
+ BIT(1) | /* bic */
+ BIT(2) | /* orr/mov */
+ BIT(3) | /* orn/mvn */
+ BIT(4) | /* eor */
+ BIT(8) | /* add */
+ BIT(10) | /* adc */
+ BIT(11) | /* sbc */
+ BIT(12) | /* sub */
+ BIT(13)); /* rsb */
+
+ insn = __mem_to_opcode_thumb32(insn);
+
+ if (!__opcode_is_thumb32(insn)) {
+ pr_err("patch: invalid thumb2 insn %08x\n", insn);
+ return -EINVAL;
+ }
+
+ /* allow only data processing (immediate)
+ * 1111 0x0x xxx0 xxxx 0xxx xxxx xxxx xxxx */
+ if ((insn & 0xfa008000) != 0xf0000000) {
+ pr_err("patch: unknown insn %08x\n", insn);
+ return -EINVAL;
+ }
+
+ /* extract op code */
+ op = (insn >> 21) & 0xf;
+
+ /* disallow unsupported opcodes */
+ if ((supported_ops & BIT(op)) == 0) {
+ pr_err("patch: unsupported opcode %x\n", op);
+ return -EINVAL;
+ }
+
+ if (imm <= 0xff) {
+ rot = 0;
+ val = imm;
+ } else {
+ rot = 32 - fls(imm); /* clz */
+ if (imm & ~(0xff000000 >> rot)) {
+ pr_err("patch: constant overflow %08x\n", imm);
+ return -EINVAL;
+ }
+ val = (imm >> (24 - rot)) & 0x7f;
+ rot += 8; /* encoded i:imm3:a */
+
+ /* pack least-sig rot bit into most-sig val bit */
+ val |= (rot & 1) << 7;
+ rot >>= 1;
+ }
+
+ *ninsn = insn & ~(BIT(26) | 0x7 << 12 | 0xff);
+ *ninsn |= (rot >> 3) << 26; /* field "i" */
+ *ninsn |= (rot & 0x7) << 12; /* field "imm3" */
+ *ninsn |= val;
+
+ return 0;
+}
+
+#else
+
+static int do_patch_imm8(u32 insn, u32 imm, u32 *ninsn)
+{
+ u32 rot, val, op;
+
+ insn = __mem_to_opcode_arm(insn);
+
+ /* disallow special unconditional instructions
+ * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx */
+ if ((insn >> 24) == 0xf) {
+ pr_err("patch: unconditional insn %08x\n", insn);
+ return -EINVAL;
+ }
+
+ /* allow only data processing (immediate)
+ * xxxx 001x xxxx xxxx xxxx xxxx xxxx xxxx */
+ if (((insn >> 25) & 0x3) != 1) {
+ pr_err("patch: unknown insn %08x\n", insn);
+ return -EINVAL;
+ }
+
+ /* extract op code */
+ op = (insn >> 20) & 0x1f;
+
+ /* disallow unsupported 10xxx op codes */
+ if (((op >> 3) & 0x3) == 2) {
+ pr_err("patch: unsupported opcode %08x\n", insn);
+ return -EINVAL;
+ }
+
+ rot = imm ? __ffs(imm) / 2 : 0;
+ val = imm >> (rot * 2);
+ rot = (-rot) & 0xf;
+
+ /* does this fit in 8-bit? */
+ if (val > 0xff) {
+ pr_err("patch: constant overflow %08x\n", imm);
+ return -EINVAL;
+ }
+
+ /* patch in new immediate and rotation */
+ *ninsn = (insn & ~0xfff) | (rot << 8) | val;
+
+ return 0;
+}
+
+#endif /* CONFIG_THUMB2_KERNEL */
+
+static int apply_patch_imm8(const struct patch_info *p)
+{
+ u32 *insn_ptr = p->insn, ninsn;
+ int count = p->insn_size / sizeof(u32);
+ const struct patch_info_imm8 *info;
+ int err;
+
+
+ if (count <= 0 || p->data_size != count * sizeof(*info)) {
+ pr_err("patch: bad patch, insn size %d, data size %d\n",
+ p->insn_size, p->data_size);
+ return -EINVAL;
+ }
+
+ for (info = patch_data(p); count; count--, info++, insn_ptr++) {
+ err = do_patch_imm8(info->insn, *info->imm, &ninsn);
+ if (err)
+ return err;
+ __patch_text(insn_ptr, ninsn);
+ }
+
+
+ return 0;
+}
+
+#ifdef CONFIG_ARM_RUNTIME_PATCH_TEST
+
+struct patch_test_imm8 {
+ u16 imm;
+ u16 shift;
+ u32 insn;
+};
+
+static void __init __used __naked __patch_test_code_imm8(void)
+{
+ __asm__ __volatile__ (
+
+ /* a single test case */
+ " .macro test_one, imm, sft\n"
+ " .hword \\imm\n"
+ " .hword \\sft\n"
+ " add r1, r2, #(\\imm << \\sft)\n"
+ " .endm\n"
+
+ /* a sequence of tests at 'inc' increments of shift */
+ " .macro test_seq, imm, sft, max, inc\n"
+ " test_one \\imm, \\sft\n"
+ " .if \\sft < \\max\n"
+ " test_seq \\imm, (\\sft + \\inc), \\max, \\inc\n"
+ " .endif\n"
+ " .endm\n"
+
+ /* an empty record to mark the end */
+ " .macro test_end\n"
+ " .hword 0, 0\n"
+ " .word 0\n"
+ " .endm\n"
+
+ /* finally generate the test sequences */
+ " test_seq 0x41, 0, 24, 1\n"
+ " test_seq 0x81, 0, 24, 2\n"
+ " test_end\n"
+ : : : "r1", "r2", "cc");
+}
+
+static void __init test_patch_imm8(void)
+{
+ u32 test_code_addr = (u32)(&__patch_test_code_imm8);
+ struct patch_test_imm8 *test = (void *)(test_code_addr & ~1);
+ u32 ninsn, insn, patched_insn;
+ int i, err;
+
+ insn = test[0].insn;
+ for (i = 0; test[i].insn; i++) {
+ err = do_patch_imm8(insn, test[i].imm << test[i].shift, &ninsn);
+ __patch_text(&patched_insn, ninsn);
+
+ if (err) {
+ pr_err("rtpatch imm8: failed at imm %x, shift %d\n",
+ test[i].imm, test[i].shift);
+ } else if (patched_insn != test[i].insn) {
+ pr_err("rtpatch imm8: failed, need %x got %x\n",
+ test[i].insn, patched_insn);
+ } else {
+ pr_debug("rtpatch imm8: imm %x, shift %d, %x -> %x\n",
+ test[i].imm, test[i].shift, insn,
+ patched_insn);
+ }
+ }
+}
+
+static void __init runtime_patch_test(void)
+{
+ test_patch_imm8();
+}
+#endif
+
+int runtime_patch(const void *table, unsigned size)
+{
+ const struct patch_info *p = table, *end = (table + size);
+
+ for (p = table; p < end; p = patch_next(p)) {
+ int err = -EINVAL;
+
+ if (p->type == PATCH_IMM8)
+ err = apply_patch_imm8(p);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+void __init runtime_patch_kernel(void)
+{
+ extern unsigned __runtime_patch_table_begin, __runtime_patch_table_end;
+ const void *start = &__runtime_patch_table_begin;
+ const void *end = &__runtime_patch_table_end;
+
+#ifdef CONFIG_ARM_RUNTIME_PATCH_TEST
+ runtime_patch_test();
+#endif
+ BUG_ON(runtime_patch(start, end - start));
+}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 452a6124c4f..a47e3680b11 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -54,6 +54,7 @@
#include <asm/unwind.h>
#include <asm/memblock.h>
#include <asm/virt.h>
+#include <asm/runtime-patch.h>
#include "atags.h"
#include "tcm.h"
@@ -143,6 +144,19 @@ static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '
DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+
+/*
+ * These are initialized in head.S code prior to BSS getting cleared out.
+ * The initializers here prevent these from landing in the BSS section.
+ */
+unsigned long __pv_offset = 0xdeadbeef;
+EXPORT_SYMBOL(__pv_offset);
+phys_addr_t __pv_phys_offset = 0xdeadbeef;
+EXPORT_SYMBOL(__pv_phys_offset);
+
+#endif
+
/*
* Standard memory resources
*/
@@ -810,6 +824,8 @@ void __init setup_arch(char **cmdline_p)
if (mdesc->init_early)
mdesc->init_early();
+
+ runtime_patch_kernel();
}
@@ -817,6 +833,12 @@ static int __init topology_init(void)
{
int cpu;
+#ifdef CONFIG_NUMA
+ int node;
+ for_each_online_node(node)
+ register_one_node(node);
+#endif
+
for_each_possible_cpu(cpu) {
struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
cpuinfo->cpu.hotpluggable = 1;
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index c115ab3c27f..2477225c33c 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -71,6 +71,13 @@ enum ipi_msg_type {
static DECLARE_COMPLETION(cpu_running);
+static unsigned long get_arch_pgd(pgd_t *pgd)
+{
+ phys_addr_t pgdir = virt_to_phys(pgd);
+ BUG_ON(pgdir & ARCH_PGD_MASK);
+ return pgdir >> ARCH_PGD_SHIFT;
+}
+
static struct smp_operations smp_ops;
void __init smp_set_ops(struct smp_operations *ops)
@@ -88,8 +95,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
* its stack and the page tables.
*/
secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
- secondary_data.pgdir = virt_to_phys(idmap_pgd);
- secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir);
+ secondary_data.pgdir = get_arch_pgd(idmap_pgd);
+ secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
__cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 11c1785bf63..88c7f2f5100 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -173,10 +173,15 @@ SECTIONS
__smpalt_end = .;
}
#endif
- .init.pv_table : {
- __pv_table_begin = .;
- *(.pv_table)
- __pv_table_end = .;
+ .init.runtime_patch_table : {
+ __runtime_patch_table_begin = .;
+ *(.runtime.patch.table)
+ __runtime_patch_table_end = .;
+ }
+ .init.runtime_patch_code : {
+ __runtime_patch_code_begin = .;
+ *(.runtime.patch.code)
+ __runtime_patch_code_end = .;
}
.init.data : {
#ifndef CONFIG_XIP_KERNEL
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index e103c290bc9..46600332be1 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -332,6 +332,7 @@ config MACH_ORIGEN
select CPU_EXYNOS4210
select EXYNOS4_DEV_USB_OHCI
select EXYNOS4_SETUP_FIMD0
+ select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_USB_PHY
select EXYNOS_DEV_DMA
@@ -340,7 +341,9 @@ config MACH_ORIGEN
select S3C24XX_PWM
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC2
+ select S3C_DEV_HSMMC3
select S3C_DEV_RTC
+ select S3C_DEV_I2C1
select S3C_DEV_USB_HSOTG
select S3C_DEV_WDT
select S5P_DEV_FIMC0
@@ -349,6 +352,7 @@ config MACH_ORIGEN
select S5P_DEV_FIMC3
select S5P_DEV_FIMD0
select S5P_DEV_G2D
+ select S5P_DEV_G3D
select S5P_DEV_I2C_HDMIPHY
select S5P_DEV_JPEG
select S5P_DEV_MFC
@@ -416,6 +420,8 @@ config MACH_EXYNOS4_DT
select PINCTRL
select PINCTRL_EXYNOS4
select USE_OF
+ select SAMSUNG_DEV_BACKLIGHT
+ select SAMSUNG_DEV_PWM
help
Machine support for Samsung Exynos4 machine with device tree enabled.
Select this if a fdt blob is available for the Exynos4 SoC based board.
@@ -428,6 +434,8 @@ config MACH_EXYNOS5_DT
depends on ARCH_EXYNOS5
select ARM_AMBA
select USE_OF
+ select EXYNOS4_SETUP_USB_PHY
+ select USB_ARCH_HAS_XHCI
help
Machine support for Samsung EXYNOS5 machine with device tree enabled.
Select this if a fdt blob is available for the EXYNOS5 SoC based board.
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
index bbcb3dea0d4..c125dd73978 100644
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ b/arch/arm/mach-exynos/clock-exynos4.c
@@ -23,14 +23,28 @@
#include <plat/pm.h>
#include <mach/map.h>
+#include <mach/regs-audss.h>
#include <mach/regs-clock.h>
#include <mach/sysmmu.h>
#include "common.h"
#include "clock-exynos4.h"
+/* For vpll */
+struct vpll_div_data {
+ u32 rate;
+ u32 pdiv;
+ u32 mdiv;
+ u32 sdiv;
+ u32 k;
+ u32 mfr;
+ u32 mrr;
+ u32 vsel;
+};
+
#ifdef CONFIG_PM_SLEEP
static struct sleep_save exynos4_clock_save[] = {
+ SAVE_ITEM(EXYNOS4_CLKSRC_AUDSS),
SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
@@ -118,6 +132,15 @@ static struct clk dummy_apb_pclk = {
.id = -1,
};
+static struct clk exynos4_clk_xxti = {
+ .name = "xxti",
+};
+
+static int exynos4_clk_ip_g3d_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(EXYNOS4_CLKGATE_IP_G3D, clk, enable);
+}
+
static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
{
return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
@@ -617,6 +640,11 @@ static struct clk exynos4_init_clocks_off[] = {
.ctrlbit = (1 << 18),
}, {
.name = "iis",
+ .devname = "samsung-i2s.0",
+ .enable = exynos4_clk_ip_peril_ctrl,
+ .ctrlbit = (1 << 19),
+ }, {
+ .name = "iis",
.devname = "samsung-i2s.1",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 20),
@@ -823,6 +851,24 @@ static struct clk exynos4_clk_fimd0 = {
.ctrlbit = (1 << 0),
};
+static struct clk *exynos4_clkset_mout_audss_list[] = {
+ &exynos4_clk_xxti,
+ &clk_fout_epll,
+};
+
+static struct clksrc_sources exynos4_clkset_mout_audss = {
+ .sources = exynos4_clkset_mout_audss_list,
+ .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_audss_list),
+};
+
+static struct clksrc_clk exynos4_clk_mout_audss = {
+ .clk = {
+ .name = "busclk",
+ },
+ .sources = &exynos4_clkset_mout_audss,
+ .reg_src = { .reg = EXYNOS4_CLKSRC_AUDSS, .shift = 0, .size = 1 },
+};
+
struct clk *exynos4_clkset_group_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_xusbxti,
@@ -906,6 +952,52 @@ static struct clksrc_sources exynos4_clkset_mout_mfc = {
.nr_sources = ARRAY_SIZE(exynos4_clkset_mout_mfc_list),
};
+static struct clk *exynos4_clkset_mout_g3d0_list[] = {
+ [0] = &exynos4_clk_mout_mpll.clk,
+ [1] = &exynos4_clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources exynos4_clkset_mout_g3d0 = {
+ .sources = exynos4_clkset_mout_g3d0_list,
+ .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g3d0_list),
+};
+
+static struct clksrc_clk exynos4_clk_mout_g3d0 = {
+ .clk = {
+ .name = "mout_g3d0",
+ },
+ .sources = &exynos4_clkset_mout_g3d0,
+ .reg_src = { .reg = EXYNOS4_CLKSRC_G3D, .shift = 0, .size = 1 },
+};
+
+static struct clk *exynos4_clkset_mout_g3d1_list[] = {
+ [0] = &exynos4_clk_mout_epll.clk,
+ [1] = &exynos4_clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources exynos4_clkset_mout_g3d1 = {
+ .sources = exynos4_clkset_mout_g3d1_list,
+ .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g3d1_list),
+};
+
+static struct clksrc_clk exynos4_clk_mout_g3d1 = {
+ .clk = {
+ .name = "mout_g3d1",
+ },
+ .sources = &exynos4_clkset_mout_g3d1,
+ .reg_src = { .reg = EXYNOS4_CLKSRC_G3D, .shift = 4, .size = 1 },
+};
+
+static struct clk *exynos4_clkset_mout_g3d_list[] = {
+ [0] = &exynos4_clk_mout_g3d0.clk,
+ [1] = &exynos4_clk_mout_g3d1.clk,
+};
+
+static struct clksrc_sources exynos4_clkset_mout_g3d = {
+ .sources = exynos4_clkset_mout_g3d_list,
+ .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g3d_list),
+};
+
static struct clk *exynos4_clkset_sclk_dac_list[] = {
[0] = &exynos4_clk_sclk_vpll.clk,
[1] = &exynos4_clk_sclk_hdmiphy,
@@ -1134,6 +1226,15 @@ static struct clksrc_clk exynos4_clksrcs[] = {
.reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
}, {
.clk = {
+ .name = "sclk_g3d",
+ .enable = exynos4_clk_ip_g3d_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &exynos4_clkset_mout_g3d,
+ .reg_src = { .reg = EXYNOS4_CLKSRC_G3D, .shift = 8, .size = 1 },
+ .reg_div = { .reg = EXYNOS4_CLKDIV_G3D, .shift = 0, .size = 4 },
+ }, {
+ .clk = {
.name = "ciu",
.parent = &exynos4_clk_dout_mmc4.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
@@ -1323,6 +1424,7 @@ static struct clksrc_clk *exynos4_sysclks[] = {
&exynos4_clk_aclk_100,
&exynos4_clk_aclk_160,
&exynos4_clk_aclk_133,
+ &exynos4_clk_mout_audss,
&exynos4_clk_dout_mmc0,
&exynos4_clk_dout_mmc1,
&exynos4_clk_dout_mmc2,
@@ -1330,6 +1432,8 @@ static struct clksrc_clk *exynos4_sysclks[] = {
&exynos4_clk_dout_mmc4,
&exynos4_clk_mout_mfc0,
&exynos4_clk_mout_mfc1,
+ &exynos4_clk_mout_g3d0,
+ &exynos4_clk_mout_g3d1,
};
static struct clk *exynos4_clk_cdev[] = {
@@ -1372,6 +1476,7 @@ static struct clk_lookup exynos4_clk_lookup[] = {
CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
+ CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &exynos4_clk_mout_audss.clk),
};
static int xtal_rate;
@@ -1387,13 +1492,92 @@ static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
return 0;
}
+static u32 exynos4_epll_div[][6] = {
+ { 48000000, 0, 48, 3, 3, 0 },
+ { 96000000, 0, 48, 3, 2, 0 },
+ { 144000000, 1, 72, 3, 2, 0 },
+ { 192000000, 0, 48, 3, 1, 0 },
+ { 288000000, 1, 72, 3, 1, 0 },
+ { 84000000, 0, 42, 3, 2, 0 },
+ { 50000000, 0, 50, 3, 3, 0 },
+ { 80000000, 1, 80, 3, 3, 0 },
+ { 32750000, 1, 65, 3, 4, 35127 },
+ { 32768000, 1, 65, 3, 4, 35127 },
+ { 49152000, 0, 49, 3, 3, 9961 },
+ { 67737600, 1, 67, 3, 3, 48366 },
+ { 73728000, 1, 73, 3, 3, 47710 },
+ { 45158400, 0, 45, 3, 3, 10381 },
+ { 45000000, 0, 45, 3, 3, 10355 },
+ { 45158000, 0, 45, 3, 3, 10355 },
+ { 49125000, 0, 49, 3, 3, 9961 },
+ { 67738000, 1, 67, 3, 3, 48366 },
+ { 73800000, 1, 73, 3, 3, 47710 },
+ { 36000000, 1, 32, 3, 4, 0 },
+ { 60000000, 1, 60, 3, 3, 0 },
+ { 72000000, 1, 72, 3, 3, 0 },
+ { 191923200, 0, 47, 3, 1, 64278 },
+ { 180633600, 0, 45, 3, 1, 10381 },
+};
+
+static int exynos4_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned int epll_con, epll_con_k;
+ unsigned int i;
+
+ /* Return if nothing changed */
+ if (clk->rate == rate)
+ return 0;
+
+ epll_con = __raw_readl(EXYNOS4_EPLL_CON0);
+ epll_con &= ~(0x1 << 27 | \
+ PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
+ PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
+ PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+ for (i = 0; i < ARRAY_SIZE(exynos4_epll_div); i++) {
+ if (exynos4_epll_div[i][0] == rate) {
+ epll_con_k = exynos4_epll_div[i][5] << 0;
+ epll_con |= exynos4_epll_div[i][1] << 27;
+ epll_con |= exynos4_epll_div[i][2] << PLL46XX_MDIV_SHIFT;
+ epll_con |= exynos4_epll_div[i][3] << PLL46XX_PDIV_SHIFT;
+ epll_con |= exynos4_epll_div[i][4] << PLL46XX_SDIV_SHIFT;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(exynos4_epll_div)) {
+ printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ __raw_writel(epll_con, EXYNOS4_EPLL_CON0);
+ __raw_writel(epll_con_k, EXYNOS4_EPLL_CON1);
+
+ clk->rate = rate;
+
+ return 0;
+}
+
+static struct clk_ops exynos4_epll_ops = {
+ .get_rate = s5p_epll_get_rate,
+ .set_rate = exynos4_epll_set_rate,
+};
+
static struct clk_ops exynos4_fout_apll_ops = {
.get_rate = exynos4_fout_apll_get_rate,
};
-static u32 exynos4_vpll_div[][8] = {
- { 54000000, 3, 53, 3, 1024, 0, 17, 0 },
- { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+static struct vpll_div_data exynos4_vpll_div[] = {
+ {54000000, 2, 72, 4, 0, 0, 0, 0},
+ {108000000, 2, 72, 3, 0, 0, 0, 0},
+ {160000000, 3, 160, 3, 0, 0, 0, 0},
+ {266000000, 3, 133, 2, 0, 0, 0, 0},
+ {275000000, 2, 92, 2, 43692, 0, 0, 0},
+ {300000000, 2, 100, 2, 0, 0, 0, 0},
+ {333000000, 2, 111, 2, 0, 0, 0, 0},
+ {350000000, 3, 175, 2, 0, 0, 0, 0},
+ {440000000, 3, 110, 1, 0, 0, 0, 0},
};
static unsigned long exynos4_vpll_get_rate(struct clk *clk)
@@ -1403,7 +1587,7 @@ static unsigned long exynos4_vpll_get_rate(struct clk *clk)
static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
{
- unsigned int vpll_con0, vpll_con1 = 0;
+ unsigned int vpll_con0, vpll_con1;
unsigned int i;
/* Return if nothing changed */
@@ -1411,25 +1595,22 @@ static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
return 0;
vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
- vpll_con0 &= ~(0x1 << 27 | \
- PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | \
- PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
- PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+ vpll_con0 &= ~(PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT | \
+ PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT | \
+ PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
- vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT | \
- PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
- PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+ vpll_con1 &= ~(0xffff << 0);
for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
- if (exynos4_vpll_div[i][0] == rate) {
- vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
- vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
- vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
- vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
- vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
- vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
- vpll_con0 |= exynos4_vpll_div[i][7] << 27;
+ if (exynos4_vpll_div[i].rate == rate) {
+ vpll_con0 |= exynos4_vpll_div[i].pdiv <<
+ PLL36XX_PDIV_SHIFT;
+ vpll_con0 |= exynos4_vpll_div[i].mdiv <<
+ PLL36XX_MDIV_SHIFT;
+ vpll_con0 |= exynos4_vpll_div[i].sdiv <<
+ PLL36XX_SDIV_SHIFT;
+ vpll_con1 |= exynos4_vpll_div[i].k << 0;
break;
}
}
@@ -1443,11 +1624,8 @@ static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
- /* Wait for VPLL lock */
- while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
- continue;
-
clk->rate = rate;
+
return 0;
}
@@ -1516,6 +1694,10 @@ void __init_or_cpufreq exynos4_setup_clocks(void)
clk_fout_vpll.ops = &exynos4_vpll_ops;
clk_fout_vpll.rate = vpll;
+ clk_fout_epll.enable = s5p_epll_enable;
+ clk_fout_epll.ops = &exynos4_epll_ops;
+ clk_set_parent(&exynos4_clk_mout_audss.clk, &clk_fout_epll);
+
printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
apll, mpll, epll, vpll);
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
index e9d7b80bae4..49a20d2c05d 100644
--- a/arch/arm/mach-exynos/clock-exynos5.c
+++ b/arch/arm/mach-exynos/clock-exynos5.c
@@ -747,6 +747,11 @@ static struct clk exynos5_init_clocks_off[] = {
.enable = exynos5_clk_ip_fsys_ctrl ,
.ctrlbit = (1 << 18),
}, {
+ .name = "usbdrd30",
+ .parent = &exynos5_clk_aclk_200.clk,
+ .enable = exynos5_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 19),
+ }, {
.name = "usbotg",
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 7),
@@ -1011,6 +1016,16 @@ static struct clksrc_sources exynos5_clkset_group = {
.nr_sources = ARRAY_SIZE(exynos5_clkset_group_list),
};
+struct clk *exynos5_clkset_usbdrd30_list[] = {
+ [0] = &exynos5_clk_mout_mpll.clk,
+ [1] = &exynos5_clk_mout_cpll.clk,
+};
+
+struct clksrc_sources exynos5_clkset_usbdrd30 = {
+ .sources = exynos5_clkset_usbdrd30_list,
+ .nr_sources = ARRAY_SIZE(exynos5_clkset_usbdrd30_list),
+};
+
/* Possible clock sources for aclk_266_gscl_sub Mux */
static struct clk *clk_src_gscl_266_list[] = {
[0] = &clk_ext_xtal_mux,
@@ -1305,7 +1320,17 @@ static struct clksrc_clk exynos5_clksrcs[] = {
.parent = &exynos5_clk_mout_cpll.clk,
},
.reg_div = { .reg = EXYNOS5_CLKDIV_GEN, .shift = 4, .size = 3 },
- },
+ }, {
+
+ .clk = {
+ .name = "sclk_usbdrd30",
+ .enable = exynos5_clksrc_mask_fsys_ctrl,
+ .ctrlbit = (1 << 28),
+ },
+ .sources = &exynos5_clkset_usbdrd30,
+ .reg_src = {.reg = EXYNOS5_CLKSRC_FSYS, .shift = 28, .size = 1},
+ .reg_div = {.reg = EXYNOS5_CLKDIV_FSYS0, .shift = 24, .size = 4},
+ }
};
/* Clock initialization code */
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 1a89824a5f7..9f90e30134b 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -36,6 +36,7 @@
#include <mach/regs-pmu.h>
#include <mach/regs-gpio.h>
#include <mach/pmu.h>
+#include <mach/irqs.h>
#include <plat/cpu.h>
#include <plat/clock.h>
@@ -209,6 +210,11 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.length = SZ_64K,
.type = MT_DEVICE,
}, {
+ .virtual = (unsigned long)S5P_VA_AUDSS,
+ .pfn = __phys_to_pfn(EXYNOS4_PA_AUDSS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (unsigned long)S3C_VA_USB_HSPHY,
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
.length = SZ_4K,
@@ -289,6 +295,11 @@ static struct map_desc exynos5440_iodesc0[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS5440_PA_UART0),
.length = SZ_512K,
.type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C_VA_USB_HSPHY,
+ .pfn = __phys_to_pfn(EXYNOS5_PA_USB_PHY),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
},
};
@@ -448,6 +459,7 @@ struct combiner_chip_data {
unsigned int irq_offset;
unsigned int irq_mask;
void __iomem *base;
+ unsigned int parent_irq;
};
static struct irq_domain *combiner_irq_domain;
@@ -504,22 +516,46 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
+#ifdef CONFIG_SMP
+static int combiner_set_affinity(struct irq_data *d,
+ const struct cpumask *mask_val, bool force)
+{
+ struct combiner_chip_data *chip_data = irq_data_get_irq_chip_data(d);
+ struct irq_chip *chip = irq_get_chip(chip_data->parent_irq);
+ struct irq_data *data = irq_get_irq_data(chip_data->parent_irq);
+
+ if (chip && chip->irq_set_affinity)
+ return chip->irq_set_affinity(data, mask_val, force);
+ else
+ return -EINVAL;
+}
+#endif
+
static struct irq_chip combiner_chip = {
- .name = "COMBINER",
- .irq_mask = combiner_mask_irq,
- .irq_unmask = combiner_unmask_irq,
+ .name = "COMBINER",
+ .irq_mask = combiner_mask_irq,
+ .irq_unmask = combiner_unmask_irq,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = combiner_set_affinity,
+#endif
};
-static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
+static unsigned int max_combiner_nr(void)
{
- unsigned int max_nr;
-
if (soc_is_exynos5250())
- max_nr = EXYNOS5_MAX_COMBINER_NR;
+ return EXYNOS5_MAX_COMBINER_NR;
+ else if (soc_is_exynos4412())
+ return EXYNOS4412_MAX_COMBINER_NR;
+ else if (soc_is_exynos4212())
+ return EXYNOS4212_MAX_COMBINER_NR;
else
- max_nr = EXYNOS4_MAX_COMBINER_NR;
+ return EXYNOS4210_MAX_COMBINER_NR;
+}
- if (combiner_nr >= max_nr)
+static void __init combiner_cascade_irq(unsigned int combiner_nr,
+ unsigned int irq)
+{
+ if (combiner_nr >= max_combiner_nr())
BUG();
if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
BUG();
@@ -527,12 +563,13 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i
}
static void __init combiner_init_one(unsigned int combiner_nr,
- void __iomem *base)
+ void __iomem *base, unsigned int irq)
{
combiner_data[combiner_nr].base = base;
combiner_data[combiner_nr].irq_offset = irq_find_mapping(
combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
+ combiner_data[combiner_nr].parent_irq = irq;
/* Disable all interrupts */
__raw_writel(combiner_data[combiner_nr].irq_mask,
@@ -583,23 +620,38 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
.map = combiner_irq_domain_map,
};
+static unsigned int exynos4x12_combiner_extra_irq(int group)
+{
+ switch (group) {
+ case 16:
+ return IRQ_SPI(107);
+ case 17:
+ return IRQ_SPI(108);
+ case 18:
+ return IRQ_SPI(48);
+ case 19:
+ return IRQ_SPI(42);
+ default:
+ return 0;
+ }
+}
+
static void __init combiner_init(void __iomem *combiner_base,
struct device_node *np)
{
int i, irq, irq_base;
unsigned int max_nr, nr_irq;
+ max_nr = max_combiner_nr();
+
if (np) {
if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
- pr_warning("%s: number of combiners not specified, "
+ pr_info("%s: number of combiners not specified, "
"setting default as %d.\n",
- __func__, EXYNOS4_MAX_COMBINER_NR);
- max_nr = EXYNOS4_MAX_COMBINER_NR;
+ __func__, max_nr);
}
- } else {
- max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
- EXYNOS4_MAX_COMBINER_NR;
}
+
nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
@@ -616,12 +668,15 @@ static void __init combiner_init(void __iomem *combiner_base,
}
for (i = 0; i < max_nr; i++) {
- combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
- irq = IRQ_SPI(i);
+ if (i < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250())
+ irq = IRQ_SPI(i);
+ else
+ irq = exynos4x12_combiner_extra_irq(i);
#ifdef CONFIG_OF
if (np)
irq = irq_of_parse_and_map(np, i);
#endif
+ combiner_init_one(i, combiner_base + (i >> 2) * 0x10, irq);
combiner_cascade_irq(i, irq);
}
}
@@ -674,6 +729,8 @@ void __init exynos4_init_irq(void)
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
+
+ gic_arch_extn.irq_set_wake = s3c_irq_wake;
}
void __init exynos5_init_irq(void)
@@ -1086,3 +1143,30 @@ static int __init exynos_init_irq_eint(void)
return 0;
}
arch_initcall(exynos_init_irq_eint);
+
+static struct resource exynos4_pmu_resource[] = {
+ DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU),
+ DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU1),
+#if defined(CONFIG_SOC_EXYNOS4412)
+ DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU2),
+ DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU3),
+#endif
+};
+
+static struct platform_device exynos4_device_pmu = {
+ .name = "arm-pmu",
+ .num_resources = ARRAY_SIZE(exynos4_pmu_resource),
+ .resource = exynos4_pmu_resource,
+};
+
+static int __init exynos_armpmu_init(void)
+{
+ if (!of_have_populated_dt()) {
+ if (soc_is_exynos4210() || soc_is_exynos4212())
+ exynos4_device_pmu.num_resources = 2;
+ platform_device_register(&exynos4_device_pmu);
+ }
+
+ return 0;
+}
+arch_initcall(exynos_armpmu_init);
diff --git a/arch/arm/mach-exynos/dev-ahci.c b/arch/arm/mach-exynos/dev-ahci.c
index ce1aad3eeeb..7f3811da389 100644
--- a/arch/arm/mach-exynos/dev-ahci.c
+++ b/arch/arm/mach-exynos/dev-ahci.c
@@ -240,7 +240,7 @@ static struct resource exynos4_ahci_resource[] = {
[1] = DEFINE_RES_IRQ(EXYNOS4_IRQ_SATA),
};
-static u64 exynos4_ahci_dmamask = DMA_BIT_MASK(32);
+static u64 exynos4_ahci_dmamask = DMA_BIT_MASK(64);
struct platform_device exynos4_device_ahci = {
.name = "ahci",
@@ -250,6 +250,6 @@ struct platform_device exynos4_device_ahci = {
.dev = {
.platform_data = &exynos4_ahci_pdata,
.dma_mask = &exynos4_ahci_dmamask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
+ .coherent_dma_mask = DMA_BIT_MASK(64),
},
};
diff --git a/arch/arm/mach-exynos/dev-ohci.c b/arch/arm/mach-exynos/dev-ohci.c
index 4244d02dafb..3a9c6719e80 100644
--- a/arch/arm/mach-exynos/dev-ohci.c
+++ b/arch/arm/mach-exynos/dev-ohci.c
@@ -25,7 +25,7 @@ static struct resource exynos4_ohci_resource[] = {
[1] = DEFINE_RES_IRQ(IRQ_USB_HOST),
};
-static u64 exynos4_ohci_dma_mask = DMA_BIT_MASK(32);
+static u64 exynos4_ohci_dma_mask = DMA_BIT_MASK(64);
struct platform_device exynos4_device_ohci = {
.name = "exynos-ohci",
@@ -34,7 +34,7 @@ struct platform_device exynos4_device_ohci = {
.resource = exynos4_ohci_resource,
.dev = {
.dma_mask = &exynos4_ohci_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
+ .coherent_dma_mask = DMA_BIT_MASK(64),
}
};
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 1f4dc35cd4b..626245a38e1 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -128,7 +128,7 @@
#define EXYNOS4_IRQ_ADC1 IRQ_SPI(107)
#define EXYNOS4_IRQ_PEN1 IRQ_SPI(108)
#define EXYNOS4_IRQ_KEYPAD IRQ_SPI(109)
-#define EXYNOS4_IRQ_PMU IRQ_SPI(110)
+#define EXYNOS4_IRQ_POWER_PMU IRQ_SPI(110)
#define EXYNOS4_IRQ_GPS IRQ_SPI(111)
#define EXYNOS4_IRQ_INTFEEDCTRL_SSS IRQ_SPI(112)
#define EXYNOS4_IRQ_SLIMBUS IRQ_SPI(113)
@@ -139,6 +139,11 @@
#define EXYNOS4_IRQ_TMU_TRIG0 COMBINER_IRQ(2, 4)
#define EXYNOS4_IRQ_TMU_TRIG1 COMBINER_IRQ(3, 4)
+#define EXYNOS4_IRQ_PMU COMBINER_IRQ(2, 2)
+#define EXYNOS4_IRQ_PMU_CPU1 COMBINER_IRQ(3, 2)
+#define EXYNOS4_IRQ_PMU_CPU2 COMBINER_IRQ(18, 2)
+#define EXYNOS4_IRQ_PMU_CPU3 COMBINER_IRQ(19, 2)
+
#define EXYNOS4_IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0)
#define EXYNOS4_IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1)
#define EXYNOS4_IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2)
@@ -168,7 +173,10 @@
#define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1)
#define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2)
-#define EXYNOS4_MAX_COMBINER_NR 16
+#define EXYNOS4210_MAX_COMBINER_NR 16
+#define EXYNOS4212_MAX_COMBINER_NR 18
+#define EXYNOS4412_MAX_COMBINER_NR 20
+#define EXYNOS4_MAX_COMBINER_NR EXYNOS4412_MAX_COMBINER_NR
#define EXYNOS4_IRQ_GPIO1_NR_GROUPS 16
#define EXYNOS4_IRQ_GPIO2_NR_GROUPS 9
@@ -233,7 +241,6 @@
#define IRQ_TC EXYNOS4_IRQ_PEN0
#define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD
-#define IRQ_PMU EXYNOS4_IRQ_PMU
#define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO
#define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC
@@ -464,6 +471,7 @@
#define S5P_GPIOINT_BASE (S5P_EINT_BASE1 + 32)
#define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
#define IRQ_TIMER_BASE (IRQ_GPIO_END + 64)
+#define IRQ_TS (S5P_EINT_BASE1 + 25)
/* Set the default NR_IRQS */
diff --git a/arch/arm/mach-exynos/include/mach/mali/config.h b/arch/arm/mach-exynos/include/mach/mali/config.h
new file mode 100644
index 00000000000..ccd3cf7d245
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach/mali/config.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+/* Configuration for the EB platform with ZBT memory enabled */
+/*zepplin added 2010.08.17 for orion configuration*/
+#define MALI_BASE_ADDR 0x13000000
+#define GP_ADDR MALI_BASE_ADDR
+#define L2_ADDR MALI_BASE_ADDR+0x1000
+#define PMU_ADDR MALI_BASE_ADDR+0x2000
+#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000
+#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000
+#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000
+#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000
+#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000
+#define PP0_ADDR MALI_BASE_ADDR+0x8000
+#define PP1_ADDR MALI_BASE_ADDR+0xA000
+#define PP2_ADDR MALI_BASE_ADDR+0xC000
+#define PP3_ADDR MALI_BASE_ADDR+0xE000
+
+/*for mmu and os memory*/
+#define MEM_BASE_ADDR 0x40000000
+#define MEM_TOTAL_SIZE 0x40000000
+#define MEM_MALI_OS_SIZE 0x18000000
+
+/*for dedicated memory*/
+//#define MEM_MALI_BASE 0x58000000
+//#define MEM_MALI_SIZE 0x08000000
+#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024
+#define MEM_MALI_BASE 0x60000000 - MEM_MALI_SIZE
+
+//#define S5P_IRQ(x) (x+32)
+//#define IRQ_SPI(x) S5P_IRQ(x+32)
+#define MAX_IRQ_IN_COMBINER 8
+//#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
+
+#define IRQ_PPMMU0_3D COMBINER_IRQ(13, 0)
+#define IRQ_PPMMU1_3D COMBINER_IRQ(13, 1)
+#define IRQ_PPMMU2_3D COMBINER_IRQ(13, 2)
+#define IRQ_PPMMU3_3D COMBINER_IRQ(13, 3)
+#define IRQ_GPMMU_3D COMBINER_IRQ(13, 4)
+
+#define IRQ_PP0_3D COMBINER_IRQ(14, 0)
+#define IRQ_PP1_3D COMBINER_IRQ(14, 1)
+#define IRQ_PP2_3D COMBINER_IRQ(14, 2)
+#define IRQ_PP3_3D COMBINER_IRQ(14, 3)
+#define IRQ_GP_3D COMBINER_IRQ(14, 4)
+#define IRQ_PMU_3D COMBINER_IRQ(14, 5)
+
+static _mali_osk_resource_t arch_configuration [] =
+{
+ {
+ .type = MALI400GP,
+ .description = "Mali-400 GP",
+ .base = GP_ADDR,
+ .irq = IRQ_GP_3D,
+ .mmu_id = 1
+ },
+ {
+ .type = MALI400PP,
+ .base = PP0_ADDR,
+ .irq = IRQ_PP0_3D,
+ .description = "Mali-400 PP 0",
+ .mmu_id = 2
+ },
+ {
+ .type = MALI400PP,
+ .base = PP1_ADDR,
+ .irq = IRQ_PP1_3D,
+ .description = "Mali-400 PP 1",
+ .mmu_id = 3
+ },
+ {
+ .type = MALI400PP,
+ .base = PP2_ADDR,
+ .irq = IRQ_PP2_3D,
+ .description = "Mali-400 PP 2",
+ .mmu_id = 4
+ },
+ {
+ .type = MALI400PP,
+ .base = PP3_ADDR,
+ .irq = IRQ_PP3_3D,
+ .description = "Mali-400 PP 3",
+ .mmu_id = 5
+ },
+#if USING_MMU
+ {
+ .type = MMU,
+ .base = GP_MMU_ADDR,
+ .irq = IRQ_GPMMU_3D,
+ .description = "Mali-400 MMU for GP",
+ .mmu_id = 1
+ },
+ {
+ .type = MMU,
+ .base = PP0_MMU_ADDR,
+ .irq = IRQ_PPMMU0_3D,
+ .description = "Mali-400 MMU for PP 0",
+ .mmu_id = 2
+ },
+ {
+ .type = MMU,
+ .base = PP1_MMU_ADDR,
+ .irq = IRQ_PPMMU1_3D,
+ .description = "Mali-400 MMU for PP 1",
+ .mmu_id = 3
+ },
+ {
+ .type = MMU,
+ .base = PP2_MMU_ADDR,
+ .irq = IRQ_PPMMU2_3D,
+ .description = "Mali-400 MMU for PP 2",
+ .mmu_id = 4
+ },
+ {
+ .type = MMU,
+ .base = PP3_MMU_ADDR,
+ .irq = IRQ_PPMMU3_3D,
+ .description = "Mali-400 MMU for PP 3",
+ .mmu_id = 5
+ },
+#if USING_OS_MEMORY
+ {
+ .type = OS_MEMORY,
+ .description = "System Memory",
+ .size = MEM_MALI_OS_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE
+ },
+#endif
+#if USING_DED /* Dedicated Memory */
+ {
+ .type = MEMORY,
+ .description = "Dedicated Memory",
+ .base = MEM_MALI_BASE,
+ .size = MEM_MALI_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE
+ },
+#endif/* if USING_OS_MEMORY*/
+ {
+ .type = MEM_VALIDATION,
+ .description = "memory validation",
+ .base = MEM_BASE_ADDR,
+ .size = MEM_TOTAL_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE
+ },
+#else /* Not using MMU */
+ {
+ .type = MEMORY,
+ .description = "Dedicated Memory",
+ .base = MEM_MALI_BASE,
+ .size = MEM_MALI_SIZE,
+ .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE
+ },
+#endif
+ {
+ .type = MALI400L2,
+ .base = L2_ADDR,
+ .description = "Mali-400 L2 cache"
+ },
+};
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 1df6abbf53b..6421632733c 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -39,6 +39,8 @@
#define EXYNOS4_PA_G2D 0x12800000
+#define EXYNOS4_PA_G3D 0x13000000
+
#define EXYNOS4_PA_I2S0 0x03830000
#define EXYNOS4_PA_I2S1 0xE3100000
#define EXYNOS4_PA_I2S2 0xE2A00000
@@ -188,10 +190,13 @@
#define EXYNOS4_PA_HSOTG 0x12480000
#define EXYNOS4_PA_USB_HSPHY 0x125B0000
-
+#define EXYNOS5_PA_HSPHY 0x12130000
#define EXYNOS4_PA_SATA 0x12560000
#define EXYNOS4_PA_SATAPHY 0x125D0000
#define EXYNOS4_PA_SATAPHY_CTRL 0x126B0000
+#define EXYNOS5_PA_SATA_PHY_CTRL 0x12170000
+#define EXYNOS5_PA_SATA_PHY_I2C 0x121D0000
+#define EXYNOS5_PA_SATA_BASE 0x122F0000
#define EXYNOS4_PA_SROMC 0x12570000
#define EXYNOS5_PA_SROMC 0x12250000
@@ -199,11 +204,16 @@
#define EXYNOS4_PA_EHCI 0x12580000
#define EXYNOS4_PA_OHCI 0x12590000
#define EXYNOS4_PA_HSPHY 0x125B0000
+#define EXYNOS5_PA_DRD 0x12000000
+#define EXYNOS5_PA_EHCI 0x12110000
+#define EXYNOS5_PA_OHCI 0x12120000
#define EXYNOS4_PA_MFC 0x13400000
#define EXYNOS4_PA_UART 0x13800000
#define EXYNOS5_PA_UART 0x12C00000
+#define EXYNOS5_PA_USB_PHY 0x12130000
+
#define EXYNOS4_PA_VP 0x12C00000
#define EXYNOS4_PA_MIXER 0x12C10000
#define EXYNOS4_PA_SDO 0x12C20000
@@ -216,6 +226,8 @@
#define EXYNOS4_PA_ADC 0x13910000
#define EXYNOS4_PA_ADC1 0x13911000
+#define EXYNOS4_PA_AUDSS 0x03810000
+
#define EXYNOS4_PA_AC97 0x139A0000
#define EXYNOS4_PA_SPDIF 0x139B0000
@@ -246,7 +258,7 @@
#define S3C_PA_SPI1 EXYNOS4_PA_SPI1
#define S3C_PA_SPI2 EXYNOS4_PA_SPI2
#define S3C_PA_USB_HSOTG EXYNOS4_PA_HSOTG
-
+#define S3C_PA_USB_PHY EXYNOS4_PA_HSPHY
#define S5P_PA_EHCI EXYNOS4_PA_EHCI
#define S5P_PA_FIMC0 EXYNOS4_PA_FIMC0
#define S5P_PA_FIMC1 EXYNOS4_PA_FIMC1
@@ -254,6 +266,7 @@
#define S5P_PA_FIMC3 EXYNOS4_PA_FIMC3
#define S5P_PA_JPEG EXYNOS4_PA_JPEG
#define S5P_PA_G2D EXYNOS4_PA_G2D
+#define S5P_PA_G3D EXYNOS4_PA_G3D
#define S5P_PA_FIMD0 EXYNOS4_PA_FIMD0
#define S5P_PA_HDMI EXYNOS4_PA_HDMI
#define S5P_PA_IIC_HDMIPHY EXYNOS4_PA_IIC_HDMIPHY
diff --git a/arch/arm/mach-exynos/include/mach/regs-audss.h b/arch/arm/mach-exynos/include/mach/regs-audss.h
index ca5a8b64218..71ceb08ae63 100644
--- a/arch/arm/mach-exynos/include/mach/regs-audss.h
+++ b/arch/arm/mach-exynos/include/mach/regs-audss.h
@@ -1,5 +1,4 @@
-/* arch/arm/mach-exynos4/include/mach/regs-audss.h
- *
+/*
* Copyright (c) 2011 Samsung Electronics
* http://www.samsung.com
*
@@ -15,4 +14,12 @@
#define EXYNOS4_AUDSS_INT_MEM (0x03000000)
+#define EXYNOS_AUDSSREG(x) (S5P_VA_AUDSS + (x))
+
+#define EXYNOS4_CLKSRC_AUDSS EXYNOS_AUDSSREG(0x0)
+#define EXYNOS4_CLKDIV_AUDSS EXYNOS_AUDSSREG(0x4)
+#define EXYNOS4_CLKGATE_AUDSS EXYNOS_AUDSSREG(0x8)
+
+#define EXYNOS4_AUDSS_CLKGATE_I2SBUS (1<<2)
+
#endif /* _PLAT_REGS_AUDSS_H */
diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h
index 3f30aa1ae35..d2bee973ecc 100644
--- a/arch/arm/mach-exynos/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h
@@ -41,6 +41,10 @@
#define S5P_HDMI_PHY_CONTROL S5P_PMUREG(0x0700)
#define S5P_HDMI_PHY_ENABLE (1 << 0)
+/* only for EXYNOS5250*/
+#define S5P_USBDRD_PHY_CONTROL S5P_PMUREG(0x0704)
+#define S5P_USBDRD_PHY_ENABLE (1 << 0)
+
#define S5P_DAC_PHY_CONTROL S5P_PMUREG(0x070C)
#define S5P_DAC_PHY_ENABLE (1 << 0)
@@ -369,4 +373,7 @@
#define EXYNOS5_OPTION_USE_RETENTION (1 << 4)
+/* Only for EXYNOS5250 */
+#define EXYNOS5_SATA_PHY_CONTROL S5P_PMUREG(0x0724)
+
#endif /* __ASM_ARCH_REGS_PMU_H */
diff --git a/arch/arm/mach-exynos/include/mach/regs-sata.h b/arch/arm/mach-exynos/include/mach/regs-sata.h
new file mode 100644
index 00000000000..80dd564eb32
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach/regs-sata.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - SATA PHY controller definition
+ *
+ * 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.
+*/
+
+#define EXYNOS5_SATA_RESET 0x4
+#define RESET_CMN_RST_N (1 << 1)
+#define LINK_RESET 0xF0000
+
+#define EXYNOS5_SATA_MODE0 0x10
+
+#define EXYNOS5_SATA_CTRL0 0x14
+#define CTRL0_P0_PHY_CALIBRATED_SEL (1 << 9)
+#define CTRL0_P0_PHY_CALIBRATED (1 << 8)
+
+#define EXYNOS5_SATA_PHSATA_CTRLM 0xE0
+#define PHCTRLM_REF_RATE (1 << 1)
+#define PHCTRLM_HIGH_SPEED (1 << 0)
+
+#define EXYNOS5_SATA_PHSATA_STATM 0xF0
+#define PHSTATM_PLL_LOCKED (1 << 0)
+
+#define SATA_PHY_CON_RESET 0xF003F
diff --git a/arch/arm/mach-exynos/include/mach/regs-usb-phy.h b/arch/arm/mach-exynos/include/mach/regs-usb-phy.h
index 07277735252..2df4bd7e540 100644
--- a/arch/arm/mach-exynos/include/mach/regs-usb-phy.h
+++ b/arch/arm/mach-exynos/include/mach/regs-usb-phy.h
@@ -13,6 +13,7 @@
#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S3C_VA_USB_HSPHY)
+/* Exynos 4 */
#define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00)
#define PHY1_HSIC_NORMAL_MASK (0xf << 9)
#define PHY1_HSIC1_SLEEP (1 << 12)
@@ -71,4 +72,89 @@
#define EXYNOS4_PHY1CON EXYNOS4_HSOTG_PHYREG(0x34)
#define FPENABLEN (1 << 0)
+/* Exynos 5 */
+#define EXYNOS5_PHY_HOST_CTRL0 EXYNOS4_HSOTG_PHYREG(0x00)
+#define HOST_CTRL0_PHYSWRSTALL (0x1 << 31)
+
+#define HOST_CTRL0_REFCLKSEL_XTAL (0x0)
+#define HOST_CTRL0_REFCLKSEL_EXTL (0x1)
+#define HOST_CTRL0_REFCLKSEL_CLK_CORE (0x2)
+#define HOST_CTRL0_REFCLKSEL_MASK (0x3)
+#define HOST_CTRL0_REFCLKSEL_SHIFT (19)
+
+#define EXYNOS5_CLKSEL_50M (0x7)
+#define EXYNOS5_CLKSEL_24M (0x5)
+#define EXYNOS5_CLKSEL_20M (0x4)
+#define EXYNOS5_CLKSEL_19200K (0x3)
+#define EXYNOS5_CLKSEL_12M (0x2)
+#define EXYNOS5_CLKSEL_10M (0x1)
+#define EXYNOS5_CLKSEL_9600K (0x0)
+#define HOST_CTRL0_FSEL_MASK (0x7 << 16)
+#define HOST_CTRL0_CLKSEL_SHIFT (16)
+
+#define HOST_CTRL0_COMMONON_N (0x1 << 9)
+#define HOST_CTRL0_SIDDQ (0x1 << 6)
+#define HOST_CTRL0_FORCESLEEP (0x1 << 5)
+#define HOST_CTRL0_FORCESUSPEND (0x1 << 4)
+#define HOST_CTRL0_WORDINTERFACE (0x1 << 3)
+#define HOST_CTRL0_UTMISWRST (0x1 << 2)
+#define HOST_CTRL0_LINKSWRST (0x1 << 1)
+#define HOST_CTRL0_PHYSWRST (0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_TUNE0 EXYNOS4_HSOTG_PHYREG(0x04)
+#define EXYNOS5_PHY_HOST_TEST0 EXYNOS4_HSOTG_PHYREG(0x08)
+
+#define EXYNOS5_PHY_HSIC_CTRL1 EXYNOS4_HSOTG_PHYREG(0x10)
+#define EXYNOS5_PHY_HSIC_CTRL2 EXYNOS4_HSOTG_PHYREG(0x20)
+#define HSIC_CTRL_REFCLKSEL (0x2)
+#define HSIC_CTRL_REFCLKSEL_MASK (0x3)
+#define HSIC_CTRL_REFCLKSEL_SHIFT (23)
+
+#define HSIC_CTRL_REFCLKDIV_12 (0x24)
+#define HSIC_CTRL_REFCLKDIV_15 (0x1C)
+#define HSIC_CTRL_REFCLKDIV_16 (0x1A)
+#define HSIC_CTRL_REFCLKDIV_19_2 (0x15)
+#define HSIC_CTRL_REFCLKDIV_20 (0x14)
+#define HSIC_CTRL_REFCLKDIV_MASK (0x7f)
+#define HSIC_CTRL_REFCLKDIV_SHIFT (16)
+
+#define HSIC_CTRL_SIDDQ (0x1 << 6)
+#define HSIC_CTRL_FORCESLEEP (0x1 << 5)
+#define HSIC_CTRL_FORCESUSPEND (0x1 << 4)
+#define HSIC_CTRL_WORDINTERFACE (0x1 << 3)
+#define HSIC_CTRL_UTMISWRST (0x1 << 2)
+#define HSIC_CTRL_PHYSWRST (0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_EHCICTRL EXYNOS4_HSOTG_PHYREG(0x30)
+#define EHCICTRL_ENAINCRXALIGN (0x1 << 29)
+#define EHCICTRL_ENAINCR4 (0x1 << 28)
+#define EHCICTRL_ENAINCR8 (0x1 << 27)
+#define EHCICTRL_ENAINCR16 (0x1 << 26)
+
+#define EXYNOS5_PHY_HOST_OHCICTRL EXYNOS4_HSOTG_PHYREG(0x34)
+#define OHCICTRL_SUSPLGCY (0x1 << 3)
+#define OHCICTRL_APPSTARTCLK (0x1 << 2)
+#define OHCICTRL_CNTSEL (0x1 << 1)
+#define OHCICTRL_CLKCKTRST (0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_SYS EXYNOS4_HSOTG_PHYREG(0x38)
+#define OTG_SYS_PHYLINK_SW_RESET (0x1 << 14)
+#define OTG_SYS_LINK_SW_RST_UOTG (0x1 << 13)
+#define OTG_SYS_PHY0_SW_RST (0x1 << 12)
+
+#define OTG_SYS_REF_CLK_SEL_XTAL (0x0)
+#define OTG_SYS_REF_CLK_SEL_EXTL (0x1)
+#define OTG_SYS_REF_CLK_SEL_CLKCORE (0x2)
+#define OTG_SYS_REF_CLK_SEL_MASK (0x3)
+#define OTG_SYS_REF_CLK_SEL_SHIFT (9)
+
+#define OTG_SYS_IP_PULLUP_UOTG (0x1 << 8)
+#define OTG_SYS_COMMON_ON (0x1 << 7)
+#define OTG_SYS_CLKSEL_SHIFT (4)
+#define OTG_SYS_CTRL0_FSEL_MASK (0x7 << 4)
+#define OTG_SYS_FORCE_SLEEP (0x1 << 3)
+#define OTG_SYS_OTGDISABLE (0x1 << 2)
+#define OTG_SYS_SIDDQ_UOTG (0x1 << 1)
+#define OTG_SYS_FORCE_SUSPEND (0x1 << 0)
+
#endif /* __PLAT_S5P_REGS_USB_PHY_H */
diff --git a/arch/arm/mach-exynos/include/mach/ump/config.h b/arch/arm/mach-exynos/include/mach/ump/config.h
new file mode 100644
index 00000000000..a82934f2799
--- /dev/null
+++ b/arch/arm/mach-exynos/include/mach/ump/config.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2010 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ARCH_CONFIG_H__
+#define __ARCH_CONFIG_H__
+
+#define ARCH_UMP_BACKEND_DEFAULT UMP_MEMORY_TYPE
+#define ARCH_UMP_MEMORY_ADDRESS_DEFAULT 0
+#define ARCH_UMP_MEMORY_SIZE_DEFAULT CONFIG_UMP_MEM_SIZE * 1024UL * 1024UL
+
+#endif /* __ARCH_CONFIG_H__ */
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 92757ff817a..26babfa032a 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -14,15 +14,58 @@
#include <linux/of_platform.h>
#include <linux/serial_core.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
+#include <linux/platform_data/usb-exynos.h>
+
+#include <linux/platform_data/s3c-hsotg.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+#include <linux/fb.h>
+#include <linux/lcd.h>
+
+#include <video/samsung_fimd.h>
+
+#include <plat/backlight.h>
+#include <plat/gpio-cfg.h>
+#include <plat/fb.h>
+#include <plat/devs.h>
+
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/regs-serial.h>
+#include <plat/usb-phy.h>
#include "common.h"
+static struct s5p_ehci_platdata origen_ehci_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
+static struct exynos4_ohci_platdata origen_ohci_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
+static struct s3c_hsotg_plat origen_hsotg_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
+/* LCD Backlight data */
+static struct samsung_bl_gpio_info origen_bl_gpio_info = {
+ .no = EXYNOS4_GPD0(0),
+ .func = S3C_GPIO_SFN(2),
+};
+
+static struct platform_pwm_backlight_data origen_bl_data = {
+ .pwm_id = 0,
+ .pwm_period_ns = 1000,
+};
+
/*
* The following lookup table is used to override device names when devices
* are registered from device tree. This is temporarily added to enable
@@ -69,6 +112,12 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
"s3c2440-i2c.6", NULL),
OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(7),
"s3c2440-i2c.7", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-hdmiphy-i2c", EXYNOS4_PA_IIC_HDMIPHY,
+ "s3c2440-hdmiphy-i2c", NULL),
+ OF_DEV_AUXDATA("samsung,s5pv210-tvmixer", EXYNOS4_PA_MIXER,
+ "s5p-mixer", NULL),
+ OF_DEV_AUXDATA("samsung,s5pv210-hdmi", EXYNOS4_PA_HDMI,
+ "exynos4-hdmi", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI0,
"exynos4210-spi.0", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI1,
@@ -80,6 +129,16 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU,
"exynos-tmu", NULL),
+ OF_DEV_AUXDATA("samsung,exynos-ehci", EXYNOS4_PA_EHCI, "s5p-ehci",
+ &origen_ehci_pdata),
+ OF_DEV_AUXDATA("samsung,exynos-ohci", EXYNOS4_PA_OHCI, "exynos-ohci",
+ &origen_ohci_pdata),
+ OF_DEV_AUXDATA("samsung,exynos-hsotg", EXYNOS4_PA_HSOTG, "s3c-hsotg",
+ &origen_hsotg_pdata),
+ OF_DEV_AUXDATA("samsung,exynos4210-fimd", EXYNOS4_PA_FIMD0,
+ "exynos4-fb.0", NULL),
+ OF_DEV_AUXDATA("samsung,samsung-i2s", EXYNOS4_PA_I2S0,
+ "samsung-i2s.0", NULL),
{},
};
@@ -89,10 +148,21 @@ static void __init exynos4_dt_map_io(void)
s3c24xx_init_clocks(24000000);
}
+static void __init exynos4_setup_fimd(void)
+{
+ unsigned int reg;
+
+ reg = __raw_readl(S3C_VA_SYS + 0x0210);
+ reg |= (1 << 1);
+ __raw_writel(reg, S3C_VA_SYS + 0x0210);
+}
+
static void __init exynos4_dt_machine_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
exynos4_auxdata_lookup, NULL);
+ samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
+ exynos4_setup_fimd();
}
static char const *exynos4_dt_compat[] __initdata = {
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index e99d3d8f2bc..f479b5b03f5 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -17,15 +17,40 @@
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
+
#include <mach/map.h>
#include <mach/regs-pmu.h>
#include <plat/cpu.h>
#include <plat/regs-serial.h>
#include <plat/mfc.h>
+#include <linux/platform_data/samsung-usbphy.h>
+#include <linux/platform_data/usb-exynos.h>
+
+#include <plat/regs-srom.h>
+#include <plat/devs.h>
+#include <plat/usb-phy.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
#include "common.h"
+
+
+static struct samsung_usbphy_data exynos5_usbphy_pdata = {
+ .pmu_isolation = s5p_usb_phy_pmu_isolation,
+ .phy_cfg_sel = s5p_usb_phy_cfg_sel,
+};
+
+static struct exynos4_ohci_platdata smdk5250_ohci_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
+static struct s5p_ehci_platdata smdk5250_ehci_pdata = {
+ .phy_init = s5p_usb_phy_init,
+ .phy_exit = s5p_usb_phy_exit,
+};
+
/*
* The following lookup table is used to override device names when devices
* are registered from device tree. This is temporarily added to enable
@@ -80,11 +105,11 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
"exynos4210-spi.1", NULL),
OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2,
"exynos4210-spi.2", NULL),
- OF_DEV_AUXDATA("samsung,exynos5-sata-ahci", 0x122F0000,
+ OF_DEV_AUXDATA("samsung,exynos5-sata-ahci", EXYNOS5_PA_SATA_BASE,
"exynos5-sata", NULL),
- OF_DEV_AUXDATA("samsung,exynos5-sata-phy", 0x12170000,
+ OF_DEV_AUXDATA("samsung,exynos5-sata-phy", EXYNOS5_PA_SATA_PHY_CTRL,
"exynos5-sata-phy", NULL),
- OF_DEV_AUXDATA("samsung,exynos5-sata-phy-i2c", 0x121D0000,
+ OF_DEV_AUXDATA("samsung,exynos5-sata-phy-i2c", EXYNOS5_PA_SATA_PHY_I2C,
"exynos5-sata-phy-i2c", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
@@ -104,6 +129,14 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL),
OF_DEV_AUXDATA("samsung,exynos5250-tmu", 0x10060000,
"exynos-tmu", NULL),
+ OF_DEV_AUXDATA("samsung,exynos5250-usbphy", EXYNOS5_PA_HSPHY,
+ "s3c-usbphy", &exynos5_usbphy_pdata),
+ OF_DEV_AUXDATA("samsung,exynos-dwc3", EXYNOS5_PA_DRD,
+ "exynos-dwc3", NULL),
+ OF_DEV_AUXDATA("samsung,exynos-ohci", 0x12120000,
+ "exynos-ohci", &smdk5250_ohci_pdata),
+ OF_DEV_AUXDATA("samsung,exynos-ehci", 0x12110000,
+ "s5p-ehci", &smdk5250_ehci_pdata),
{},
};
@@ -123,6 +156,11 @@ static void __init exynos5_dt_map_io(void)
s3c24xx_init_clocks(24000000);
}
+static void exynos5_i2c_setup(void)
+{ /* Setup the low-speed i2c controller interrupts */
+ writel(0x0, EXYNOS5_SYS_I2C_CFG);
+}
+
static void __init exynos5_dt_machine_init(void)
{
struct device_node *i2c_np;
@@ -147,6 +185,8 @@ static void __init exynos5_dt_machine_init(void)
}
}
+ exynos5_i2c_setup();
+
if (of_machine_is_compatible("samsung,exynos5250"))
of_platform_populate(NULL, of_default_bus_match_table,
exynos5250_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 5e34b9c1619..85f984dff9e 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -20,6 +20,7 @@
#include <linux/gpio_keys.h>
#include <linux/i2c.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <linux/mfd/max8997.h>
#include <linux/lcd.h>
#include <linux/rfkill-gpio.h>
@@ -27,6 +28,8 @@
#include <linux/platform_data/s3c-hsotg.h>
#include <linux/platform_data/usb-ehci-s5p.h>
#include <linux/platform_data/usb-exynos.h>
+#include <linux/ath6kl.h>
+#include <linux/delay.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -34,6 +37,7 @@
#include <video/platform_lcd.h>
#include <video/samsung_fimd.h>
+#include <video/lcd_pwrctrl.h>
#include <plat/regs-serial.h>
#include <plat/cpu.h>
@@ -65,6 +69,11 @@
S5PV210_UFCON_TXTRIG4 | \
S5PV210_UFCON_RXTRIG4)
+enum fixed_regulator_id {
+ FIXED_REG_ID_MMC = 0,
+ FIXED_REG_ID_5V,
+};
+
static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
@@ -96,6 +105,10 @@ static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
},
};
+static struct regulator_consumer_supply __initdata fixed_5v_supply[] = {
+ REGULATOR_SUPPLY("hdmi-en", "exynos4-hdmi"), /* HDMI */
+};
+
static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
@@ -135,7 +148,7 @@ static struct regulator_consumer_supply __initdata buck3_consumer[] = {
REGULATOR_SUPPLY("vdd_g3d", "mali_drm"), /* G3D */
};
static struct regulator_consumer_supply __initdata buck7_consumer[] = {
- REGULATOR_SUPPLY("vcc", "platform-lcd"), /* LCD */
+ REGULATOR_SUPPLY("vcc-lcd", "lcd-pwrctrl.0"), /* LCD */
};
static struct regulator_init_data __initdata max8997_ldo1_data = {
@@ -169,6 +182,7 @@ static struct regulator_init_data __initdata max8997_ldo3_data = {
.min_uV = 1100000,
.max_uV = 1100000,
.apply_uV = 1,
+ .always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
.disabled = 1,
@@ -197,6 +211,7 @@ static struct regulator_init_data __initdata max8997_ldo6_data = {
.min_uV = 1800000,
.max_uV = 1800000,
.apply_uV = 1,
+ .always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
.disabled = 1,
@@ -227,6 +242,7 @@ static struct regulator_init_data __initdata max8997_ldo8_data = {
.min_uV = 3300000,
.max_uV = 3300000,
.apply_uV = 1,
+ .always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
.disabled = 1,
@@ -271,6 +287,7 @@ static struct regulator_init_data __initdata max8997_ldo11_data = {
.min_uV = 3000000,
.max_uV = 3000000,
.apply_uV = 1,
+ .always_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
.disabled = 1,
@@ -361,7 +378,9 @@ static struct regulator_init_data __initdata max8997_buck3_data = {
.constraints = {
.name = "VDD_G3D_1.1V",
.min_uV = 900000,
- .max_uV = 1100000,
+ .max_uV = 1200000,
+ .always_on = 1,
+ .boot_on = 1,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
.state_mem = {
@@ -390,7 +409,7 @@ static struct regulator_init_data __initdata max8997_buck7_data = {
.name = "VDD_LCD_3.3V",
.min_uV = 3300000,
.max_uV = 3300000,
- .boot_on = 1,
+ .boot_on = 0,
.apply_uV = 1,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.state_mem = {
@@ -473,6 +492,49 @@ static struct i2c_board_info i2c0_devs[] __initdata = {
.platform_data = &origen_max8997_pdata,
.irq = IRQ_EINT(4),
},
+#ifdef CONFIG_TOUCHSCREEN_UNIDISPLAY_TS
+ {
+ I2C_BOARD_INFO("unidisplay_ts", 0x41),
+ .irq = IRQ_TS,
+ },
+#endif
+};
+
+static struct regulator_consumer_supply mmc_supplies[] = {
+ REGULATOR_SUPPLY("vmmc", "exynos4-sdhci.0"),
+ REGULATOR_SUPPLY("vmmc", "exynos4-sdhci.2"),
+};
+
+static struct regulator_init_data mmc_fixed_voltage_init_data = {
+ .constraints = {
+ .name = "VMEM_VDD_2.8V",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(mmc_supplies),
+ .consumer_supplies = mmc_supplies,
+};
+
+static struct fixed_voltage_config mmc_fixed_voltage_config = {
+ .supply_name = "MMC_POWER_EN",
+ .microvolts = 2800000,
+ .gpio = EXYNOS4_GPX1(1),
+ .enable_high = true,
+ .init_data = &mmc_fixed_voltage_init_data,
+};
+
+static struct platform_device mmc_fixed_voltage = {
+ .name = "reg-fixed-voltage",
+ .id = FIXED_REG_ID_MMC,
+ .dev = {
+ .platform_data = &mmc_fixed_voltage_config,
+ },
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+ {
+ I2C_BOARD_INFO("alc5625", 0x1E),
+ },
};
static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
@@ -483,6 +545,100 @@ static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
.cd_type = S3C_SDHCI_CD_INTERNAL,
};
+
+/*
+ * WLAN: SDIO Host will call this func at booting time
+ */
+static int origen_wifi_status_register(void (*notify_func)
+ (struct platform_device *, int state));
+
+/* WLAN: MMC3-SDIO */
+static struct s3c_sdhci_platdata origen_hsmmc3_pdata __initdata = {
+ .max_width = 4,
+ .host_caps = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+ .pm_caps = MMC_PM_KEEP_POWER,
+ .cd_type = S3C_SDHCI_CD_EXTERNAL,
+ .ext_cd_init = origen_wifi_status_register,
+};
+
+/*
+ * WLAN: Save SDIO Card detect func into this pointer
+ */
+static void (*wifi_status_cb)(struct platform_device *, int state);
+
+static int origen_wifi_status_register(void (*notify_func)
+ (struct platform_device *, int state))
+{
+ /* Assign sdhci_s3c_notify_change to wifi_status_cb */
+ if (!notify_func)
+ return -EAGAIN;
+ else
+ wifi_status_cb = notify_func;
+
+ return 0;
+}
+
+#define ORIGEN_WLAN_WOW EXYNOS4_GPX2(3)
+#define ORIGEN_WLAN_RESET EXYNOS4_GPX2(4)
+
+
+static void origen_wlan_setup_power(bool val)
+{
+ int err;
+
+ if (val) {
+ err = gpio_request_one(ORIGEN_WLAN_RESET,
+ GPIOF_OUT_INIT_LOW, "GPX2_4");
+ if (err) {
+ pr_warning("ORIGEN: Not obtain WIFI gpios\n");
+ return;
+ }
+ s3c_gpio_cfgpin(ORIGEN_WLAN_RESET, S3C_GPIO_OUTPUT);
+ s3c_gpio_setpull(ORIGEN_WLAN_RESET,
+ S3C_GPIO_PULL_NONE);
+ /* VDD33,I/O Supply must be done */
+ gpio_set_value(ORIGEN_WLAN_RESET, 0);
+ udelay(30); /*Tb */
+ gpio_direction_output(ORIGEN_WLAN_RESET, 1);
+ } else {
+ gpio_direction_output(ORIGEN_WLAN_RESET, 0);
+ gpio_free(ORIGEN_WLAN_RESET);
+ }
+
+ mdelay(100);
+
+ return;
+}
+
+/*
+ * This will be called at init time of WLAN driver
+ */
+static int origen_wifi_set_detect(bool val)
+{
+
+ if (!wifi_status_cb) {
+ pr_warning("ORIGEN: WLAN: No callback \n"
+ "ORIGEN: WLAN: MMC should boot earlier than net \n");
+
+ return -EAGAIN;
+ }
+ if (true == val) {
+ origen_wlan_setup_power(true);
+ wifi_status_cb(&s3c_device_hsmmc3, 1);
+ } else {
+ origen_wlan_setup_power(false);
+ wifi_status_cb(&s3c_device_hsmmc3, 0);
+ }
+
+ return 0;
+}
+
+struct ath6kl_platform_data origen_wlan_data __initdata = {
+ .setup_power = origen_wifi_set_detect,
+};
+
+
/* USB EHCI */
static struct s5p_ehci_platdata origen_ehci_pdata;
@@ -590,29 +746,12 @@ static struct platform_device origen_device_gpiokeys = {
},
};
-static void lcd_hv070wsa_set_power(struct plat_lcd_data *pd, unsigned int power)
-{
- int ret;
-
- if (power)
- ret = gpio_request_one(EXYNOS4_GPE3(4),
- GPIOF_OUT_INIT_HIGH, "GPE3_4");
- else
- ret = gpio_request_one(EXYNOS4_GPE3(4),
- GPIOF_OUT_INIT_LOW, "GPE3_4");
-
- gpio_free(EXYNOS4_GPE3(4));
-
- if (ret)
- pr_err("failed to request gpio for LCD power: %d\n", ret);
-}
-
-static struct plat_lcd_data origen_lcd_hv070wsa_data = {
- .set_power = lcd_hv070wsa_set_power,
+static struct lcd_pwrctrl_data origen_lcd_hv070wsa_data = {
+ .gpio = EXYNOS4_GPE3(4),
};
static struct platform_device origen_lcd_hv070wsa = {
- .name = "platform-lcd",
+ .name = "lcd-pwrctrl",
.dev.parent = &s5p_device_fimd0.dev,
.dev.platform_data = &origen_lcd_hv070wsa_data,
};
@@ -646,7 +785,25 @@ static struct s3c_fb_pd_win origen_fb_win0 = {
.xres = 1024,
.yres = 600,
.max_bpp = 32,
- .default_bpp = 24,
+ .default_bpp = 32,
+ .virtual_x = 1024,
+ .virtual_y = 2 * 600,
+};
+
+static struct s3c_fb_pd_win origen_fb_win1 = {
+ .xres = 1024,
+ .yres = 600,
+ .max_bpp = 32,
+ .default_bpp = 32,
+ .virtual_x = 1024,
+ .virtual_y = 2 * 600,
+};
+
+static struct s3c_fb_pd_win origen_fb_win2 = {
+ .xres = 1024,
+ .yres = 600,
+ .max_bpp = 32,
+ .default_bpp = 32,
.virtual_x = 1024,
.virtual_y = 2 * 600,
};
@@ -664,6 +821,8 @@ static struct fb_videomode origen_lcd_timing = {
static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
.win[0] = &origen_fb_win0,
+ .win[1] = &origen_fb_win1,
+ .win[2] = &origen_fb_win2,
.vtiming = &origen_lcd_timing,
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
@@ -690,9 +849,12 @@ static struct platform_device origen_device_bluetooth = {
};
static struct platform_device *origen_devices[] __initdata = {
+ &mmc_fixed_voltage,
&s3c_device_hsmmc2,
&s3c_device_hsmmc0,
+ &s3c_device_hsmmc3,
&s3c_device_i2c0,
+ &s3c_device_i2c1,
&s3c_device_rtc,
&s3c_device_usb_hsotg,
&s3c_device_wdt,
@@ -704,6 +866,7 @@ static struct platform_device *origen_devices[] __initdata = {
&s5p_device_fimc_md,
&s5p_device_fimd0,
&s5p_device_g2d,
+ &s5p_device_g3d,
&s5p_device_hdmi,
&s5p_device_i2c_hdmiphy,
&s5p_device_jpeg,
@@ -711,6 +874,7 @@ static struct platform_device *origen_devices[] __initdata = {
&s5p_device_mfc_l,
&s5p_device_mfc_r,
&s5p_device_mixer,
+ &exynos4_device_i2s0,
&exynos4_device_ohci,
&origen_device_gpiokeys,
&origen_lcd_hv070wsa,
@@ -768,7 +932,7 @@ static void __init origen_power_init(void)
static void __init origen_reserve(void)
{
- s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
+ s5p_mfc_reserve_mem(0x43000000, 32 << 20, 0x51000000, 32 << 20);
}
static void __init origen_machine_init(void)
@@ -778,12 +942,16 @@ static void __init origen_machine_init(void)
s3c_i2c0_set_platdata(NULL);
i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+ s3c_i2c1_set_platdata(NULL);
+ i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+
/*
* Since sdhci instance 2 can contain a bootable media,
* sdhci instance 0 is registered after instance 2.
*/
s3c_sdhci2_set_platdata(&origen_hsmmc2_pdata);
s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata);
+ s3c_sdhci3_set_platdata(&origen_hsmmc3_pdata);
origen_ehci_init();
origen_ohci_init();
@@ -800,12 +968,17 @@ static void __init origen_machine_init(void)
s5p_fimd0_set_platdata(&origen_lcd_pdata);
#endif
+ regulator_register_always_on(FIXED_REG_ID_5V, "Fixed 5V",
+ fixed_5v_supply, ARRAY_SIZE(fixed_5v_supply), 5000000);
+
platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
pwm_add_table(origen_pwm_lookup, ARRAY_SIZE(origen_pwm_lookup));
samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
origen_bt_setup();
+
+ ath6kl_set_platform_data(&origen_wlan_data);
}
MACHINE_START(ORIGEN, "ORIGEN")
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index 9f1351de52f..b9bfc3b9643 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -276,6 +276,11 @@ static __init int exynos4_pm_init_power_domain(void)
#ifdef CONFIG_S5P_DEV_G2D
exynos_pm_add_dev_to_genpd(&s5p_device_g2d, &exynos4_pd_lcd0);
#endif
+#ifdef CONFIG_S5P_DEV_G3D
+ /* MALI requires the PD to be always on. */
+ exynos4_pd_g3d.pd.power_off = NULL;
+ exynos_pm_add_dev_to_genpd(&s5p_device_g3d, &exynos4_pd_g3d);
+#endif
#ifdef CONFIG_S5P_DEV_JPEG
exynos_pm_add_dev_to_genpd(&s5p_device_jpeg, &exynos4_pd_cam);
#endif
diff --git a/arch/arm/mach-exynos/setup-usb-phy.c b/arch/arm/mach-exynos/setup-usb-phy.c
index b81cc569a8d..78100981b0b 100644
--- a/arch/arm/mach-exynos/setup-usb-phy.c
+++ b/arch/arm/mach-exynos/setup-usb-phy.c
@@ -14,24 +14,75 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
#include <mach/regs-pmu.h>
#include <mach/regs-usb-phy.h>
#include <plat/cpu.h>
+#include <plat/map-base.h>
#include <plat/usb-phy.h>
+#define PHY_ENABLE 1
+#define PHY_DISABLE 0
+#define EXYNOS5_USB_CFG (S3C_VA_SYS + 0x230)
+
static atomic_t host_usage;
static int exynos4_usb_host_phy_is_on(void)
{
- return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
+ if (soc_is_exynos5250()) {
+ return (readl(EXYNOS5_PHY_HOST_CTRL0) &
+ HOST_CTRL0_PHYSWRSTALL) ? 0 : 1;
+ } else {
+ return (readl(EXYNOS4_PHYPWR) &
+ PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
+ }
+}
+
+static void exynos_usb_mux_change(struct platform_device *pdev, int val)
+{
+ u32 is_host;
+ if (soc_is_exynos5250()) {
+ is_host = readl(EXYNOS5_USB_CFG);
+ writel(val, EXYNOS5_USB_CFG);
+ }
+ if (is_host != val)
+ dev_dbg(&pdev->dev, "Change USB MUX from %s to %s",
+ is_host ? "Host" : "Device", val ? "Host" : "Device");
}
-static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
+static struct clk *exynos_usb_clock_enable(struct platform_device *pdev)
+{
+ struct clk *usb_clk = NULL;
+ int err = 0;
+
+ if (soc_is_exynos5250())
+ usb_clk = clk_get(&pdev->dev, "usbhost");
+ else
+ usb_clk = clk_get(&pdev->dev, "otg");
+ if (IS_ERR(usb_clk)) {
+ dev_err(&pdev->dev, "Failed to get otg clock\n");
+ return NULL;
+ }
+
+ err = clk_enable(usb_clk);
+ if (err) {
+ clk_put(usb_clk);
+ return NULL;
+ }
+ return usb_clk;
+}
+
+static int exynos4210_usb_phy_clkset(struct platform_device *pdev)
{
struct clk *xusbxti_clk;
- u32 phyclk;
+ u32 phyclk = 0;
+
+ if (soc_is_exynos5250())
+ xusbxti_clk = clk_get(&pdev->dev, "ext_xtal");
+ else
+ xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
- xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
if (soc_is_exynos4210()) {
/* set clock frequency for PLL */
@@ -77,11 +128,47 @@ static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
break;
}
writel(phyclk, EXYNOS4_PHYCLK);
+ } else if (soc_is_exynos5250()) {
+ /* set clock frequency for PLL */
+ switch (clk_get_rate(xusbxti_clk)) {
+ case 96 * 100000:
+ phyclk |= EXYNOS5_CLKSEL_9600K;
+ break;
+ case 10 * MHZ:
+ phyclk |= EXYNOS5_CLKSEL_10M;
+ break;
+ case 12 * MHZ:
+ phyclk |= EXYNOS5_CLKSEL_12M;
+ break;
+ case 192 * 100000:
+ phyclk |= EXYNOS5_CLKSEL_19200K;
+ break;
+ case 20 * MHZ:
+ phyclk |= EXYNOS5_CLKSEL_20M;
+ break;
+ case 50 * MHZ:
+ phyclk |= EXYNOS5_CLKSEL_50M;
+ break;
+ case 24 * MHZ:
+ default:
+ /* default reference clock */
+ phyclk |= EXYNOS5_CLKSEL_24M;
+ break;
+ }
}
clk_put(xusbxti_clk);
}
+ return phyclk;
}
-
+#if 0
+static void exynos_usb_phy_control(enum usb_phy_type phy_type , int on)
+{
+ if (soc_is_exynos5250()) {
+ if (phy_type & USB_PHY)
+ writel(on, S5P_USBHOST_PHY_CONTROL);
+ }
+}
+#endif
static int exynos4210_usb_phy0_init(struct platform_device *pdev)
{
u32 rstcon;
@@ -120,21 +207,12 @@ static int exynos4210_usb_phy1_init(struct platform_device *pdev)
{
struct clk *otg_clk;
u32 rstcon;
- int err;
atomic_inc(&host_usage);
- otg_clk = clk_get(&pdev->dev, "otg");
- if (IS_ERR(otg_clk)) {
- dev_err(&pdev->dev, "Failed to get otg clock\n");
- return PTR_ERR(otg_clk);
- }
-
- err = clk_enable(otg_clk);
- if (err) {
- clk_put(otg_clk);
- return err;
- }
+ otg_clk = exynos_usb_clock_enable(pdev);
+ if (otg_clk == NULL)
+ dev_err(&pdev->dev, "Failed to enable otg clock\n");
if (exynos4_usb_host_phy_is_on())
return 0;
@@ -173,22 +251,13 @@ static int exynos4210_usb_phy1_init(struct platform_device *pdev)
static int exynos4210_usb_phy1_exit(struct platform_device *pdev)
{
struct clk *otg_clk;
- int err;
if (atomic_dec_return(&host_usage) > 0)
return 0;
- otg_clk = clk_get(&pdev->dev, "otg");
- if (IS_ERR(otg_clk)) {
- dev_err(&pdev->dev, "Failed to get otg clock\n");
- return PTR_ERR(otg_clk);
- }
-
- err = clk_enable(otg_clk);
- if (err) {
- clk_put(otg_clk);
- return err;
- }
+ otg_clk = exynos_usb_clock_enable(pdev);
+ if (otg_clk == NULL)
+ dev_err(&pdev->dev, "Failed to enable otg clock\n");
writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
EXYNOS4_PHYPWR);
@@ -202,22 +271,70 @@ static int exynos4210_usb_phy1_exit(struct platform_device *pdev)
return 0;
}
+
int s5p_usb_phy_init(struct platform_device *pdev, int type)
{
- if (type == S5P_USB_PHY_DEVICE)
+ if (type == USB_PHY_TYPE_DEVICE)
return exynos4210_usb_phy0_init(pdev);
- else if (type == S5P_USB_PHY_HOST)
- return exynos4210_usb_phy1_init(pdev);
+ else if (type == USB_PHY_TYPE_HOST) {
+ return exynos4210_usb_phy1_init(pdev);
+ }
return -EINVAL;
}
int s5p_usb_phy_exit(struct platform_device *pdev, int type)
{
- if (type == S5P_USB_PHY_DEVICE)
- return exynos4210_usb_phy0_exit(pdev);
- else if (type == S5P_USB_PHY_HOST)
- return exynos4210_usb_phy1_exit(pdev);
+ if (type == USB_PHY_TYPE_DEVICE)
+ return exynos4210_usb_phy0_exit(pdev);
+ else if (type == USB_PHY_TYPE_HOST) {
+ return exynos4210_usb_phy1_exit(pdev);
+ }
return -EINVAL;
}
+
+ void s5p_usb_phy_pmu_isolation(int on, int type)
+ {
+ if (type == USB_PHY_TYPE_HOST) {
+ if (on)
+ writel(readl(S5P_USBHOST_PHY_CONTROL)
+ & ~S5P_USBHOST_PHY_ENABLE,
+ S5P_USBHOST_PHY_CONTROL);
+ else
+ writel(readl(S5P_USBHOST_PHY_CONTROL)
+ | S5P_USBHOST_PHY_ENABLE,
+ S5P_USBHOST_PHY_CONTROL);
+ }else if(type == USB_PHY_TYPE_DRD) {
+ if (on)
+ writel(readl(S5P_USBDRD_PHY_CONTROL)
+ & ~S5P_USBDRD_PHY_ENABLE,
+ S5P_USBDRD_PHY_CONTROL);
+ else
+ writel(readl(S5P_USBDRD_PHY_CONTROL)
+ | S5P_USBDRD_PHY_ENABLE,
+ S5P_USBDRD_PHY_CONTROL);
+ } else {
+ if (on)
+ writel(readl(S5P_USBDEVICE_PHY_CONTROL)
+ & ~S5P_USBDEVICE_PHY_ENABLE,
+ S5P_USBDEVICE_PHY_CONTROL);
+ else
+ writel(readl(S5P_USBDEVICE_PHY_CONTROL)
+ | S5P_USBDEVICE_PHY_ENABLE,
+ S5P_USBDEVICE_PHY_CONTROL);
+ }
+ }
+
+/* Switch between HOST and OTG link from PHY_CFG */
+void s5p_usb_phy_cfg_sel(struct device *dev, int type)
+{
+ u32 is_host;
+
+ is_host = readl(EXYNOS5_USB_CFG);
+ writel(type, EXYNOS5_USB_CFG);
+
+ if (is_host != type)
+ dev_dbg(dev, "Changed USB MUX from %s to %s",
+ is_host ? "Host" : "Device", type ? "Host" : "Device");
+}
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 9d32a253aac..684a5fe84ea 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -17,6 +17,12 @@ obj-$(CONFIG_MODULES) += proc-syms.o
obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+ifeq ($(CONFIG_ARM_LPAE),y)
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage-3level.o
+else
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage-2level.o
+endif
obj-$(CONFIG_CPU_ABRT_NOMMU) += abort-nommu.o
obj-$(CONFIG_CPU_ABRT_EV4) += abort-ev4.o
@@ -97,3 +103,5 @@ obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o
obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o
+
+obj-$(CONFIG_NUMA_ALLOC_NODES) += numa.o
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index bc4a5e9ebb7..7c17ff80882 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -20,6 +20,7 @@
#include <asm/smp_plat.h>
#include <asm/thread_notify.h>
#include <asm/tlbflush.h>
+#include <asm/proc-fns.h>
/*
* On ARMv6, we have the following structure in the Context ID:
@@ -52,17 +53,11 @@ static cpumask_t tlb_flush_pending;
#ifdef CONFIG_ARM_LPAE
static void cpu_set_reserved_ttbr0(void)
{
- unsigned long ttbl = __pa(swapper_pg_dir);
- unsigned long ttbh = 0;
-
/*
* Set TTBR0 to swapper_pg_dir which contains only global entries. The
* ASID is set to 0.
*/
- asm volatile(
- " mcrr p15, 0, %0, %1, c2 @ set TTBR0\n"
- :
- : "r" (ttbl), "r" (ttbh));
+ cpu_set_ttbr(0, __pa(swapper_pg_dir));
isb();
}
#else
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 6b2fb87c869..d2c7c3acf51 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -239,7 +239,7 @@ static void __dma_free_buffer(struct page *page, size_t size)
#ifdef CONFIG_MMU
#ifdef CONFIG_HUGETLB_PAGE
-#error ARM Coherent DMA allocator does not (yet) support huge TLB
+#warning ARM Coherent DMA allocator does not (yet) support huge TLB
#endif
static void *__alloc_from_contiguous(struct device *dev, size_t size,
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index e207aa5f846..b55bec0f1f0 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -497,13 +497,13 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
#endif /* CONFIG_MMU */
/*
- * Some section permission faults need to be handled gracefully.
- * They can happen due to a __{get,put}_user during an oops.
+ * A fault in a section will likely be due to a huge page, treat it
+ * as a page fault.
*/
static int
do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
- do_bad_area(addr, fsr, regs);
+ do_page_fault(addr, fsr, regs);
return 0;
}
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 1c8f7f56417..0a69cb83a22 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -17,6 +17,7 @@
#include <asm/highmem.h>
#include <asm/smp_plat.h>
#include <asm/tlbflush.h>
+#include <linux/hugetlb.h>
#include "mm.h"
@@ -168,17 +169,21 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
* coherent with the kernels mapping.
*/
if (!PageHighMem(page)) {
- __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
+ __cpuc_flush_dcache_area(page_address(page), (PAGE_SIZE << compound_order(page)));
} else {
- void *addr = kmap_high_get(page);
- if (addr) {
- __cpuc_flush_dcache_area(addr, PAGE_SIZE);
- kunmap_high(page);
- } else if (cache_is_vipt()) {
- /* unmapped pages might still be cached */
- addr = kmap_atomic(page);
- __cpuc_flush_dcache_area(addr, PAGE_SIZE);
- kunmap_atomic(addr);
+ unsigned long i;
+ for(i = 0; i < (1 << compound_order(page)); i++) {
+ struct page *cpage = page + i;
+ void *addr = kmap_high_get(cpage);
+ if (addr) {
+ __cpuc_flush_dcache_area(addr, PAGE_SIZE);
+ kunmap_high(cpage);
+ } else if (cache_is_vipt()) {
+ /* unmapped pages might still be cached */
+ addr = kmap_atomic(cpage);
+ __cpuc_flush_dcache_area(addr, PAGE_SIZE);
+ kunmap_atomic(addr);
+ }
}
}
diff --git a/arch/arm/mm/fsr-3level.c b/arch/arm/mm/fsr-3level.c
index 05a4e943183..47f4c6fb25b 100644
--- a/arch/arm/mm/fsr-3level.c
+++ b/arch/arm/mm/fsr-3level.c
@@ -9,7 +9,7 @@ static struct fsr_info fsr_info[] = {
{ do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
{ do_bad, SIGBUS, 0, "reserved access flag fault" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
- { do_bad, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
+ { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
{ do_bad, SIGBUS, 0, "reserved permission fault" },
{ do_bad, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
diff --git a/arch/arm/mm/hugetlbpage-2level.c b/arch/arm/mm/hugetlbpage-2level.c
new file mode 100644
index 00000000000..4b2b38ca0f4
--- /dev/null
+++ b/arch/arm/mm/hugetlbpage-2level.c
@@ -0,0 +1,115 @@
+/*
+ * arch/arm/mm/hugetlbpage-2level.c
+ *
+ * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 2012 ARM Ltd
+ * Copyright (C) 2012 Bill Carson.
+ *
+ * Based on arch/x86/include/asm/hugetlb.h and Bill Carson's patches
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+ return 0;
+}
+
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ pgd = pgd_offset(mm, addr);
+ pud = pud_offset(pgd, addr);
+ pmd = pmd_offset(pud, addr);
+
+ return (pte_t *)pmd; /* our huge pte is actually a pmd */
+}
+
+struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ pmd_t *pmd, int write)
+{
+ struct page *page;
+ unsigned long pfn;
+
+ BUG_ON((pmd_val(*pmd) & PMD_TYPE_MASK) != PMD_TYPE_SECT);
+ pfn = ((pmd_val(*pmd) & HPAGE_MASK) >> PAGE_SHIFT);
+ page = pfn_to_page(pfn);
+ return page;
+}
+
+pte_t huge_ptep_get(pte_t *ptep)
+{
+ pmd_t *pmdp = (pmd_t*)ptep;
+ pmdval_t pmdval = pmd_val(*pmdp);
+ pteval_t retval;
+
+ if (!pmdval)
+ return __pte(0);
+
+ retval = (pteval_t) (pmdval & HPAGE_MASK);
+ HPMD_XLATE(retval, pmdval, PMD_SECT_XN, L_PTE_XN);
+ HPMD_XLATE(retval, pmdval, PMD_SECT_S, L_PTE_SHARED);
+ HPMD_XLATE(retval, pmdval, PMD_DSECT_AF, L_PTE_YOUNG);
+ HPMD_XLATE(retval, pmdval, PMD_DSECT_DIRTY, L_PTE_DIRTY);
+
+ /* preserve bits C & B */
+ retval |= (pmdval & (3 << 2));
+
+ /* PMD TEX bit 0 corresponds to Linux PTE bit 4 */
+ HPMD_XLATE(retval, pmdval, PMD_SECT_TEX(1), 1 << 4);
+
+ if (pmdval & PMD_SECT_AP_WRITE)
+ retval &= ~L_PTE_RDONLY;
+ else
+ retval |= L_PTE_RDONLY;
+
+ if ((pmdval & PMD_TYPE_MASK) == PMD_TYPE_SECT)
+ retval |= L_PTE_VALID;
+
+ /* we assume all hugetlb pages are user */
+ retval |= L_PTE_USER;
+
+ return __pte(retval);
+}
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ pmdval_t pmdval = (pmdval_t) pte_val(pte);
+ pmd_t *pmdp = (pmd_t*) ptep;
+
+ pmdval &= HPAGE_MASK;
+ pmdval |= PMD_SECT_AP_READ | PMD_SECT_nG | PMD_TYPE_SECT;
+ pmdval = pmd_val(pmd_modify(__pmd(pmdval), __pgprot(pte_val(pte))));
+
+ __sync_icache_dcache(pte);
+
+ set_pmd_at(mm, addr, pmdp, __pmd(pmdval));
+}
diff --git a/arch/arm/mm/hugetlbpage-3level.c b/arch/arm/mm/hugetlbpage-3level.c
new file mode 100644
index 00000000000..86474f01104
--- /dev/null
+++ b/arch/arm/mm/hugetlbpage-3level.c
@@ -0,0 +1,190 @@
+/*
+ * arch/arm/mm/hugetlbpage-3level.c
+ *
+ * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * Based on arch/x86/mm/hugetlbpage.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+
+static unsigned long page_table_shareable(struct vm_area_struct *svma,
+ struct vm_area_struct *vma,
+ unsigned long addr, pgoff_t idx)
+{
+ unsigned long saddr = ((idx - svma->vm_pgoff) << PAGE_SHIFT) +
+ svma->vm_start;
+ unsigned long sbase = saddr & PUD_MASK;
+ unsigned long s_end = sbase + PUD_SIZE;
+
+ /* Allow segments to share if only one is marked locked */
+ unsigned long vm_flags = vma->vm_flags & ~VM_LOCKED;
+ unsigned long svm_flags = svma->vm_flags & ~VM_LOCKED;
+
+ /*
+ * match the virtual addresses, permission and the alignment of the
+ * page table page.
+ */
+ if (pmd_index(addr) != pmd_index(saddr) ||
+ vm_flags != svm_flags ||
+ sbase < svma->vm_start || svma->vm_end < s_end)
+ return 0;
+
+ return saddr;
+}
+
+static int vma_shareable(struct vm_area_struct *vma, unsigned long addr)
+{
+ unsigned long base = addr & PUD_MASK;
+ unsigned long end = base + PUD_SIZE;
+
+ /*
+ * check on proper vm_flags and page table alignment
+ */
+ if (vma->vm_flags & VM_MAYSHARE &&
+ vma->vm_start <= base && end <= vma->vm_end)
+ return 1;
+ return 0;
+}
+
+/*
+ * search for a shareable pmd page for hugetlb.
+ */
+static pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr,
+ pud_t *pud)
+{
+ struct vm_area_struct *vma = find_vma(mm, addr);
+ struct address_space *mapping = vma->vm_file->f_mapping;
+ pgoff_t idx = ((addr - vma->vm_start) >> PAGE_SHIFT) +
+ vma->vm_pgoff;
+ struct vm_area_struct *svma;
+ unsigned long saddr;
+ pte_t *spte = NULL;
+ pte_t *pte;
+
+ if (!vma_shareable(vma, addr))
+ return (pte_t *)pmd_alloc(mm, pud, addr);
+
+ mutex_lock(&mapping->i_mmap_mutex);
+ vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
+ if (svma == vma)
+ continue;
+
+ saddr = page_table_shareable(svma, vma, addr, idx);
+ if (saddr) {
+ spte = huge_pte_offset(svma->vm_mm, saddr);
+ if (spte) {
+ get_page(virt_to_page(spte));
+ break;
+ }
+ }
+ }
+
+ if (!spte)
+ goto out;
+
+ spin_lock(&mm->page_table_lock);
+ if (pud_none(*pud))
+ pud_populate(mm, pud, (pmd_t *)((unsigned long)spte & PAGE_MASK));
+ else
+ put_page(virt_to_page(spte));
+ spin_unlock(&mm->page_table_lock);
+out:
+ pte = (pte_t *)pmd_alloc(mm, pud, addr);
+ mutex_unlock(&mapping->i_mmap_mutex);
+ return pte;
+}
+
+/*
+ * unmap huge page backed by shared pte.
+ *
+ * Hugetlb pte page is ref counted at the time of mapping. If pte is shared
+ * indicated by page_count > 1, unmap is achieved by clearing pud and
+ * decrementing the ref count. If count == 1, the pte page is not shared.
+ *
+ * called with vma->vm_mm->page_table_lock held.
+ *
+ * returns: 1 successfully unmapped a shared pte page
+ * 0 the underlying pte page is not shared, or it is the last user
+ */
+int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep)
+{
+ pgd_t *pgd = pgd_offset(mm, *addr);
+ pud_t *pud = pud_offset(pgd, *addr);
+
+ BUG_ON(page_count(virt_to_page(ptep)) == 0);
+ if (page_count(virt_to_page(ptep)) == 1)
+ return 0;
+
+ pud_clear(pud);
+ put_page(virt_to_page(ptep));
+ *addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE;
+ return 1;
+}
+
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+ unsigned long addr, unsigned long sz)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pte_t *pte = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ pud = pud_alloc(mm, pgd, addr);
+ if (pud) {
+ BUG_ON(sz != PMD_SIZE);
+ if (pud_none(*pud))
+ pte = huge_pmd_share(mm, addr, pud);
+ else
+ pte = (pte_t *)pmd_alloc(mm, pud, addr);
+ }
+ BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));
+
+ return pte;
+}
+
+struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ pmd_t *pmd, int write)
+{
+ struct page *page;
+
+ page = pte_page(*(pte_t *)pmd);
+ if (page)
+ page += ((address & ~PMD_MASK) >> PAGE_SHIFT);
+ return page;
+}
+
+struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address,
+ pud_t *pud, int write)
+{
+ struct page *page;
+
+ page = pte_page(*(pte_t *)pud);
+ if (page)
+ page += ((address & ~PUD_MASK) >> PAGE_SHIFT);
+ return page;
+}
diff --git a/arch/arm/mm/hugetlbpage.c b/arch/arm/mm/hugetlbpage.c
new file mode 100644
index 00000000000..32fe7fdae0a
--- /dev/null
+++ b/arch/arm/mm/hugetlbpage.c
@@ -0,0 +1,65 @@
+/*
+ * arch/arm/mm/hugetlbpage.c
+ *
+ * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * Based on arch/x86/mm/hugetlbpage.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <linux/sysctl.h>
+#include <asm/mman.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (pgd_present(*pgd)) {
+ pud = pud_offset(pgd, addr);
+ if (pud_present(*pud))
+ pmd = pmd_offset(pud, addr);
+ }
+
+ return (pte_t *)pmd;
+}
+
+struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+ int write)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+int pmd_huge(pmd_t pmd)
+{
+ return (pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT;
+}
+
+int pud_huge(pud_t pud)
+{
+ return 0;
+}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index ad722f1208a..e5c80b6a4c8 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -33,15 +33,17 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
+#include <asm/mmzone.h>
#include "mm.h"
-static unsigned long phys_initrd_start __initdata = 0;
+static phys_addr_t phys_initrd_start __initdata = 0;
static unsigned long phys_initrd_size __initdata = 0;
static int __init early_initrd(char *p)
{
- unsigned long start, size;
+ phys_addr_t start;
+ unsigned long size;
char *endp;
start = memparse(p, &endp);
@@ -94,36 +96,56 @@ void show_mem(unsigned int filter)
{
int free = 0, total = 0, reserved = 0;
int shared = 0, cached = 0, slab = 0, i;
- struct meminfo * mi = &meminfo;
+ struct meminfo *mi = &meminfo;
+ struct memblock_region *reg;
printk("Mem-info:\n");
show_free_areas(filter);
for_each_bank (i, mi) {
struct membank *bank = &mi->bank[i];
- unsigned int pfn1, pfn2;
- struct page *page, *end;
-
- pfn1 = bank_pfn_start(bank);
- pfn2 = bank_pfn_end(bank);
-
- page = pfn_to_page(pfn1);
- end = pfn_to_page(pfn2 - 1) + 1;
-
- do {
- total++;
- if (PageReserved(page))
- reserved++;
- else if (PageSwapCache(page))
- cached++;
- else if (PageSlab(page))
- slab++;
- else if (!page_count(page))
- free++;
- else
- shared += page_count(page) - 1;
- page++;
- } while (page < end);
+ unsigned int sbank, ebank;
+
+ sbank = bank_pfn_start(bank);
+ ebank = bank_pfn_end(bank);
+
+ /* consider every memory block that intersects our memory bank */
+ for_each_memblock(memory, reg) {
+ struct page *page, *end;
+ unsigned int pfn1, pfn2;
+ unsigned int sblock = memblock_region_memory_base_pfn(reg);
+ unsigned int eblock = memblock_region_memory_end_pfn(reg);
+
+ /* we're beyond the membank */
+ if (sblock >= ebank)
+ break;
+
+ /* we're not yet at the membank */
+ if (eblock <= sbank)
+ continue;
+
+ /* take the intersection between bank and block */
+ pfn1 = max(sblock, sbank);
+ pfn2 = min(eblock, ebank);
+
+ page = pfn_to_page(pfn1);
+ end = pfn_to_page(pfn2 - 1) + 1;
+
+ do {
+ total++;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (PageSlab(page))
+ slab++;
+ else if (!page_count(page))
+ free++;
+ else
+ shared += page_count(page) - 1;
+ page++;
+ } while (page < end);
+ }
}
printk("%d pages of RAM\n", total);
@@ -158,6 +180,12 @@ static void __init arm_bootmem_init(unsigned long start_pfn,
pg_data_t *pgdat;
/*
+ * If we have NUMA or discontiguous memory, allocate the required
+ * nodes by reserving memblocks.
+ */
+ arm_numa_alloc_nodes(end_pfn);
+
+ /*
* Allocate the bootmem bitmap page. This must be in a region
* of memory which has already been mapped.
*/
@@ -241,56 +269,31 @@ void __init setup_dma_zone(struct machine_desc *mdesc)
static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
unsigned long max_high)
{
- unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
- struct memblock_region *reg;
+ unsigned long max_zone_pfns[MAX_NR_ZONES];
/*
- * initialise the zones.
- */
- memset(zone_size, 0, sizeof(zone_size));
-
- /*
- * The memory size has already been determined. If we need
- * to do anything fancy with the allocation of this memory
- * to the zones, now is the time to do it.
+ * On NUMA systems we register a CPU notifier, split the memory between
+ * the nodes and bring them online before free_area_init_nodes).
+ *
+ * Otherwise, we put all memory into node 0.
*/
- zone_size[0] = max_low - min;
-#ifdef CONFIG_HIGHMEM
- zone_size[ZONE_HIGHMEM] = max_high - max_low;
-#endif
-
+ arm_setup_nodes(min, max_high);
+
/*
- * Calculate the size of the holes.
- * holes = node_size - sum(bank_sizes)
+ * initialise the zones.
*/
- memcpy(zhole_size, zone_size, sizeof(zhole_size));
- for_each_memblock(memory, reg) {
- unsigned long start = memblock_region_memory_base_pfn(reg);
- unsigned long end = memblock_region_memory_end_pfn(reg);
+ memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
+ max_zone_pfns[ZONE_NORMAL] = max_low;
- if (start < max_low) {
- unsigned long low_end = min(end, max_low);
- zhole_size[0] -= low_end - start;
- }
#ifdef CONFIG_HIGHMEM
- if (end > max_low) {
- unsigned long high_start = max(start, max_low);
- zhole_size[ZONE_HIGHMEM] -= end - high_start;
- }
+ max_zone_pfns[ZONE_HIGHMEM] = max_high;
#endif
- }
-#ifdef CONFIG_ZONE_DMA
- /*
- * Adjust the sizes according to any special requirements for
- * this machine type.
- */
- if (arm_dma_zone_size)
- arm_adjust_dma_zone(zone_size, zhole_size,
- arm_dma_zone_size >> PAGE_SHIFT);
+#ifdef CONFIG_DMA
+ max_zone_pfns[ZONE_DMA] = __phys_to_pfn(arm_dma_limit);
#endif
- free_area_init_node(0, zone_size, min, zhole_size);
+ free_area_init_nodes(max_zone_pfns);
}
#ifdef CONFIG_HAVE_ARCH_PFN_VALID
@@ -347,14 +350,14 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
#ifdef CONFIG_BLK_DEV_INITRD
if (phys_initrd_size &&
!memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) {
- pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n",
- phys_initrd_start, phys_initrd_size);
+ pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n",
+ (u64)phys_initrd_start, phys_initrd_size);
phys_initrd_start = phys_initrd_size = 0;
}
if (phys_initrd_size &&
memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) {
- pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n",
- phys_initrd_start, phys_initrd_size);
+ pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n",
+ (u64)phys_initrd_start, phys_initrd_size);
phys_initrd_start = phys_initrd_size = 0;
}
if (phys_initrd_size) {
@@ -457,7 +460,7 @@ static inline void
free_memmap(unsigned long start_pfn, unsigned long end_pfn)
{
struct page *start_pg, *end_pg;
- unsigned long pg, pgend;
+ phys_addr_t pg, pgend;
/*
* Convert start_pfn/end_pfn to a struct page pointer.
@@ -469,8 +472,8 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn)
* Convert to physical addresses, and
* round start upwards and end downwards.
*/
- pg = (unsigned long)PAGE_ALIGN(__pa(start_pg));
- pgend = (unsigned long)__pa(end_pg) & PAGE_MASK;
+ pg = PAGE_ALIGN(__pa(start_pg));
+ pgend = __pa(end_pg) & PAGE_MASK;
/*
* If there are free pages between these,
@@ -600,7 +603,9 @@ void __init mem_init(void)
extern u32 itcm_end;
#endif
+#ifdef CONFIG_FLATMEM
max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
+#endif
/* this will put all unused low memory onto the freelists */
free_unused_memmap(&meminfo);
@@ -619,22 +624,41 @@ void __init mem_init(void)
for_each_bank(i, &meminfo) {
struct membank *bank = &meminfo.bank[i];
- unsigned int pfn1, pfn2;
- struct page *page, *end;
-
- pfn1 = bank_pfn_start(bank);
- pfn2 = bank_pfn_end(bank);
-
- page = pfn_to_page(pfn1);
- end = pfn_to_page(pfn2 - 1) + 1;
-
- do {
- if (PageReserved(page))
- reserved_pages++;
- else if (!page_count(page))
- free_pages++;
- page++;
- } while (page < end);
+ unsigned int sbank, ebank;
+
+ sbank = bank_pfn_start(bank);
+ ebank = bank_pfn_end(bank);
+
+ /* consider every memory block that intersects our memory bank */
+ for_each_memblock(memory, reg) {
+ struct page *page, *end;
+ unsigned int pfn1, pfn2;
+ unsigned int sblock = memblock_region_memory_base_pfn(reg);
+ unsigned int eblock = memblock_region_memory_end_pfn(reg);
+
+ /* we're beyond the membank */
+ if (sblock >= ebank)
+ break;
+
+ /* we're not yet at the membank */
+ if (eblock <= sbank)
+ continue;
+
+ /* take the intersection between bank and block */
+ pfn1 = max(sblock, sbank);
+ pfn2 = min(eblock, ebank);
+
+ page = pfn_to_page(pfn1);
+ end = pfn_to_page(pfn2 - 1) + 1;
+
+ do {
+ if (PageReserved(page))
+ reserved_pages++;
+ else if (!page_count(page))
+ free_pages++;
+ page++;
+ } while (page < end);
+ }
}
/*
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 59eeb5c20bd..aa677868334 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -950,27 +950,28 @@ phys_addr_t arm_lowmem_limit __initdata = 0;
void __init sanity_check_meminfo(void)
{
int i, j, highmem = 0;
+ phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1;
for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
struct membank *bank = &meminfo.bank[j];
- *bank = meminfo.bank[i];
+ phys_addr_t size_limit;
- if (bank->start > ULONG_MAX)
- highmem = 1;
+ *bank = meminfo.bank[i];
+ size_limit = bank->size;
-#ifdef CONFIG_HIGHMEM
- if (__va(bank->start) >= vmalloc_min ||
- __va(bank->start) < (void *)PAGE_OFFSET)
+ if (bank->start >= vmalloc_limit)
highmem = 1;
+ else
+ size_limit = vmalloc_limit - bank->start;
bank->highmem = highmem;
+#ifdef CONFIG_HIGHMEM
/*
* Split those memory banks which are partially overlapping
* the vmalloc area greatly simplifying things later.
*/
- if (!highmem && __va(bank->start) < vmalloc_min &&
- bank->size > vmalloc_min - __va(bank->start)) {
+ if (!highmem && bank->size > size_limit) {
if (meminfo.nr_banks >= NR_BANKS) {
printk(KERN_CRIT "NR_BANKS too low, "
"ignoring high memory\n");
@@ -979,16 +980,14 @@ void __init sanity_check_meminfo(void)
(meminfo.nr_banks - i) * sizeof(*bank));
meminfo.nr_banks++;
i++;
- bank[1].size -= vmalloc_min - __va(bank->start);
- bank[1].start = __pa(vmalloc_min - 1) + 1;
+ bank[1].size -= size_limit;
+ bank[1].start = vmalloc_limit;
bank[1].highmem = highmem = 1;
j++;
}
- bank->size = vmalloc_min - __va(bank->start);
+ bank->size = size_limit;
}
#else
- bank->highmem = highmem;
-
/*
* Highmem banks not allowed with !CONFIG_HIGHMEM.
*/
@@ -1001,31 +1000,16 @@ void __init sanity_check_meminfo(void)
}
/*
- * Check whether this memory bank would entirely overlap
- * the vmalloc area.
- */
- if (__va(bank->start) >= vmalloc_min ||
- __va(bank->start) < (void *)PAGE_OFFSET) {
- printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
- "(vmalloc region overlap).\n",
- (unsigned long long)bank->start,
- (unsigned long long)bank->start + bank->size - 1);
- continue;
- }
-
- /*
* Check whether this memory bank would partially overlap
* the vmalloc area.
*/
- if (__va(bank->start + bank->size - 1) >= vmalloc_min ||
- __va(bank->start + bank->size - 1) <= __va(bank->start)) {
- unsigned long newsize = vmalloc_min - __va(bank->start);
+ if (bank->size > size_limit) {
printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
"to -%.8llx (vmalloc region overlap).\n",
(unsigned long long)bank->start,
(unsigned long long)bank->start + bank->size - 1,
- (unsigned long long)bank->start + newsize - 1);
- bank->size = newsize;
+ (unsigned long long)bank->start + size_limit - 1);
+ bank->size = size_limit;
}
#endif
if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit)
diff --git a/arch/arm/mm/numa.c b/arch/arm/mm/numa.c
new file mode 100644
index 00000000000..5933e2caf2d
--- /dev/null
+++ b/arch/arm/mm/numa.c
@@ -0,0 +1,278 @@
+/*
+ * Discontiguous memory and NUMA support, based on the PowerPC implementation.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/nodemask.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/node.h>
+#include <linux/cpu.h>
+#include <linux/memblock.h>
+
+#include <asm/string.h>
+#include <asm/mmzone.h>
+#include <asm/setup.h>
+
+struct pglist_data *node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(node_data);
+
+static unsigned int numa_node_count = 1;
+
+cpumask_var_t *node_to_cpumask_map;
+EXPORT_SYMBOL(node_to_cpumask_map);
+
+void __init arm_numa_alloc_nodes(unsigned long max_low)
+{
+ int node;
+
+ arm_numa_alloc_cpumask(max_low);
+
+ for (node = 0; node < numa_node_count; node++) {
+ phys_addr_t pa = memblock_alloc_base(sizeof(pg_data_t),
+ L1_CACHE_BYTES, __pfn_to_phys(max_low));
+
+ NODE_DATA(node) = __va(pa);
+ memset(NODE_DATA(node), 0, sizeof(pg_data_t));
+ NODE_DATA(node)->bdata = &bootmem_node_data[node];
+ }
+}
+
+#ifdef CONFIG_NUMA
+
+static unsigned int numa_use_topology;
+
+static char *memcmdline __initdata;
+
+int numa_cpu_lookup_table[NR_CPUS];
+EXPORT_SYMBOL(numa_cpu_lookup_table);
+
+static unsigned long pfn_starts[MAX_NUMNODES];
+
+#ifdef CONFIG_DISCONTIGMEM
+int pfn_to_nid(unsigned long pfn)
+{
+ int node;
+
+ for (node = numa_node_count - 1; node >= 0; node--)
+ if (pfn >= pfn_starts[node])
+ return node;
+
+ panic("NUMA: Unable to locate nid for %lX\n", pfn);
+ return 0;
+}
+#endif
+
+void __init arm_numa_alloc_cpumask(unsigned long max_low)
+{
+ size_t size = sizeof(cpumask_var_t) * numa_node_count;
+ node_to_cpumask_map = __va(memblock_alloc_base(size,
+ L1_CACHE_BYTES, __pfn_to_phys(max_low)));
+ memset(node_to_cpumask_map, 0, size);
+}
+
+/*
+ * Add a CPU to a NUMA node.
+ * Default assignment policy is the cpu number modulo the number of nodes.
+ *
+ * We can also group CPUs via the topology_physical_package_id.
+ * (if the user adds "usetopology" to the command line).
+ * When we add CPU 0 (the boot CPU), it is always to node 0, as we don't have
+ * the topology information at that time.
+ * Subsequent CPUs get added based on the topology_physical_package_id.
+ * To stop CPU0 being added to the same node as CPUs on a different cluster,
+ * we subtract the topology_physical_package_id of node 0.
+ *
+ * This ensures that the TC2 has equivalent node configurations when booted
+ * off the A15s or the A7s.
+ */
+static void add_cpu_to_node(int cpu)
+{
+ unsigned int node;
+ unsigned int n0 = topology_physical_package_id(0);
+ unsigned int nc = topology_physical_package_id(cpu);
+
+ if (numa_use_topology)
+ node = cpu ? (numa_node_count + nc - n0) % numa_node_count : 0;
+ else
+ node = cpu % numa_node_count;
+
+ cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
+ numa_cpu_lookup_table[cpu] = node;
+ pr_info("NUMA: Adding CPU %d to node %d\n", cpu, node);
+}
+
+static int __cpuinit numa_add_cpu(struct notifier_block *self,
+ unsigned long action, void *cpu)
+{
+ if (action == CPU_ONLINE)
+ add_cpu_to_node((int)cpu);
+
+ return NOTIFY_OK;
+
+}
+
+static struct notifier_block __cpuinitdata numa_node_nb = {
+ .notifier_call = numa_add_cpu,
+ .priority = 1, /* Must run before sched domains notifier. */
+};
+
+/*
+ * Split the available memory between the NUMA nodes.
+ * We want all the pages mapped by a pmd to belong to the same node; as code,
+ * such as the THP splitting code, assumes pmds are backed by contiguous
+ * struct page *s. So we mask off the sizes with "rmask".
+ *
+ * By default, the memory is distributed roughly evenly between nodes.
+ *
+ * One can also specify requested node sizes on the command line, if
+ * "memcmdline" is not NULL, we try to parse it as a size.
+ *
+ * We traverse memory blocks rather than the pfn addressable range to allow for
+ * sparse memory configurations and memory holes.
+ */
+static void __init arm_numa_split_memblocks(void)
+{
+ const unsigned long rmask = ~((1UL << (PMD_SHIFT - PAGE_SHIFT)) - 1);
+ unsigned int node;
+ unsigned long pfnsrem = 0, pfnsblock, pfncurr, pfnend = 0;
+ struct memblock_region *reg;
+
+ for_each_memblock(memory, reg) {
+ pfnend = memblock_region_memory_end_pfn(reg);
+ pfnsrem += pfnend - memblock_region_memory_base_pfn(reg);
+ }
+
+ reg = memblock.memory.regions;
+ pfnsblock = memblock_region_memory_end_pfn(reg)
+ - memblock_region_memory_base_pfn(reg);
+
+ pfncurr = memblock_region_memory_base_pfn(reg);
+ pfn_starts[0] = pfncurr;
+
+ for (node = 0; node < numa_node_count - 1; node++) {
+ unsigned long pfnsnode = pfnsrem / (numa_node_count - node)
+ & rmask;
+
+ if (memcmdline) {
+ unsigned long nsize = __phys_to_pfn(
+ memparse(memcmdline, &memcmdline))
+ & rmask;
+ if (*memcmdline == ',')
+ ++memcmdline;
+
+ if ((nsize > 0) && (nsize < pfnsrem))
+ pfnsnode = nsize;
+ else
+ memcmdline = NULL;
+ }
+
+ while (pfnsnode > 0) {
+ unsigned long pfnsset = min(pfnsnode, pfnsblock);
+
+ pfncurr += pfnsset;
+
+ pfnsblock -= pfnsset;
+ pfnsrem -= pfnsset;
+ pfnsnode -= pfnsset;
+
+ if (pfnsblock == 0) {
+ reg++;
+ pfnsblock = memblock_region_memory_end_pfn(reg)
+ - memblock_region_memory_base_pfn(reg);
+ pfncurr = memblock_region_memory_base_pfn(reg);
+ }
+ }
+
+ pfn_starts[node + 1] = pfncurr;
+ }
+
+ for (node = 0; node < numa_node_count - 1; node++)
+ memblock_set_node(__pfn_to_phys(pfn_starts[node]),
+ __pfn_to_phys(pfn_starts[node + 1] - pfn_starts[node]),
+ node);
+
+ memblock_set_node(__pfn_to_phys(pfn_starts[node]),
+ __pfn_to_phys(pfnend - pfn_starts[node]), node);
+
+}
+
+void __init arm_setup_nodes(unsigned long min, unsigned long max_high)
+{
+ int node;
+
+ register_cpu_notifier(&numa_node_nb);
+ arm_numa_split_memblocks();
+
+
+ for (node = 0; node < numa_node_count; node++) {
+ alloc_bootmem_cpumask_var(&node_to_cpumask_map[node]);
+ node_set_online(node);
+ }
+
+ add_cpu_to_node(0);
+
+}
+
+static int __init early_numa(char *p)
+{
+ if (!p)
+ return 0;
+
+ p = strstr(p, "fake=");
+ if (p) {
+ int num_nodes = 0;
+ int optres;
+
+ p += strlen("fake=");
+ optres = get_option(&p, &num_nodes);
+ if ((optres == 0) || (optres == 3))
+ return -EINVAL;
+
+ if ((num_nodes > 0) && (num_nodes <= MAX_NUMNODES)) {
+ pr_info("NUMA: setting up fake NUMA with %d nodes.\n",
+ num_nodes);
+
+ numa_node_count = num_nodes;
+ } else {
+ pr_info("NUMA: can't set up %d nodes for NUMA (MAX_NUMNODES = %d)\n",
+ num_nodes, MAX_NUMNODES);
+ return -EINVAL;
+ }
+
+ /*
+ * If a comma was specified after the number of nodes then subsequent
+ * numbers should be regarded as memory sizes for each node for as
+ * many nodes as are supplied.
+ */
+ if (optres == 2)
+ memcmdline = p;
+
+ if (strstr(p, "usetopology")) {
+ numa_use_topology = 1;
+ pr_info("NUMA: using CPU topology to assign nodes.\n");
+ } else
+ pr_info("NUMA: NOT using CPU topology.\n");
+ }
+
+ return 0;
+}
+early_param("numa", early_numa);
+
+#endif /* CONFIG_NUMA */
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index cdadc2fff92..4b6c527fa25 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -39,6 +39,14 @@
#define TTB_FLAGS_SMP (TTB_IRGN_WBWA|TTB_S|TTB_RGN_OC_WBWA)
#define PMD_FLAGS_SMP (PMD_SECT_WBWA|PMD_SECT_S)
+#ifndef __ARMEB__
+# define rpgdl r0
+# define rpgdh r1
+#else
+# define rpgdl r1
+# define rpgdh r0
+#endif
+
/*
* cpu_v7_switch_mm(pgd_phys, tsk)
*
@@ -47,10 +55,11 @@
*/
ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_MMU
- ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
- and r3, r1, #0xff
- mov r3, r3, lsl #(48 - 32) @ ASID
- mcrr p15, 0, r0, r3, c2 @ set TTB 0
+ ldr r2, [r2, #MM_CONTEXT_ID] @ get mm->context.id
+ and r2, r2, #0xff
+ mov r2, r2, lsl #(48 - 32) @ ASID
+ orr rpgdh, rpgdh, r2 @ upper 32-bits of pgd phys
+ mcrr p15, 0, rpgdl, rpgdh, c2 @ set TTB 0
isb
#endif
mov pc, lr
@@ -107,6 +116,7 @@ ENDPROC(cpu_v7_set_pte_ext)
*/
.macro v7_ttb_setup, zero, ttbr0, ttbr1, tmp
ldr \tmp, =swapper_pg_dir @ swapper_pg_dir virtual address
+ mov \tmp, \tmp, lsr #ARCH_PGD_SHIFT
cmp \ttbr1, \tmp @ PHYS_OFFSET > PAGE_OFFSET? (branch below)
mrc p15, 0, \tmp, c2, c0, 2 @ TTB control register
orr \tmp, \tmp, #TTB_EAE
@@ -124,18 +134,17 @@ ENDPROC(cpu_v7_set_pte_ext)
* booting secondary CPUs would end up using TTBR1 for the identity
* mapping set up in TTBR0.
*/
- bhi 9001f @ PHYS_OFFSET > PAGE_OFFSET?
- orr \tmp, \tmp, #(((PAGE_OFFSET >> 30) - 1) << 16) @ TTBCR.T1SZ
-#if defined CONFIG_VMSPLIT_2G
- /* PAGE_OFFSET == 0x80000000, T1SZ == 1 */
- add \ttbr1, \ttbr1, #1 << 4 @ skip two L1 entries
-#elif defined CONFIG_VMSPLIT_3G
- /* PAGE_OFFSET == 0xc0000000, T1SZ == 2 */
- add \ttbr1, \ttbr1, #4096 * (1 + 3) @ only L2 used, skip pgd+3*pmd
-#endif
- /* CONFIG_VMSPLIT_1G does not need TTBR1 adjustment */
-9001: mcr p15, 0, \tmp, c2, c0, 2 @ TTB control register
- mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
+ orrls \tmp, \tmp, #TTBR1_SIZE @ TTBCR.T1SZ
+ mcr p15, 0, \tmp, c2, c0, 2 @ TTBCR
+ mov \tmp, \ttbr1, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits
+ mov \ttbr1, \ttbr1, lsl #ARCH_PGD_SHIFT @ lower bits
+ addls \ttbr1, \ttbr1, #TTBR1_OFFSET
+ mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
+ mov \tmp, \ttbr0, lsr #(32 - ARCH_PGD_SHIFT) @ upper bits
+ mov \ttbr0, \ttbr0, lsl #ARCH_PGD_SHIFT @ lower bits
+ mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0
+ mcrr p15, 1, \ttbr1, \zero, c2 @ load TTBR1
+ mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0
.endm
__CPUINIT
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index a9d52167e16..c67ff56c2e6 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -371,6 +371,11 @@ config S5P_DEV_G2D
help
Compile in platform device definitions for G2D device
+config S5P_DEV_G3D
+ bool
+ help
+ Compile in platform device definitions for G3D device
+
config S5P_DEV_I2C_HDMIPHY
bool
help
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 51afedda9ab..9e21d3f6bc5 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -282,6 +282,25 @@ struct platform_device s5p_device_g2d = {
};
#endif /* CONFIG_S5P_DEV_G2D */
+/* G3D */
+
+#ifdef CONFIG_S5P_DEV_G3D
+static struct resource s5p_g3d_resource[] = {
+ [0] = DEFINE_RES_MEM(S5P_PA_G3D, SZ_256K),
+};
+
+struct platform_device s5p_device_g3d = {
+ .name = "s5p-g3d",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_g3d_resource),
+ .resource = s5p_g3d_resource,
+ .dev = {
+ .dma_mask = &samsung_device_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+#endif /* CONFIG_S5P_DEV_G3D */
+
#ifdef CONFIG_S5P_DEV_JPEG
static struct resource s5p_jpeg_resource[] = {
[0] = DEFINE_RES_MEM(S5P_PA_JPEG, SZ_4K),
@@ -1113,7 +1132,7 @@ struct platform_device s5p_device_onenand = {
/* PMU */
-#ifdef CONFIG_PLAT_S5P
+#if defined(CONFIG_PLAT_S5P) && !defined(CONFIG_ARCH_EXYNOS)
static struct resource s5p_pmu_resource[] = {
DEFINE_RES_IRQ(IRQ_PMU)
};
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 87d501ff332..e4bbd7d0ccd 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -83,6 +83,7 @@ extern struct platform_device s5p_device_fimc3;
extern struct platform_device s5p_device_fimc_md;
extern struct platform_device s5p_device_jpeg;
extern struct platform_device s5p_device_g2d;
+extern struct platform_device s5p_device_g3d;
extern struct platform_device s5p_device_fimd0;
extern struct platform_device s5p_device_hdmi;
extern struct platform_device s5p_device_i2c_hdmiphy;
@@ -134,7 +135,6 @@ extern struct platform_device exynos4_device_spdif;
extern struct platform_device samsung_asoc_idma;
extern struct platform_device samsung_device_keypad;
-
/* s3c2440 specific devices */
#ifdef CONFIG_CPU_S3C2440
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index c2d7bdae589..b98be492ee0 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -40,6 +40,8 @@
#define S5P_VA_GIC_CPU S3C_ADDR(0x02810000)
#define S5P_VA_GIC_DIST S3C_ADDR(0x02820000)
+#define S5P_VA_AUDSS S3C_ADDR(0X02A00000)
+
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0)
#define VA_VIC1 VA_VIC(1)
diff --git a/arch/arm/plat-samsung/include/plat/usb-phy.h b/arch/arm/plat-samsung/include/plat/usb-phy.h
index 959bcdb03a2..72fb3122912 100644
--- a/arch/arm/plat-samsung/include/plat/usb-phy.h
+++ b/arch/arm/plat-samsung/include/plat/usb-phy.h
@@ -11,12 +11,8 @@
#ifndef __PLAT_SAMSUNG_USB_PHY_H
#define __PLAT_SAMSUNG_USB_PHY_H __FILE__
-enum s5p_usb_phy_type {
- S5P_USB_PHY_DEVICE,
- S5P_USB_PHY_HOST,
-};
-
extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
-
+extern void s5p_usb_phy_pmu_isolation(int on, int type);
+extern void s5p_usb_phy_cfg_sel(struct device *dev, int type);
#endif /* __PLAT_SAMSUNG_USB_PHY_H */
diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c
index 5ec104b5408..d7c679b7588 100644
--- a/arch/arm/plat-samsung/s5p-dev-mfc.c
+++ b/arch/arm/plat-samsung/s5p-dev-mfc.c
@@ -12,6 +12,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
#include <linux/memblock.h>
#include <linux/ioport.h>
#include <linux/of_fdt.h>
@@ -22,55 +23,17 @@
#include <plat/irqs.h>
#include <plat/mfc.h>
-struct s5p_mfc_reserved_mem {
- phys_addr_t base;
- unsigned long size;
- struct device *dev;
-};
-
-static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata;
-
void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize,
phys_addr_t lbase, unsigned int lsize)
{
- int i;
-
- s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev;
- s5p_mfc_mem[0].base = rbase;
- s5p_mfc_mem[0].size = rsize;
-
- s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev;
- s5p_mfc_mem[1].base = lbase;
- s5p_mfc_mem[1].size = lsize;
-
- for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
- struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
- if (memblock_remove(area->base, area->size)) {
- printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n",
- area->size, (unsigned long) area->base);
- area->base = 0;
- }
- }
-}
-
-static int __init s5p_mfc_memory_init(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) {
- struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i];
- if (!area->base)
- continue;
+ if (dma_declare_contiguous(&s5p_device_mfc_r.dev, rsize, rbase, 0))
+ printk(KERN_ERR "Failed to reserve memory for MFC device (%u bytes at 0x%08lx)\n",
+ rsize, (unsigned long) rbase);
- if (dma_declare_coherent_memory(area->dev, area->base,
- area->base, area->size,
- DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0)
- printk(KERN_ERR "Failed to declare coherent memory for MFC device (%ld bytes at 0x%08lx)\n",
- area->size, (unsigned long) area->base);
- }
- return 0;
+ if (dma_declare_contiguous(&s5p_device_mfc_l.dev, lsize, lbase, 0))
+ printk(KERN_ERR "Failed to reserve memory for MFC device (%u bytes at 0x%08lx)\n",
+ rsize, (unsigned long) rbase);
}
-device_initcall(s5p_mfc_memory_init);
#ifdef CONFIG_OF
int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname,