diff options
Diffstat (limited to 'arch/arm')
74 files changed, 490 insertions, 211 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 40f63f4e9e54..941dbb86a4d6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1090,6 +1090,20 @@ if !MMU source "arch/arm/Kconfig-nommu" endif +config PJ4B_ERRATA_4742 + bool "PJ4B Errata 4742: IDLE Wake Up Commands can Cause the CPU Core to Cease Operation" + depends on CPU_PJ4B && MACH_ARMADA_370 + default y + help + When coming out of either a Wait for Interrupt (WFI) or a Wait for + Event (WFE) IDLE states, a specific timing sensitivity exists between + the retiring WFI/WFE instructions and the newly issued subsequent + instructions. This sensitivity can result in a CPU hang scenario. + Workaround: + The software must insert either a Data Synchronization Barrier (DSB) + or Data Memory Barrier (DMB) command immediately after the WFI/WFE + instruction + config ARM_ERRATA_326103 bool "ARM errata: FSR write bit incorrect on a SWP to read-only memory" depends on CPU_V6 @@ -1192,6 +1206,16 @@ config PL310_ERRATA_588369 is not correctly implemented in PL310 as clean lines are not invalidated as a result of these operations. +config ARM_ERRATA_643719 + bool "ARM errata: LoUIS bit field in CLIDR register is incorrect" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 643719 Cortex-A9 (prior to + r1p0) erratum. On affected cores the LoUIS bit field of the CLIDR + register returns zero when it should return one. The workaround + corrects this value, ensuring cache maintenance operations which use + it behave as intended and avoiding data corruption. + config ARM_ERRATA_720789 bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID" depends on CPU_V7 @@ -1531,7 +1555,7 @@ config NR_CPUS config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" - depends on SMP && HOTPLUG + depends on SMP help Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. @@ -2009,7 +2033,7 @@ config XIP_PHYS_ADDR config KEXEC bool "Kexec system call (EXPERIMENTAL)" - depends on (!SMP || HOTPLUG_CPU) + depends on (!SMP || PM_SLEEP_SMP) help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1ba358ba16b8..7ea15176d109 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -168,7 +168,7 @@ machine-$(CONFIG_ARCH_OMAP1) += omap1 machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2 machine-$(CONFIG_ARCH_ORION5X) += orion5x machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell -machine-$(CONFIG_ARCH_PRIMA2) += prima2 +machine-$(CONFIG_ARCH_SIRF) += prima2 machine-$(CONFIG_ARCH_PXA) += pxa machine-$(CONFIG_ARCH_REALVIEW) += realview machine-$(CONFIG_ARCH_RPC) += rpc diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 79e9bdbfc491..120b83bfde20 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -116,7 +116,8 @@ targets := vmlinux vmlinux.lds \ # Make sure files are removed during clean extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern \ - lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs) + lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs) \ + hyp-stub.S ifeq ($(CONFIG_FUNCTION_TRACER),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index 550eb772c30e..52a1f5efc086 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -80,7 +80,7 @@ sata@a0000 { compatible = "marvell,orion-sata"; - reg = <0xa0000 0x2400>; + reg = <0xa0000 0x5000>; interrupts = <55>; clocks = <&gateclk 15>, <&gateclk 30>; clock-names = "0", "1"; @@ -96,7 +96,7 @@ ethernet@70000 { compatible = "marvell,armada-370-neta"; - reg = <0x70000 0x2500>; + reg = <0x70000 0x4000>; interrupts = <8>; clocks = <&gateclk 4>; status = "disabled"; @@ -104,7 +104,7 @@ ethernet@74000 { compatible = "marvell,armada-370-neta"; - reg = <0x74000 0x2500>; + reg = <0x74000 0x4000>; interrupts = <10>; clocks = <&gateclk 3>; status = "disabled"; diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index f4029f015aff..2d9335da210c 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi @@ -92,7 +92,7 @@ ethernet@34000 { compatible = "marvell,armada-370-neta"; - reg = <0x34000 0x2500>; + reg = <0x34000 0x4000>; interrupts = <14>; clocks = <&gateclk 1>; status = "disabled"; diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi index 6ab56bd35de9..488ca5eb9a55 100644 --- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi @@ -107,7 +107,7 @@ ethernet@34000 { compatible = "marvell,armada-370-neta"; - reg = <0x34000 0x2500>; + reg = <0x34000 0x4000>; interrupts = <14>; clocks = <&gateclk 1>; status = "disabled"; diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index 5b902f9a3af2..1ee8540b0eba 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -88,7 +88,7 @@ ethernet@30000 { compatible = "marvell,armada-370-neta"; - reg = <0x30000 0x2500>; + reg = <0x30000 0x4000>; interrupts = <12>; clocks = <&gateclk 2>; status = "disabled"; diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi index d1650fb34c0a..ded558bb0f3b 100644 --- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi @@ -763,7 +763,7 @@ }; }; - pinctrl@03680000 { + pinctrl@03860000 { gpz: gpz { gpio-controller; #gpio-cells = <2>; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 0673524238a6..fc9fb3d526e2 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -161,9 +161,9 @@ interrupts = <0 50 0>; }; - pinctrl_3: pinctrl@03680000 { + pinctrl_3: pinctrl@03860000 { compatible = "samsung,exynos5250-pinctrl"; - reg = <0x0368000 0x1000>; + reg = <0x03860000 0x1000>; interrupts = <0 47 0>; }; diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi index a573b94b7c93..c12af78e479c 100644 --- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi +++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi @@ -449,7 +449,11 @@ usb@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ + }; + + usb-phy@c5004000 { + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ }; sdhci@c8000600 { diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts index e7d5de4e00b9..ec5293758753 100644 --- a/arch/arm/boot/dts/tegra20-harmony.dts +++ b/arch/arm/boot/dts/tegra20-harmony.dts @@ -428,17 +428,26 @@ status = "okay"; }; + usb-phy@c5000000 { + status = "okay"; + }; + usb@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ + }; + + usb-phy@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ }; usb@c5008000 { status = "okay"; }; - usb-phy@c5004400 { - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + usb-phy@c5008000 { + status = "okay"; }; sdhci@c8000200 { diff --git a/arch/arm/boot/dts/tegra20-iris-512.dts b/arch/arm/boot/dts/tegra20-iris-512.dts index 52f1103907d7..9f64f7086881 100644 --- a/arch/arm/boot/dts/tegra20-iris-512.dts +++ b/arch/arm/boot/dts/tegra20-iris-512.dts @@ -38,13 +38,20 @@ usb@c5000000 { status = "okay"; - dr_mode = "otg"; + }; + + usb-phy@c5000000 { + status = "okay"; }; usb@c5008000 { status = "okay"; }; + usb-phy@c5008000 { + status = "okay"; + }; + serial@70006000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index e3e0c9977df4..1c17ffaff1ad 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -427,17 +427,26 @@ status = "okay"; }; + usb-phy@c5000000 { + status = "okay"; + }; + usb@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ + }; + + usb-phy@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ }; usb@c5008000 { status = "okay"; }; - usb-phy@c5004400 { - nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + usb-phy@c5008000 { + status = "okay"; }; sdhci@c8000000 { diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index cee4c34010fe..009dafecf88b 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -569,17 +569,28 @@ dr_mode = "otg"; }; + usb-phy@c5000000 { + status = "okay"; + vbus-supply = <&vbus_reg>; + dr_mode = "otg"; + }; + usb@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ + }; + + usb-phy@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ }; usb@c5008000 { status = "okay"; }; - usb-phy@c5004400 { - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + usb-phy@c5008000 { + status = "okay"; }; sdhci@c8000000 { @@ -807,6 +818,15 @@ gpio = <&pmic 1 0>; enable-active-high; }; + + vbus_reg: regulator@3 { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "vdd_vbus_wup1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio 24 0>; /* PD0 */ + }; }; sound { diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi index 50b3ec16b93a..fc2f7d6e70b2 100644 --- a/arch/arm/boot/dts/tegra20-tamonten.dtsi +++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi @@ -470,6 +470,10 @@ status = "okay"; }; + usb-phy@c5008000 { + status = "okay"; + }; + sdhci@c8000600 { cd-gpios = <&gpio 58 1>; /* gpio PH2 */ wp-gpios = <&gpio 59 0>; /* gpio PH3 */ diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index 9cc78a15d739..0e65c00ec732 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -314,17 +314,27 @@ nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */ }; + usb-phy@c5000000 { + status = "okay"; + vbus-supply = <&vbus_reg>; + }; + usb@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ + }; + + usb-phy@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ }; usb@c5008000 { status = "okay"; }; - usb-phy@c5004400 { - nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + usb-phy@c5008000 { + status = "okay"; }; sdhci@c8000000 { @@ -390,6 +400,15 @@ regulator-max-microvolt = <1800000>; regulator-always-on; }; + + vbus_reg: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "usb1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio 170 0>; /* PV2 */ + }; }; sound { diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts index dd38f1f03834..e00f89e645f9 100644 --- a/arch/arm/boot/dts/tegra20-ventana.dts +++ b/arch/arm/boot/dts/tegra20-ventana.dts @@ -505,17 +505,26 @@ status = "okay"; }; + usb-phy@c5000000 { + status = "okay"; + }; + usb@c5004000 { status = "okay"; - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ + }; + + usb-phy@c5004000 { + status = "okay"; + nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ }; usb@c5008000 { status = "okay"; }; - usb-phy@c5004400 { - nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + usb-phy@c5008000 { + status = "okay"; }; sdhci@c8000000 { diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts index d2567f83aaff..3c24c9b92b44 100644 --- a/arch/arm/boot/dts/tegra20-whistler.dts +++ b/arch/arm/boot/dts/tegra20-whistler.dts @@ -511,11 +511,21 @@ nvidia,vbus-gpio = <&tca6416 0 0>; /* GPIO_PMU0 */ }; + usb-phy@c5000000 { + status = "okay"; + vbus-supply = <&vbus1_reg>; + }; + usb@c5008000 { status = "okay"; nvidia,vbus-gpio = <&tca6416 1 0>; /* GPIO_PMU1 */ }; + usb-phy@c5008000 { + status = "okay"; + vbus-supply = <&vbus3_reg>; + }; + sdhci@c8000400 { status = "okay"; cd-gpios = <&gpio 69 1>; /* gpio PI5 */ @@ -568,6 +578,24 @@ regulator-max-microvolt = <5000000>; regulator-always-on; }; + + vbus1_reg: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "vbus1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&tca6416 0 0>; /* GPIO_PMU0 */ + }; + + vbus3_reg: regulator@3 { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "vbus3"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&tca6416 1 0>; /* GPIO_PMU1 */ + }; }; sound { diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 56a91106041b..96d6d8a3aa72 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -455,13 +455,24 @@ status = "disabled"; }; - phy1: usb-phy@c5000400 { + phy1: usb-phy@c5000000 { compatible = "nvidia,tegra20-usb-phy"; - reg = <0xc5000400 0x3c00>; + reg = <0xc5000000 0x4000 0xc5000000 0x4000>; phy_type = "utmi"; + clocks = <&tegra_car 22>, + <&tegra_car 127>, + <&tegra_car 106>, + <&tegra_car 22>; + clock-names = "reg", "pll_u", "timer", "utmi-pads"; nvidia,has-legacy-mode; - clocks = <&tegra_car 22>, <&tegra_car 127>; - clock-names = "phy", "pll_u"; + hssync_start_delay = <9>; + idle_wait_delay = <17>; + elastic_limit = <16>; + term_range_adj = <6>; + xcvr_setup = <9>; + xcvr_lsfslew = <1>; + xcvr_lsrslew = <1>; + status = "disabled"; }; usb@c5004000 { @@ -474,12 +485,15 @@ status = "disabled"; }; - phy2: usb-phy@c5004400 { + phy2: usb-phy@c5004000 { compatible = "nvidia,tegra20-usb-phy"; - reg = <0xc5004400 0x3c00>; + reg = <0xc5004000 0x4000>; phy_type = "ulpi"; - clocks = <&tegra_car 93>, <&tegra_car 127>; - clock-names = "phy", "pll_u"; + clocks = <&tegra_car 58>, + <&tegra_car 127>, + <&tegra_car 93>; + clock-names = "reg", "pll_u", "ulpi-link"; + status = "disabled"; }; usb@c5008000 { @@ -492,12 +506,23 @@ status = "disabled"; }; - phy3: usb-phy@c5008400 { + phy3: usb-phy@c5008000 { compatible = "nvidia,tegra20-usb-phy"; - reg = <0xc5008400 0x3c00>; + reg = <0xc5008000 0x4000 0xc5000000 0x4000>; phy_type = "utmi"; - clocks = <&tegra_car 22>, <&tegra_car 127>; - clock-names = "phy", "pll_u"; + clocks = <&tegra_car 59>, + <&tegra_car 127>, + <&tegra_car 106>, + <&tegra_car 22>; + clock-names = "reg", "pll_u", "timer", "utmi-pads"; + hssync_start_delay = <9>; + idle_wait_delay = <17>; + elastic_limit = <16>; + term_range_adj = <6>; + xcvr_setup = <9>; + xcvr_lsfslew = <2>; + xcvr_lsrslew = <2>; + status = "disabled"; }; sdhci@c8000000 { diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index bff71388e72a..17d0ae8672fa 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -320,9 +320,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma, } #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE -static inline void flush_kernel_dcache_page(struct page *page) -{ -} +extern void flush_kernel_dcache_page(struct page *); #define flush_dcache_mmap_lock(mapping) \ spin_lock_irq(&(mapping)->tree_lock) diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index 7652712d1d14..dba62cb1ad08 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -32,6 +32,8 @@ #define MPIDR_HWID_BITMASK 0xFFFFFF +#define MPIDR_INVALID (~MPIDR_HWID_BITMASK) + #define MPIDR_LEVEL_BITS 8 #define MPIDR_LEVEL_MASK ((1 << MPIDR_LEVEL_BITS) - 1) diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h index ac1dd54724b6..8017e94acc5e 100644 --- a/arch/arm/include/asm/glue-proc.h +++ b/arch/arm/include/asm/glue-proc.h @@ -230,6 +230,15 @@ # endif #endif +#ifdef CONFIG_CPU_PJ4B +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_pj4b +# endif +#endif + #ifndef MULTI_CPU #define cpu_proc_init __glue(CPU_NAME,_proc_init) #define cpu_proc_fin __glue(CPU_NAME,_proc_fin) diff --git a/arch/arm/include/asm/pgtable-nommu.h b/arch/arm/include/asm/pgtable-nommu.h index 7ec60d6075bf..0642228ff785 100644 --- a/arch/arm/include/asm/pgtable-nommu.h +++ b/arch/arm/include/asm/pgtable-nommu.h @@ -79,8 +79,6 @@ extern unsigned int kobjsize(const void *objp); * No page table caches to initialise. */ #define pgtable_cache_init() do { } while (0) -#define io_remap_pfn_range remap_pfn_range - /* * All 32bit addresses are effectively valid for vmalloc... diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 9bcd262a9008..229e0dde9c71 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -318,13 +318,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define HAVE_ARCH_UNMAPPED_AREA #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN -/* - * remap a physical page `pfn' of size `size' with page protection `prot' - * into virtual address `from' - */ -#define io_remap_pfn_range(vma,from,pfn,size,prot) \ - remap_pfn_range(vma, from, pfn, size, prot) - #define pgtable_cache_init() do { } while (0) #endif /* !__ASSEMBLY__ */ diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h index aaa61b6f50ff..e78983202737 100644 --- a/arch/arm/include/asm/smp_plat.h +++ b/arch/arm/include/asm/smp_plat.h @@ -49,7 +49,7 @@ static inline int cache_ops_need_broadcast(void) /* * Logical CPU mapping. */ -extern int __cpu_logical_map[]; +extern u32 __cpu_logical_map[]; #define cpu_logical_map(cpu) __cpu_logical_map[cpu] /* * Retrieve logical cpu index corresponding to a given MPIDR[23:0] diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 5af04f6daa33..5859c8bc727c 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -82,7 +82,7 @@ void __init arm_dt_init_cpu_maps(void) u32 i, j, cpuidx = 1; u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0; - u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS-1] = UINT_MAX }; + u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS-1] = MPIDR_INVALID }; bool bootcpu_valid = false; cpus = of_find_node_by_path("/cpus"); @@ -92,6 +92,9 @@ void __init arm_dt_init_cpu_maps(void) for_each_child_of_node(cpus, cpu) { u32 hwid; + if (of_node_cmp(cpu->type, "cpu")) + continue; + pr_debug(" * %s...\n", cpu->full_name); /* * A device tree containing CPU nodes with missing "reg" @@ -149,9 +152,10 @@ void __init arm_dt_init_cpu_maps(void) tmp_map[i] = hwid; } - if (WARN(!bootcpu_valid, "DT missing boot CPU MPIDR[23:0], " - "fall back to default cpu_logical_map\n")) + if (!bootcpu_valid) { + pr_warn("DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map\n"); return; + } /* * Since the boot CPU node contains proper data, and all nodes have diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 8ef8c9337809..4fb074c446bf 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -134,6 +134,10 @@ void machine_kexec(struct kimage *image) unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; + if (num_online_cpus() > 1) { + pr_err("kexec: error: multiple CPUs still online\n"); + return; + } page_list = image->head & PAGE_MASK; diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 1e9be5d25e56..85c3fb6c93c2 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -288,24 +288,16 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, if (strcmp(".ARM.exidx.init.text", secname) == 0) maps[ARM_SEC_INIT].unw_sec = s; - else if (strcmp(".ARM.exidx.devinit.text", secname) == 0) - maps[ARM_SEC_DEVINIT].unw_sec = s; else if (strcmp(".ARM.exidx", secname) == 0) maps[ARM_SEC_CORE].unw_sec = s; else if (strcmp(".ARM.exidx.exit.text", secname) == 0) maps[ARM_SEC_EXIT].unw_sec = s; - else if (strcmp(".ARM.exidx.devexit.text", secname) == 0) - maps[ARM_SEC_DEVEXIT].unw_sec = s; else if (strcmp(".init.text", secname) == 0) maps[ARM_SEC_INIT].txt_sec = s; - else if (strcmp(".devinit.text", secname) == 0) - maps[ARM_SEC_DEVINIT].txt_sec = s; else if (strcmp(".text", secname) == 0) maps[ARM_SEC_CORE].txt_sec = s; else if (strcmp(".exit.text", secname) == 0) maps[ARM_SEC_EXIT].txt_sec = s; - else if (strcmp(".devexit.text", secname) == 0) - maps[ARM_SEC_DEVEXIT].txt_sec = s; } for (i = 0; i < ARM_SEC_MAX; i++) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 282de4826abb..6e8931ccf13e 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -184,30 +184,61 @@ int __init reboot_setup(char *str) __setup("reboot=", reboot_setup); +/* + * Called by kexec, immediately prior to machine_kexec(). + * + * This must completely disable all secondary CPUs; simply causing those CPUs + * to execute e.g. a RAM-based pin loop is not sufficient. This allows the + * kexec'd kernel to use any and all RAM as it sees fit, without having to + * avoid any code or data used by any SW CPU pin loop. The CPU hotplug + * functionality embodied in disable_nonboot_cpus() to achieve this. + */ void machine_shutdown(void) { -#ifdef CONFIG_SMP - smp_send_stop(); -#endif + disable_nonboot_cpus(); } +/* + * Halting simply requires that the secondary CPUs stop performing any + * activity (executing tasks, handling interrupts). smp_send_stop() + * achieves this. + */ void machine_halt(void) { - machine_shutdown(); + smp_send_stop(); + local_irq_disable(); while (1); } +/* + * Power-off simply requires that the secondary CPUs stop performing any + * activity (executing tasks, handling interrupts). smp_send_stop() + * achieves this. When the system power is turned off, it will take all CPUs + * with it. + */ void machine_power_off(void) { - machine_shutdown(); + smp_send_stop(); + if (pm_power_off) pm_power_off(); } +/* + * Restart requires that the secondary CPUs stop performing any activity + * while the primary CPU resets the system. Systems with a single CPU can + * use soft_restart() as their machine descriptor's .restart hook, since that + * will cause the only available CPU to reset. Systems with multiple CPUs must + * provide a HW restart implementation, to ensure that all CPUs reset at once. + * This is required so that any code running after reset on the primary CPU + * doesn't have to co-ordinate with other CPUs to ensure they aren't still + * executing pre-reset code, and using RAM that the primary CPU's code wishes + * to use. Implementing such co-ordination would be essentially impossible. + */ void machine_restart(char *cmd) { - machine_shutdown(); + smp_send_stop(); arm_pm_restart(reboot_mode, cmd); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 1522c7ae31b0..b4b1d397592b 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -444,7 +444,7 @@ void notrace cpu_init(void) : "r14"); } -int __cpu_logical_map[NR_CPUS]; +u32 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = MPIDR_INVALID }; void __init smp_setup_processor_id(void) { diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 550d63cef68e..5919eb451bb9 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -651,17 +651,6 @@ void smp_send_reschedule(int cpu) smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); } -#ifdef CONFIG_HOTPLUG_CPU -static void smp_kill_cpus(cpumask_t *mask) -{ - unsigned int cpu; - for_each_cpu(cpu, mask) - platform_cpu_kill(cpu); -} -#else -static void smp_kill_cpus(cpumask_t *mask) { } -#endif - void smp_send_stop(void) { unsigned long timeout; @@ -679,8 +668,6 @@ void smp_send_stop(void) if (num_online_cpus() > 1) pr_warning("SMP: failed to stop secondary CPUs\n"); - - smp_kill_cpus(&mask); } /* diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index a871b8e00fca..fa25e4e425f6 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -70,10 +70,6 @@ SECTIONS ARM_EXIT_DISCARD(EXIT_TEXT) ARM_EXIT_DISCARD(EXIT_DATA) EXIT_CALL -#ifndef CONFIG_HOTPLUG - *(.ARM.exidx.devexit.text) - *(.ARM.extab.devexit.text) -#endif #ifndef CONFIG_MMU *(.fixup) *(__ex_table) diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 02802386b894..699b71e7f7ec 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -163,6 +163,7 @@ config MACH_SAMA5_DT bool "Atmel SAMA5 Evaluation Kits with device-tree support" depends on SOC_SAMA5 select USE_OF + select PHYLIB if NETDEVICES help Select this if you want to experiment device-tree with an Atmel Evaluation Kit. diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index d193a409bc45..9eb574397ee1 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -332,10 +332,6 @@ static void __init at91rm9200_initialize(void) { arm_pm_idle = at91rm9200_idle; arm_pm_restart = at91rm9200_restart; - at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1) - | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3) - | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5) - | (1 << AT91RM9200_ID_IRQ6); /* Initialize GPIO subsystem */ at91_gpio_init(at91rm9200_gpio, @@ -388,6 +384,10 @@ static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = { AT91_SOC_START(at91rm9200) .map_io = at91rm9200_map_io, .default_irq_priority = at91rm9200_default_irq_priority, + .extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1) + | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3) + | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5) + | (1 << AT91RM9200_ID_IRQ6), .ioremap_registers = at91rm9200_ioremap_registers, .register_clocks = at91rm9200_register_clocks, .init = at91rm9200_initialize, diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index a8ce24538da6..5de6074b4f4f 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -348,8 +348,6 @@ static void __init at91sam9260_initialize(void) { arm_pm_idle = at91sam9_idle; arm_pm_restart = at91sam9_alt_restart; - at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) - | (1 << AT91SAM9260_ID_IRQ2); /* Register GPIO subsystem */ at91_gpio_init(at91sam9260_gpio, 3); @@ -400,6 +398,8 @@ static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = { AT91_SOC_START(at91sam9260) .map_io = at91sam9260_map_io, .default_irq_priority = at91sam9260_default_irq_priority, + .extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) + | (1 << AT91SAM9260_ID_IRQ2), .ioremap_registers = at91sam9260_ioremap_registers, .register_clocks = at91sam9260_register_clocks, .init = at91sam9260_initialize, diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 25efb5ac30f1..0e0793241ab7 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -290,8 +290,6 @@ static void __init at91sam9261_initialize(void) { arm_pm_idle = at91sam9_idle; arm_pm_restart = at91sam9_alt_restart; - at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1) - | (1 << AT91SAM9261_ID_IRQ2); /* Register GPIO subsystem */ at91_gpio_init(at91sam9261_gpio, 3); @@ -342,6 +340,8 @@ static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = { AT91_SOC_START(at91sam9261) .map_io = at91sam9261_map_io, .default_irq_priority = at91sam9261_default_irq_priority, + .extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1) + | (1 << AT91SAM9261_ID_IRQ2), .ioremap_registers = at91sam9261_ioremap_registers, .register_clocks = at91sam9261_register_clocks, .init = at91sam9261_initialize, diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index f44ffd2105a7..6ce7d1850893 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -327,7 +327,6 @@ static void __init at91sam9263_initialize(void) { arm_pm_idle = at91sam9_idle; arm_pm_restart = at91sam9_alt_restart; - at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1); /* Register GPIO subsystem */ at91_gpio_init(at91sam9263_gpio, 5); @@ -378,6 +377,7 @@ static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = { AT91_SOC_START(at91sam9263) .map_io = at91sam9263_map_io, .default_irq_priority = at91sam9263_default_irq_priority, + .extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1), .ioremap_registers = at91sam9263_ioremap_registers, .register_clocks = at91sam9263_register_clocks, .init = at91sam9263_initialize, diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 8b7fce067652..fda502691686 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -374,7 +374,6 @@ static void __init at91sam9g45_initialize(void) { arm_pm_idle = at91sam9_idle; arm_pm_restart = at91sam9g45_restart; - at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0); /* Register GPIO subsystem */ at91_gpio_init(at91sam9g45_gpio, 5); @@ -425,6 +424,7 @@ static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = { AT91_SOC_START(at91sam9g45) .map_io = at91sam9g45_map_io, .default_irq_priority = at91sam9g45_default_irq_priority, + .extern_irq = (1 << AT91SAM9G45_ID_IRQ0), .ioremap_registers = at91sam9g45_ioremap_registers, .register_clocks = at91sam9g45_register_clocks, .init = at91sam9g45_initialize, diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index f77fae5591bc..d4ec0d9a9872 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c @@ -293,7 +293,6 @@ static void __init at91sam9rl_initialize(void) { arm_pm_idle = at91sam9_idle; arm_pm_restart = at91sam9_alt_restart; - at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0); /* Register GPIO subsystem */ at91_gpio_init(at91sam9rl_gpio, 4); @@ -344,6 +343,7 @@ static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = { AT91_SOC_START(at91sam9rl) .map_io = at91sam9rl_map_io, .default_irq_priority = at91sam9rl_default_irq_priority, + .extern_irq = (1 << AT91SAM9RL_ID_IRQ0), .ioremap_registers = at91sam9rl_ioremap_registers, .register_clocks = at91sam9rl_register_clocks, .init = at91sam9rl_initialize, diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c index 19ca79396905..bad94b84a46f 100644 --- a/arch/arm/mach-at91/at91x40.c +++ b/arch/arm/mach-at91/at91x40.c @@ -55,8 +55,6 @@ static void at91x40_idle(void) void __init at91x40_initialize(unsigned long main_clock) { arm_pm_idle = at91x40_idle; - at91_extern_irq = (1 << AT91X40_ID_IRQ0) | (1 << AT91X40_ID_IRQ1) - | (1 << AT91X40_ID_IRQ2); } /* @@ -86,9 +84,10 @@ static unsigned int at91x40_default_irq_priority[NR_AIC_IRQS] __initdata = { void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS]) { + u32 extern_irq = (1 << AT91X40_ID_IRQ0) | (1 << AT91X40_ID_IRQ1) + | (1 << AT91X40_ID_IRQ2); if (!priority) priority = at91x40_default_irq_priority; - at91_aic_init(priority, at91_extern_irq); + at91_aic_init(priority, extern_irq); } - diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c index 705305e62bbc..ad95f6a23a28 100644 --- a/arch/arm/mach-at91/board-dt-sama5.c +++ b/arch/arm/mach-at91/board-dt-sama5.c @@ -62,7 +62,8 @@ static int ksz9021rn_phy_fixup(struct phy_device *phy) static void __init sama5_dt_device_init(void) { - if (of_machine_is_compatible("atmel,sama5d3xcm")) + if (of_machine_is_compatible("atmel,sama5d3xcm") && + IS_ENABLED(CONFIG_PHYLIB)) phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK, ksz9021rn_phy_fixup); diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index da841885d01c..6b2630a92f71 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -75,7 +75,7 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ - || cpu_is_at91sam9n12())) + || cpu_is_sama5d3())) #define cpu_has_upll() (cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ @@ -489,7 +489,7 @@ static int at91_clk_show(struct seq_file *s, void *unused) seq_printf(s, "UCKR = %8x\n", uckr); } seq_printf(s, "MCKR = %8x\n", at91_pmc_read(AT91_PMC_MCKR)); - if (cpu_has_upll()) + if (cpu_has_upll() || cpu_is_at91sam9n12()) seq_printf(s, "USB = %8x\n", at91_pmc_read(AT91_PMC_USB)); seq_printf(s, "SR = %8x\n", sr); @@ -614,6 +614,8 @@ static u32 __init at91_usb_rate(struct clk *pll, u32 freq, u32 reg) { if (pll == &pllb && (reg & AT91_PMC_USB96M)) return freq / 2; + else if (pll == &utmi_clk || cpu_is_at91sam9n12()) + return freq / (1 + ((reg & AT91_PMC_OHCIUSBDIV) >> 8)); else return freq; } @@ -683,6 +685,8 @@ static struct clk *const standard_pmc_clocks[] __initconst = { /* PLLB generated USB full speed clock init */ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock) { + unsigned int reg; + /* * USB clock init: choose 48 MHz PLLB value, * disable 48MHz clock during usb peripheral suspend. @@ -691,22 +695,35 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock) */ uhpck.parent = &pllb; - at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; + reg = at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2); pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); if (cpu_is_at91rm9200()) { + reg = at91_pllb_usb_init |= AT91_PMC_USB96M; uhpck.pmc_mask = AT91RM9200_PMC_UHP; udpck.pmc_mask = AT91RM9200_PMC_UDP; at91_pmc_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20() || cpu_is_at91sam9g10()) { + reg = at91_pllb_usb_init |= AT91_PMC_USB96M; + uhpck.pmc_mask = AT91SAM926x_PMC_UHP; + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + } else if (cpu_is_at91sam9n12()) { + /* Divider for USB clock is in USB clock register for 9n12 */ + reg = AT91_PMC_USBS_PLLB; + + /* For PLLB output 96M, set usb divider 2 (USBDIV + 1) */ + reg |= AT91_PMC_OHCIUSBDIV_2; + at91_pmc_write(AT91_PMC_USB, reg); + + /* Still setup masks */ uhpck.pmc_mask = AT91SAM926x_PMC_UHP; udpck.pmc_mask = AT91SAM926x_PMC_UDP; } at91_pmc_write(AT91_CKGR_PLLBR, 0); - udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); - uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); + udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, reg); + uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, reg); } /* UPLL generated USB full speed clock init */ @@ -725,8 +742,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock) /* Now set uhpck values */ uhpck.parent = &utmi_clk; uhpck.pmc_mask = AT91SAM926x_PMC_UHP; - uhpck.rate_hz = utmi_clk.rate_hz; - uhpck.rate_hz /= 1 + ((at91_pmc_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8); + uhpck.rate_hz = at91_usb_rate(&utmi_clk, utmi_clk.rate_hz, usbr); } static int __init at91_pmc_init(unsigned long main_clock) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 69f9e3bbf4e5..4ec6a6d9b9be 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -51,7 +51,7 @@ static struct cpuidle_driver at91_idle_driver = { .states[1] = { .enter = at91_enter_idle, .exit_latency = 10, - .target_residency = 100000, + .target_residency = 10000, .flags = CPUIDLE_FLAG_TIME_VALID, .name = "RAM_SR", .desc = "WFI and DDR Self Refresh", diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 78ab06548658..f6de36aefe85 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -85,4 +85,4 @@ extern void __init at91_gpio_irq_setup(void); extern int __init at91_gpio_of_irq_setup(struct device_node *node, struct device_node *parent); -extern int at91_extern_irq; +extern u32 at91_get_extern_irq(void); diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h index 2bd7f51b0b82..c604cc69acb5 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc.h @@ -130,7 +130,10 @@ extern void __iomem *at91_pmc_base; #define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */ #define AT91_PMC_USBS_PLLA (0 << 0) #define AT91_PMC_USBS_UPLL (1 << 0) +#define AT91_PMC_USBS_PLLB (1 << 0) /* [AT91SAMN12 only] */ #define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */ +#define AT91_PMC_OHCIUSBDIV_1 (0x0 << 8) +#define AT91_PMC_OHCIUSBDIV_2 (0x1 << 8) #define AT91_PMC_SMD 0x3c /* Soft Modem Clock Register [some SAM9 only] */ #define AT91_PMC_SMDS (0x1 << 0) /* SMD input clock selection */ diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c index e0ca59171022..3d192c5aee66 100644 --- a/arch/arm/mach-at91/irq.c +++ b/arch/arm/mach-at91/irq.c @@ -232,7 +232,14 @@ static void __maybe_unused at91_aic5_eoi(struct irq_data *d) at91_aic_write(AT91_AIC5_EOICR, 0); } -unsigned long *at91_extern_irq; +static unsigned long *at91_extern_irq; + +u32 at91_get_extern_irq(void) +{ + if (!at91_extern_irq) + return 0; + return *at91_extern_irq; +} #define is_extern_irq(hwirq) test_bit(hwirq, at91_extern_irq) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 530db304ec5e..15afb5d9271f 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -212,7 +212,7 @@ static int at91_pm_enter(suspend_state_t state) (at91_pmc_read(AT91_PMC_PCSR) | (1 << AT91_ID_FIQ) | (1 << AT91_ID_SYS) - | (at91_extern_irq)) + | (at91_get_extern_irq())) & at91_aic_read(AT91_AIC_IMR), state); diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index e2f4bdd146d6..b17fbcf4d9e8 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -48,7 +48,7 @@ void __init at91_init_irq_default(void) void __init at91_init_interrupts(unsigned int *priority) { /* Initialize the AIC interrupt controller */ - at91_aic_init(priority, at91_extern_irq); + at91_aic_init(priority, at91_boot_soc.extern_irq); /* Enable GPIO interrupts */ at91_gpio_irq_setup(); @@ -80,7 +80,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length) desc->pfn = __phys_to_pfn(base); desc->length = length; - desc->type = MT_DEVICE; + desc->type = MT_MEMORY_NONCACHED; pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n", base, length, desc->virtual); diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h index 43a225f9e713..a1e1482c6da8 100644 --- a/arch/arm/mach-at91/soc.h +++ b/arch/arm/mach-at91/soc.h @@ -6,6 +6,7 @@ struct at91_init_soc { int builtin; + u32 extern_irq; unsigned int *default_irq_priority; void (*map_io)(void); void (*ioremap_registers)(void); diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 739be7e738fe..513eee14f77d 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -151,7 +151,6 @@ static __init void davinci_sffsdr_init(void) } MACHINE_START(SFFSDR, "Lyrtech SFFSDR") - /* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */ .atag_offset = 0x100, .map_io = davinci_sffsdr_map_io, .init_irq = davinci_irq_init, diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 73a2d905af8a..30e1ebe3a891 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -235,7 +235,6 @@ config IXP4XX_QMGR config IXP4XX_NPE tristate "IXP4xx Network Processor Engine support" select FW_LOADER - select HOTPLUG help This driver supports IXP4xx built-in network coprocessors and is automatically selected by Ethernet and HSS drivers. diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index 4dc2fbba0ecd..3a66635e7d17 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig @@ -3,7 +3,6 @@ config SOC_IMX23 select ARM_AMBA select ARM_CPU_SUSPEND if PM select CPU_ARM926T - select HAVE_PWM select PINCTRL_IMX23 config SOC_IMX28 @@ -12,7 +11,6 @@ config SOC_IMX28 select ARM_CPU_SUSPEND if PM select CPU_ARM926T select HAVE_CAN_FLEXCAN if CAN - select HAVE_PWM select PINCTRL_IMX28 config ARCH_MXS diff --git a/arch/arm/mach-mxs/pm.h b/arch/arm/mach-mxs/pm.h index f57e7cdece2e..09d77b00a96b 100644 --- a/arch/arm/mach-mxs/pm.h +++ b/arch/arm/mach-mxs/pm.h @@ -9,6 +9,10 @@ #ifndef __ARCH_MXS_PM_H #define __ARCH_MXS_PM_H +#ifdef CONFIG_PM void mxs_pm_init(void); +#else +#define mxs_pm_init NULL +#endif #endif diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index ee6218c74807..d4622ed26252 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -293,7 +293,8 @@ static struct regulator_consumer_supply cm_t35_vsim_supply[] = { static struct regulator_consumer_supply cm_t35_vio_supplies[] = { REGULATOR_SUPPLY("vcc", "spi1.0"), REGULATOR_SUPPLY("vdds_dsi", "omapdss"), - REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), }; /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 576420544178..f1d91ba5d1ac 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -222,6 +222,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = { static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = { REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"), REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), }; diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index d0d17bc58d9b..62e4f701b63b 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -272,7 +272,8 @@ static struct regulator_init_data ldp_vaux1 = { static struct regulator_consumer_supply ldp_vpll2_supplies[] = { REGULATOR_SUPPLY("vdds_dsi", "omapdss"), - REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), }; static struct regulator_init_data ldp_vpll2 = { diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 28133d5b4fed..b1547a0edfcd 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -343,6 +343,7 @@ static struct regulator_consumer_supply pandora_vmmc3_supply[] = { static struct regulator_consumer_supply pandora_vdds_supplies[] = { REGULATOR_SUPPLY("vdds_sdi", "omapdss"), REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"), REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), }; diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 18ca61e300b3..9c2dd102fbbb 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -553,6 +553,7 @@ static struct regulator_consumer_supply rx51_vio_supplies[] = { static struct regulator_consumer_supply rx51_vaux1_consumers[] = { REGULATOR_SUPPLY("vdds_sdi", "omapdss"), + REGULATOR_SUPPLY("vdds_sdi", "omapdss_sdi.0"), /* Si4713 supply */ REGULATOR_SUPPLY("vdd", "2-0063"), /* lis3lv02d */ diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 2adb2683f074..31e0dfe4a4ea 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -249,6 +249,7 @@ void omap_ctrl_write_dsp_boot_addr(u32 bootaddr) u32 offset = cpu_is_omap243x() ? OMAP243X_CONTROL_IVA2_BOOTADDR : cpu_is_omap34xx() ? OMAP343X_CONTROL_IVA2_BOOTADDR : cpu_is_omap44xx() ? OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR : + soc_is_omap54xx() ? OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR : 0; if (!offset) { diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index f874a3da8917..403c211e35d0 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -330,10 +330,8 @@ static void __init omap_init_mcpdm(void) struct platform_device *pdev; oh = omap_hwmod_lookup("mcpdm"); - if (!oh) { - printk(KERN_ERR "Could not look up mcpdm hw_mod\n"); + if (!oh) return; - } pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0); WARN(IS_ERR(pdev), "Can't build omap_device for omap-mcpdm.\n"); @@ -351,10 +349,8 @@ static void __init omap_init_dmic(void) struct platform_device *pdev; oh = omap_hwmod_lookup("dmic"); - if (!oh) { - pr_err("Could not look up dmic hw_mod\n"); + if (!oh) return; - } pdev = omap_device_build("omap-dmic", -1, oh, NULL, 0); WARN(IS_ERR(pdev), "Can't build omap_device for omap-dmic.\n"); @@ -377,10 +373,8 @@ static void __init omap_init_hdmi_audio(void) struct platform_device *pdev; oh = omap_hwmod_lookup("dss_hdmi"); - if (!oh) { - printk(KERN_ERR "Could not look up dss_hdmi hw_mod\n"); + if (!oh) return; - } pdev = omap_device_build("omap-hdmi-audio-dai", -1, oh, NULL, 0); WARN(IS_ERR(pdev), diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 1272c41d4749..54e4c16ce539 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -601,7 +601,7 @@ void __init omap2_set_globals_tap(u32 class, void __iomem *tap) #ifdef CONFIG_SOC_BUS -static const char const *omap_types[] = { +static const char * const omap_types[] = { [OMAP2_DEVICE_TYPE_TEST] = "TST", [OMAP2_DEVICE_TYPE_EMU] = "EMU", [OMAP2_DEVICE_TYPE_SEC] = "HS", diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 58d5b5667315..3a674de6cb63 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -175,6 +175,9 @@ static char *cmdline_find_option(char *str) static int __init omap_serial_early_init(void) { + if (of_have_populated_dt()) + return -ENODEV; + do { char oh_name[MAX_UART_HWMOD_NAME_LEN]; struct omap_hwmod *oh; diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 51e138cc5398..c05898fbd634 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -140,6 +140,7 @@ static struct regulator_init_data omap3_vdac_idata = { static struct regulator_consumer_supply omap3_vpll2_supplies[] = { REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"), REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"), }; diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index 544c92bf60cc..2eb19d4d0aa1 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c @@ -28,6 +28,7 @@ #include <linux/io.h> #include <linux/gpio.h> #include <linux/usb/phy.h> +#include <linux/usb/nop-usb-xceiv.h> #include "soc.h" #include "omap_device.h" @@ -366,7 +367,8 @@ static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply, struct regulator_init_data *reg_data; struct fixed_voltage_config *config; struct platform_device *pdev; - int ret; + struct platform_device_info pdevinfo; + int ret = -ENOMEM; supplies = kzalloc(sizeof(*supplies), GFP_KERNEL); if (!supplies) @@ -377,7 +379,7 @@ static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply, reg_data = kzalloc(sizeof(*reg_data), GFP_KERNEL); if (!reg_data) - return -ENOMEM; + goto err_data; reg_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS; reg_data->consumer_supplies = supplies; @@ -386,39 +388,53 @@ static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply, config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config), GFP_KERNEL); if (!config) - return -ENOMEM; + goto err_config; + + config->supply_name = kstrdup(name, GFP_KERNEL); + if (!config->supply_name) + goto err_supplyname; - config->supply_name = name; config->gpio = gpio; config->enable_high = polarity; config->init_data = reg_data; /* create a regulator device */ - pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); - if (!pdev) - return -ENOMEM; + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.name = reg_name; + pdevinfo.id = PLATFORM_DEVID_AUTO; + pdevinfo.data = config; + pdevinfo.size_data = sizeof(*config); - pdev->id = PLATFORM_DEVID_AUTO; - pdev->name = reg_name; - pdev->dev.platform_data = config; + pdev = platform_device_register_full(&pdevinfo); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + pr_err("%s: Failed registering regulator %s for %s : %d\n", + __func__, name, dev_id, ret); + goto err_register; + } - ret = platform_device_register(pdev); - if (ret) - pr_err("%s: Failed registering regulator %s for %s\n", - __func__, name, dev_id); + return 0; +err_register: + kfree(config->supply_name); +err_supplyname: + kfree(config); +err_config: + kfree(reg_data); +err_data: + kfree(supplies); return ret; } +#define MAX_STR 20 + int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) { - char *rail_name; - int i, len; + char rail_name[MAX_STR]; + int i; struct platform_device *pdev; char *phy_id; - - /* the phy_id will be something like "nop_usb_xceiv.1" */ - len = strlen(nop_name) + 3; /* 3 -> ".1" and NULL terminator */ + struct platform_device_info pdevinfo; for (i = 0; i < num_phys; i++) { @@ -433,25 +449,26 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) !gpio_is_valid(phy->vcc_gpio)) continue; - /* create a NOP PHY device */ - pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); - if (!pdev) - return -ENOMEM; - - pdev->id = phy->port; - pdev->name = nop_name; - pdev->dev.platform_data = phy->platform_data; - - phy_id = kmalloc(len, GFP_KERNEL); - if (!phy_id) + phy_id = kmalloc(MAX_STR, GFP_KERNEL); + if (!phy_id) { + pr_err("%s: kmalloc() failed\n", __func__); return -ENOMEM; + } - scnprintf(phy_id, len, "nop_usb_xceiv.%d\n", - pdev->id); - - if (platform_device_register(pdev)) { - pr_err("%s: Failed to register device %s\n", - __func__, phy_id); + /* create a NOP PHY device */ + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.name = nop_name; + pdevinfo.id = phy->port; + pdevinfo.data = phy->platform_data; + pdevinfo.size_data = sizeof(struct nop_usb_xceiv_platform_data); + + scnprintf(phy_id, MAX_STR, "nop_usb_xceiv.%d", + phy->port); + pdev = platform_device_register_full(&pdevinfo); + if (IS_ERR(pdev)) { + pr_err("%s: Failed to register device %s : %ld\n", + __func__, phy_id, PTR_ERR(pdev)); + kfree(phy_id); continue; } @@ -459,26 +476,15 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) /* Do we need RESET regulator ? */ if (gpio_is_valid(phy->reset_gpio)) { - - rail_name = kmalloc(13, GFP_KERNEL); - if (!rail_name) - return -ENOMEM; - - scnprintf(rail_name, 13, "hsusb%d_reset", phy->port); - + scnprintf(rail_name, MAX_STR, + "hsusb%d_reset", phy->port); usbhs_add_regulator(rail_name, phy_id, "reset", phy->reset_gpio, 1); } /* Do we need VCC regulator ? */ if (gpio_is_valid(phy->vcc_gpio)) { - - rail_name = kmalloc(13, GFP_KERNEL); - if (!rail_name) - return -ENOMEM; - - scnprintf(rail_name, 13, "hsusb%d_vcc", phy->port); - + scnprintf(rail_name, MAX_STR, "hsusb%d_vcc", phy->port); usbhs_add_regulator(rail_name, phy_id, "vcc", phy->vcc_gpio, phy->vcc_polarity); } diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c index a9f475cdf603..2c70f74fed5d 100644 --- a/arch/arm/mach-prima2/common.c +++ b/arch/arm/mach-prima2/common.c @@ -16,16 +16,6 @@ #include <linux/of_platform.h> #include "common.h" -static struct of_device_id sirfsoc_of_bus_ids[] __initdata = { - { .compatible = "simple-bus", }, - {}, -}; - -void __init sirfsoc_mach_init(void) -{ - of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL); -} - void __init sirfsoc_init_late(void) { sirfsoc_pm_init(); @@ -55,7 +45,6 @@ DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)") .nr_irqs = 128, .map_io = sirfsoc_map_io, .init_time = sirfsoc_init_time, - .init_machine = sirfsoc_mach_init, .init_late = sirfsoc_init_late, .dt_compat = atlas6_dt_match, .restart = sirfsoc_restart, @@ -64,8 +53,8 @@ MACHINE_END #ifdef CONFIG_ARCH_PRIMA2 static const char *prima2_dt_match[] __initdata = { - "sirf,prima2", - NULL + "sirf,prima2", + NULL }; DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") @@ -74,7 +63,6 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") .map_io = sirfsoc_map_io, .init_time = sirfsoc_init_time, .dma_zone_size = SZ_256M, - .init_machine = sirfsoc_mach_init, .init_late = sirfsoc_init_late, .dt_compat = prima2_dt_match, .restart = sirfsoc_restart, @@ -92,7 +80,6 @@ DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)") .smp = smp_ops(sirfsoc_smp_ops), .map_io = sirfsoc_map_io, .init_time = sirfsoc_init_time, - .init_machine = sirfsoc_mach_init, .init_late = sirfsoc_init_late, .dt_compat = marco_dt_match, .restart = sirfsoc_restart, diff --git a/arch/arm/mach-prima2/pm.c b/arch/arm/mach-prima2/pm.c index 8f595c0cc8d9..02cc34388b05 100644 --- a/arch/arm/mach-prima2/pm.c +++ b/arch/arm/mach-prima2/pm.c @@ -9,7 +9,7 @@ #include <linux/kernel.h> #include <linux/suspend.h> #include <linux/slab.h> -#include <linux/module.h> +#include <linux/export.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_device.h> diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c index 32360e540ce6..eb3fa4aee0e4 100644 --- a/arch/arm/mach-tegra/pmc.c +++ b/arch/arm/mach-tegra/pmc.c @@ -234,7 +234,7 @@ static const struct of_device_id matches[] __initconst = { { } }; -static void tegra_pmc_parse_dt(void) +static void __init tegra_pmc_parse_dt(void) { struct device_node *np; u32 prop; diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 15451ee4acc8..515b00064da8 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -92,6 +92,14 @@ ENTRY(v7_flush_dcache_louis) mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr ALT_SMP(ands r3, r0, #(7 << 21)) @ extract LoUIS from clidr ALT_UP(ands r3, r0, #(7 << 27)) @ extract LoUU from clidr +#ifdef CONFIG_ARM_ERRATA_643719 + ALT_SMP(mrceq p15, 0, r2, c0, c0, 0) @ read main ID register + ALT_UP(moveq pc, lr) @ LoUU is zero, so nothing to do + ldreq r1, =0x410fc090 @ ID of ARM Cortex A9 r0p? + biceq r2, r2, #0x0000000f @ clear minor revision number + teqeq r2, r1 @ test for errata affected core and if so... + orreqs r3, #(1 << 21) @ fix LoUIS value (and set flags state to 'ne') +#endif ALT_SMP(mov r3, r3, lsr #20) @ r3 = LoUIS * 2 ALT_UP(mov r3, r3, lsr #26) @ r3 = LoUU * 2 moveq pc, lr @ return if level == 0 diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 0d473cce501c..32aa5861119f 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -301,6 +301,39 @@ void flush_dcache_page(struct page *page) EXPORT_SYMBOL(flush_dcache_page); /* + * Ensure cache coherency for the kernel mapping of this page. We can + * assume that the page is pinned via kmap. + * + * If the page only exists in the page cache and there are no user + * space mappings, this is a no-op since the page was already marked + * dirty at creation. Otherwise, we need to flush the dirty kernel + * cache lines directly. + */ +void flush_kernel_dcache_page(struct page *page) +{ + if (cache_is_vivt() || cache_is_vipt_aliasing()) { + struct address_space *mapping; + + mapping = page_mapping(page); + + if (!mapping || mapping_mapped(mapping)) { + void *addr; + + addr = page_address(page); + /* + * kmap_atomic() doesn't set the page virtual + * address for highmem pages, and + * kunmap_atomic() takes care of cache + * flushing already. + */ + if (!IS_ENABLED(CONFIG_HIGHMEM) || addr) + __cpuc_flush_dcache_area(addr, PAGE_SIZE); + } + } +} +EXPORT_SYMBOL(flush_kernel_dcache_page); + +/* * Flush an anonymous page so that users of get_user_pages() * can safely access the data. The expected sequence is: * diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index faa36d7b8786..d1d1cefa1f93 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -616,10 +616,12 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, } while (pte++, addr += PAGE_SIZE, addr != end); } -static void __init map_init_section(pmd_t *pmd, unsigned long addr, +static void __init __map_init_section(pmd_t *pmd, unsigned long addr, unsigned long end, phys_addr_t phys, const struct mem_type *type) { + pmd_t *p = pmd; + #ifndef CONFIG_ARM_LPAE /* * In classic MMU format, puds and pmds are folded in to @@ -638,7 +640,7 @@ static void __init map_init_section(pmd_t *pmd, unsigned long addr, phys += SECTION_SIZE; } while (pmd++, addr += SECTION_SIZE, addr != end); - flush_pmd_entry(pmd); + flush_pmd_entry(p); } static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, @@ -661,7 +663,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, */ if (type->prot_sect && ((addr | next | phys) & ~SECTION_MASK) == 0) { - map_init_section(pmd, addr, next, phys, type); + __map_init_section(pmd, addr, next, phys, type); } else { alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), type); diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index d51225f90ae2..eb5293a69a84 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -57,6 +57,12 @@ void flush_dcache_page(struct page *page) } EXPORT_SYMBOL(flush_dcache_page); +void flush_kernel_dcache_page(struct page *page) +{ + __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); +} +EXPORT_SYMBOL(flush_kernel_dcache_page); + void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long uaddr, void *dst, const void *src, unsigned long len) diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S index d217e9795d74..aaeb6c127c7a 100644 --- a/arch/arm/mm/proc-fa526.S +++ b/arch/arm/mm/proc-fa526.S @@ -81,7 +81,6 @@ ENDPROC(cpu_fa526_reset) */ .align 4 ENTRY(cpu_fa526_do_idle) - mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt mov pc, lr diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index f9a0aa725ea9..e3c48a3fe063 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -333,3 +333,8 @@ ENTRY(\name\()_tlb_fns) .endif .size \name\()_tlb_fns, . - \name\()_tlb_fns .endm + +.macro globl_equ x, y + .globl \x + .equ \x, \y +.endm diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 2c73a7301ff7..e35fec34453e 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -140,6 +140,29 @@ ENTRY(cpu_v7_do_resume) ENDPROC(cpu_v7_do_resume) #endif +#ifdef CONFIG_CPU_PJ4B + globl_equ cpu_pj4b_switch_mm, cpu_v7_switch_mm + globl_equ cpu_pj4b_set_pte_ext, cpu_v7_set_pte_ext + globl_equ cpu_pj4b_proc_init, cpu_v7_proc_init + globl_equ cpu_pj4b_proc_fin, cpu_v7_proc_fin + globl_equ cpu_pj4b_reset, cpu_v7_reset +#ifdef CONFIG_PJ4B_ERRATA_4742 +ENTRY(cpu_pj4b_do_idle) + dsb @ WFI may enter a low-power mode + wfi + dsb @barrier + mov pc, lr +ENDPROC(cpu_pj4b_do_idle) +#else + globl_equ cpu_pj4b_do_idle, cpu_v7_do_idle +#endif + globl_equ cpu_pj4b_dcache_clean_area, cpu_v7_dcache_clean_area + globl_equ cpu_pj4b_do_suspend, cpu_v7_do_suspend + globl_equ cpu_pj4b_do_resume, cpu_v7_do_resume + globl_equ cpu_pj4b_suspend_size, cpu_v7_suspend_size + +#endif + __CPUINIT /* @@ -350,6 +373,9 @@ __v7_setup_stack: @ define struct processor (see <asm/proc-fns.h> and proc-macros.S) define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 +#ifdef CONFIG_CPU_PJ4B + define_processor_functions pj4b, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 +#endif .section ".rodata" @@ -362,7 +388,7 @@ __v7_setup_stack: /* * Standard v7 proc info content */ -.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0 +.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0, proc_fns = v7_processor_functions ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \ PMD_SECT_AF | PMD_FLAGS_SMP | \mm_mmuflags) ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \ @@ -375,7 +401,7 @@ __v7_setup_stack: .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \ HWCAP_EDSP | HWCAP_TLS | \hwcaps .long cpu_v7_name - .long v7_processor_functions + .long \proc_fns .long v7wbi_tlb_fns .long v6_user_fns .long v7_cache_fns @@ -407,12 +433,14 @@ __v7_ca9mp_proc_info: /* * Marvell PJ4B processor. */ +#ifdef CONFIG_CPU_PJ4B .type __v7_pj4b_proc_info, #object __v7_pj4b_proc_info: - .long 0x562f5840 - .long 0xfffffff0 - __v7_proc __v7_pj4b_setup + .long 0x560f5800 + .long 0xff0fff00 + __v7_proc __v7_pj4b_setup, proc_fns = pj4b_processor_functions .size __v7_pj4b_proc_info, . - __v7_pj4b_proc_info +#endif /* * ARM Ltd. Cortex A7 processor. |