diff options
Diffstat (limited to 'arch')
810 files changed, 32820 insertions, 10219 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index dd0e8eb8042f..a4429bcd609e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -213,6 +213,9 @@ config USE_GENERIC_SMP_HELPERS config GENERIC_SMP_IDLE_THREAD bool +config GENERIC_IDLE_POLL_SETUP + bool + # Select if arch init_task initializer is different to init/init_task.c config ARCH_INIT_TASK bool diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 8629127640cf..837a1f2d8b96 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -55,9 +55,6 @@ config GENERIC_CALIBRATE_DELAY bool default y -config GENERIC_GPIO - bool - config ZONE_DMA bool default y diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index e6f4eca09ee3..5917099470ea 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -16,8 +16,6 @@ config ARC select GENERIC_FIND_FIRST_BIT # for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP select GENERIC_IRQ_SHOW - select GENERIC_KERNEL_EXECVE - select GENERIC_KERNEL_THREAD select GENERIC_PENDING_IRQ if SMP select GENERIC_SMP_IDLE_THREAD select HAVE_ARCH_KGDB @@ -61,9 +59,6 @@ config GENERIC_CALIBRATE_DELAY config GENERIC_HWEIGHT def_bool y -config BINFMT_ELF - def_bool y - config STACKTRACE_SUPPORT def_bool y select STACKTRACE @@ -82,6 +77,7 @@ menu "ARC Architecture Configuration" menu "ARC Platform/SoC/Board" source "arch/arc/plat-arcfpga/Kconfig" +source "arch/arc/plat-tb10x/Kconfig" #New platform adds here endmenu @@ -134,9 +130,6 @@ if SMP config ARC_HAS_COH_CACHES def_bool n -config ARC_HAS_COH_LLSC - def_bool n - config ARC_HAS_COH_RTSC def_bool n @@ -189,6 +182,10 @@ config ARC_CACHE_PAGES Note that Global I/D ENABLE + Per Page DISABLE works but corollary Global DISABLE + Per Page ENABLE won't work +config ARC_CACHE_VIPT_ALIASING + bool "Support VIPT Aliasing D$" + default n + endif #ARC_CACHE config ARC_HAS_ICCM @@ -304,6 +301,9 @@ config ARC_FPU_SAVE_RESTORE based on actual usage of FPU by a task. Thus our implemn does this for all tasks in system. +config ARC_CANT_LLSC + def_bool n + menuconfig ARC_CPU_REL_4_10 bool "Enable support for Rel 4.10 features" default n @@ -314,9 +314,7 @@ menuconfig ARC_CPU_REL_4_10 config ARC_HAS_LLSC bool "Insn: LLOCK/SCOND (efficient atomic ops)" default y - depends on ARC_CPU_770 - # if SMP, enable LLSC ONLY if ARC implementation has coherent atomics - depends on !SMP || ARC_HAS_COH_LLSC + depends on ARC_CPU_770 && !ARC_CANT_LLSC config ARC_HAS_SWAPE bool "Insn: SWAPE (endian-swap)" @@ -415,13 +413,6 @@ config ARC_DBG_TLB_MISS_COUNT Counts number of I and D TLB Misses and exports them via Debugfs The counters can be cleared via Debugfs as well -config CMDLINE - string "Kernel command line to built-in" - default "print-fatal-signals=1" - help - The default command line which will be appended to the optional - u-boot provided command line (see below) - config CMDLINE_UBOOT bool "Support U-boot kernel command line passing" default n @@ -430,8 +421,8 @@ config CMDLINE_UBOOT command line from the U-boot environment to the Linux kernel then switch this option on. ARC U-boot will setup the cmdline in RAM/flash and set r2 to point - to it. kernel startup code will copy the string into cmdline buffer - and also append CONFIG_CMDLINE. + to it. kernel startup code will append this to DeviceTree + /bootargs provided cmdline args. config ARC_BUILTIN_DTB_NAME string "Built in DTB" @@ -441,6 +432,10 @@ config ARC_BUILTIN_DTB_NAME source "kernel/Kconfig.preempt" +menu "Executable file formats" +source "fs/Kconfig.binfmt" +endmenu + endmenu # "ARC Architecture Configuration" source "mm/Kconfig" diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 92379c7cbc1a..183397fd289e 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -8,6 +8,10 @@ UTS_MACHINE := arc +ifeq ($(CROSS_COMPILE),) +CROSS_COMPILE := arc-elf32- +endif + KBUILD_DEFCONFIG := fpga_defconfig cflags-y += -mA7 -fno-common -pipe -fno-builtin -D__linux__ @@ -87,20 +91,23 @@ core-y += arch/arc/ core-y += arch/arc/boot/dts/ core-$(CONFIG_ARC_PLAT_FPGA_LEGACY) += arch/arc/plat-arcfpga/ +core-$(CONFIG_ARC_PLAT_TB10X) += arch/arc/plat-tb10x/ drivers-$(CONFIG_OPROFILE) += arch/arc/oprofile/ libs-y += arch/arc/lib/ $(LIBGCC) +boot := arch/arc/boot + #default target for make without any arguements. -KBUILD_IMAGE := bootpImage +KBUILD_IMAGE := bootpImage all: $(KBUILD_IMAGE) -boot := arch/arc/boot - bootpImage: vmlinux -uImage: vmlinux +boot_targets += uImage uImage.bin uImage.gz + +$(boot_targets): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ %.dtb %.dtb.S %.dtb.o: scripts diff --git a/arch/arc/boot/Makefile b/arch/arc/boot/Makefile index 7d514c24e095..e597cb34c16a 100644 --- a/arch/arc/boot/Makefile +++ b/arch/arc/boot/Makefile @@ -3,7 +3,6 @@ targets := vmlinux.bin vmlinux.bin.gz uImage # uImage build relies on mkimage being availble on your host for ARC target # You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage # and make sure it's reacable from your PATH -MKIMAGE := $(srctree)/scripts/mkuboot.sh OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S @@ -12,7 +11,12 @@ LINUX_START_TEXT = $$(readelf -h vmlinux | \ UIMAGE_LOADADDR = $(CONFIG_LINUX_LINK_BASE) UIMAGE_ENTRYADDR = $(LINUX_START_TEXT) -UIMAGE_COMPRESSION = gzip + +suffix-y := bin +suffix-$(CONFIG_KERNEL_GZIP) := gz + +targets += uImage uImage.bin uImage.gz +extra-y += vmlinux.bin vmlinux.bin.gz $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) @@ -20,7 +24,12 @@ $(obj)/vmlinux.bin: vmlinux FORCE $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) -$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE - $(call if_changed,uimage) +$(obj)/uImage.bin: $(obj)/vmlinux.bin FORCE + $(call if_changed,uimage,none) + +$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE + $(call if_changed,uimage,gzip) -PHONY += FORCE +$(obj)/uImage: $(obj)/uImage.$(suffix-y) + @ln -sf $(notdir $<) $@ + @echo ' Image $@ is ready' diff --git a/arch/arc/boot/dts/Makefile b/arch/arc/boot/dts/Makefile index 5776835d583f..faf240e29ec2 100644 --- a/arch/arc/boot/dts/Makefile +++ b/arch/arc/boot/dts/Makefile @@ -8,6 +8,8 @@ endif obj-y += $(builtindtb-y).dtb.o targets += $(builtindtb-y).dtb +.SECONDARY: $(obj)/$(builtindtb-y).dtb.S + dtbs: $(addprefix $(obj)/, $(builtindtb-y).dtb) -clean-files := *.dtb +clean-files := *.dtb *.dtb.S diff --git a/arch/arc/boot/dts/abilis_tb100.dtsi b/arch/arc/boot/dts/abilis_tb100.dtsi new file mode 100644 index 000000000000..941ad118a7e7 --- /dev/null +++ b/arch/arc/boot/dts/abilis_tb100.dtsi @@ -0,0 +1,340 @@ +/* + * Abilis Systems TB100 SOC device tree + * + * Copyright (C) Abilis Systems 2013 + * + * Author: Christian Ruppert <christian.ruppert@abilis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/include/ "abilis_tb10x.dtsi" + +/* interrupt specifiers + * -------------------- + * 0: rising, 1: low, 2: high, 3: falling, + */ + +/ { + clock-frequency = <500000000>; /* 500 MHZ */ + + soc100 { + bus-frequency = <166666666>; + + pll0: oscillator { + clock-frequency = <1000000000>; + }; + cpu_clk: clkdiv_cpu { + clock-mult = <1>; + clock-div = <2>; + }; + ahb_clk: clkdiv_ahb { + clock-mult = <1>; + clock-div = <6>; + }; + + iomux: iomux@FF10601c { + /* Port 1 */ + pctl_tsin_s0: pctl-tsin-s0 { /* Serial TS-in 0 */ + pingrp = "mis0_pins"; + }; + pctl_tsin_s1: pctl-tsin-s1 { /* Serial TS-in 1 */ + pingrp = "mis1_pins"; + }; + pctl_gpio_a: pctl-gpio-a { /* GPIO bank A */ + pingrp = "gpioa_pins"; + }; + pctl_tsin_p1: pctl-tsin-p1 { /* Parallel TS-in 1 */ + pingrp = "mip1_pins"; + }; + /* Port 2 */ + pctl_tsin_s2: pctl-tsin-s2 { /* Serial TS-in 2 */ + pingrp = "mis2_pins"; + }; + pctl_tsin_s3: pctl-tsin-s3 { /* Serial TS-in 3 */ + pingrp = "mis3_pins"; + }; + pctl_gpio_c: pctl-gpio-c { /* GPIO bank C */ + pingrp = "gpioc_pins"; + }; + pctl_tsin_p3: pctl-tsin-p3 { /* Parallel TS-in 3 */ + pingrp = "mip3_pins"; + }; + /* Port 3 */ + pctl_tsin_s4: pctl-tsin-s4 { /* Serial TS-in 4 */ + pingrp = "mis4_pins"; + }; + pctl_tsin_s5: pctl-tsin-s5 { /* Serial TS-in 5 */ + pingrp = "mis5_pins"; + }; + pctl_gpio_e: pctl-gpio-e { /* GPIO bank E */ + pingrp = "gpioe_pins"; + }; + pctl_tsin_p5: pctl-tsin-p5 { /* Parallel TS-in 5 */ + pingrp = "mip5_pins"; + }; + /* Port 4 */ + pctl_tsin_s6: pctl-tsin-s6 { /* Serial TS-in 6 */ + pingrp = "mis6_pins"; + }; + pctl_tsin_s7: pctl-tsin-s7 { /* Serial TS-in 7 */ + pingrp = "mis7_pins"; + }; + pctl_gpio_g: pctl-gpio-g { /* GPIO bank G */ + pingrp = "gpiog_pins"; + }; + pctl_tsin_p7: pctl-tsin-p7 { /* Parallel TS-in 7 */ + pingrp = "mip7_pins"; + }; + /* Port 5 */ + pctl_gpio_j: pctl-gpio-j { /* GPIO bank J */ + pingrp = "gpioj_pins"; + }; + pctl_gpio_k: pctl-gpio-k { /* GPIO bank K */ + pingrp = "gpiok_pins"; + }; + pctl_ciplus: pctl-ciplus { /* CI+ interface */ + pingrp = "ciplus_pins"; + }; + pctl_mcard: pctl-mcard { /* M-Card interface */ + pingrp = "mcard_pins"; + }; + /* Port 6 */ + pctl_tsout_p: pctl-tsout-p { /* Parallel TS-out */ + pingrp = "mop_pins"; + }; + pctl_tsout_s0: pctl-tsout-s0 { /* Serial TS-out 0 */ + pingrp = "mos0_pins"; + }; + pctl_tsout_s1: pctl-tsout-s1 { /* Serial TS-out 1 */ + pingrp = "mos1_pins"; + }; + pctl_tsout_s2: pctl-tsout-s2 { /* Serial TS-out 2 */ + pingrp = "mos2_pins"; + }; + pctl_tsout_s3: pctl-tsout-s3 { /* Serial TS-out 3 */ + pingrp = "mos3_pins"; + }; + /* Port 7 */ + pctl_uart0: pctl-uart0 { /* UART 0 */ + pingrp = "uart0_pins"; + }; + pctl_uart1: pctl-uart1 { /* UART 1 */ + pingrp = "uart1_pins"; + }; + pctl_gpio_l: pctl-gpio-l { /* GPIO bank L */ + pingrp = "gpiol_pins"; + }; + pctl_gpio_m: pctl-gpio-m { /* GPIO bank M */ + pingrp = "gpiom_pins"; + }; + /* Port 8 */ + pctl_spi3: pctl-spi3 { + pingrp = "spi3_pins"; + }; + /* Port 9 */ + pctl_spi1: pctl-spi1 { + pingrp = "spi1_pins"; + }; + pctl_gpio_n: pctl-gpio-n { + pingrp = "gpion_pins"; + }; + /* Unmuxed GPIOs */ + pctl_gpio_b: pctl-gpio-b { + pingrp = "gpiob_pins"; + }; + pctl_gpio_d: pctl-gpio-d { + pingrp = "gpiod_pins"; + }; + pctl_gpio_f: pctl-gpio-f { + pingrp = "gpiof_pins"; + }; + pctl_gpio_h: pctl-gpio-h { + pingrp = "gpioh_pins"; + }; + pctl_gpio_i: pctl-gpio-i { + pingrp = "gpioi_pins"; + }; + }; + + gpioa: gpio@FF140000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF140000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <0>; + gpio-pins = <&pctl_gpio_a>; + }; + gpiob: gpio@FF141000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF141000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <3>; + gpio-pins = <&pctl_gpio_b>; + }; + gpioc: gpio@FF142000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF142000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <5>; + gpio-pins = <&pctl_gpio_c>; + }; + gpiod: gpio@FF143000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF143000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <8>; + gpio-pins = <&pctl_gpio_d>; + }; + gpioe: gpio@FF144000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF144000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <10>; + gpio-pins = <&pctl_gpio_e>; + }; + gpiof: gpio@FF145000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF145000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <13>; + gpio-pins = <&pctl_gpio_f>; + }; + gpiog: gpio@FF146000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF146000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <15>; + gpio-pins = <&pctl_gpio_g>; + }; + gpioh: gpio@FF147000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF147000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <18>; + gpio-pins = <&pctl_gpio_h>; + }; + gpioi: gpio@FF148000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF148000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <20>; + gpio-pins = <&pctl_gpio_i>; + }; + gpioj: gpio@FF149000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF149000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <32>; + gpio-pins = <&pctl_gpio_j>; + }; + gpiok: gpio@FF14a000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14A000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <64>; + gpio-pins = <&pctl_gpio_k>; + }; + gpiol: gpio@FF14b000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14B000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <86>; + gpio-pins = <&pctl_gpio_l>; + }; + gpiom: gpio@FF14c000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14C000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <90>; + gpio-pins = <&pctl_gpio_m>; + }; + gpion: gpio@FF14d000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14D000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <94>; + gpio-pins = <&pctl_gpio_n>; + }; + }; +}; diff --git a/arch/arc/boot/dts/abilis_tb100_dvk.dts b/arch/arc/boot/dts/abilis_tb100_dvk.dts new file mode 100644 index 000000000000..c0fd3623c393 --- /dev/null +++ b/arch/arc/boot/dts/abilis_tb100_dvk.dts @@ -0,0 +1,127 @@ +/* + * Abilis Systems TB100 Development Kit PCB device tree + * + * Copyright (C) Abilis Systems 2013 + * + * Author: Christian Ruppert <christian.ruppert@abilis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/dts-v1/; + +/include/ "abilis_tb100.dtsi" + +/ { + chosen { + bootargs = "earlycon=uart8250,mmio32,0xff100000,9600n8 console=ttyS0,9600n8"; + }; + + aliases { }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x08000000>; /* 128M */ + }; + + soc100 { + uart@FF100000 { + pinctrl-names = "abilis,simple-default"; + pinctrl-0 = <&pctl_uart0>; + }; + ethernet@FE100000 { + phy-mode = "rgmii"; + }; + + i2c0: i2c@FF120000 { + sda-hold-time = <432>; + }; + i2c1: i2c@FF121000 { + sda-hold-time = <432>; + }; + i2c2: i2c@FF122000 { + sda-hold-time = <432>; + }; + i2c3: i2c@FF123000 { + sda-hold-time = <432>; + }; + i2c4: i2c@FF124000 { + sda-hold-time = <432>; + }; + + leds { + compatible = "gpio-leds"; + power { + label = "Power"; + gpios = <&gpioi 0>; + linux,default-trigger = "default-on"; + }; + heartbeat { + label = "Heartbeat"; + gpios = <&gpioi 1>; + linux,default-trigger = "heartbeat"; + }; + led2 { + label = "LED2"; + gpios = <&gpioi 2>; + default-state = "off"; + }; + led3 { + label = "LED3"; + gpios = <&gpioi 3>; + default-state = "off"; + }; + led4 { + label = "LED4"; + gpios = <&gpioi 4>; + default-state = "off"; + }; + led5 { + label = "LED5"; + gpios = <&gpioi 5>; + default-state = "off"; + }; + led6 { + label = "LED6"; + gpios = <&gpioi 6>; + default-state = "off"; + }; + led7 { + label = "LED7"; + gpios = <&gpioi 7>; + default-state = "off"; + }; + led8 { + label = "LED8"; + gpios = <&gpioi 8>; + default-state = "off"; + }; + led9 { + label = "LED9"; + gpios = <&gpioi 9>; + default-state = "off"; + }; + led10 { + label = "LED10"; + gpios = <&gpioi 10>; + default-state = "off"; + }; + led11 { + label = "LED11"; + gpios = <&gpioi 11>; + default-state = "off"; + }; + }; + }; +}; diff --git a/arch/arc/boot/dts/abilis_tb101.dtsi b/arch/arc/boot/dts/abilis_tb101.dtsi new file mode 100644 index 000000000000..fd25c212049f --- /dev/null +++ b/arch/arc/boot/dts/abilis_tb101.dtsi @@ -0,0 +1,349 @@ +/* + * Abilis Systems TB101 SOC device tree + * + * Copyright (C) Abilis Systems 2013 + * + * Author: Christian Ruppert <christian.ruppert@abilis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/include/ "abilis_tb10x.dtsi" + +/* interrupt specifiers + * -------------------- + * 0: rising, 1: low, 2: high, 3: falling, + */ + +/ { + clock-frequency = <500000000>; /* 500 MHZ */ + + soc100 { + bus-frequency = <166666666>; + + pll0: oscillator { + clock-frequency = <1000000000>; + }; + cpu_clk: clkdiv_cpu { + clock-mult = <1>; + clock-div = <2>; + }; + ahb_clk: clkdiv_ahb { + clock-mult = <1>; + clock-div = <6>; + }; + + iomux: iomux@FF10601c { + /* Port 1 */ + pctl_tsin_s0: pctl-tsin-s0 { /* Serial TS-in 0 */ + pingrp = "mis0_pins"; + }; + pctl_tsin_s1: pctl-tsin-s1 { /* Serial TS-in 1 */ + pingrp = "mis1_pins"; + }; + pctl_gpio_a: pctl-gpio-a { /* GPIO bank A */ + pingrp = "gpioa_pins"; + }; + pctl_tsin_p1: pctl-tsin-p1 { /* Parallel TS-in 1 */ + pingrp = "mip1_pins"; + }; + /* Port 2 */ + pctl_tsin_s2: pctl-tsin-s2 { /* Serial TS-in 2 */ + pingrp = "mis2_pins"; + }; + pctl_tsin_s3: pctl-tsin-s3 { /* Serial TS-in 3 */ + pingrp = "mis3_pins"; + }; + pctl_gpio_c: pctl-gpio-c { /* GPIO bank C */ + pingrp = "gpioc_pins"; + }; + pctl_tsin_p3: pctl-tsin-p3 { /* Parallel TS-in 3 */ + pingrp = "mip3_pins"; + }; + /* Port 3 */ + pctl_tsin_s4: pctl-tsin-s4 { /* Serial TS-in 4 */ + pingrp = "mis4_pins"; + }; + pctl_tsin_s5: pctl-tsin-s5 { /* Serial TS-in 5 */ + pingrp = "mis5_pins"; + }; + pctl_gpio_e: pctl-gpio-e { /* GPIO bank E */ + pingrp = "gpioe_pins"; + }; + pctl_tsin_p5: pctl-tsin-p5 { /* Parallel TS-in 5 */ + pingrp = "mip5_pins"; + }; + /* Port 4 */ + pctl_tsin_s6: pctl-tsin-s6 { /* Serial TS-in 6 */ + pingrp = "mis6_pins"; + }; + pctl_tsin_s7: pctl-tsin-s7 { /* Serial TS-in 7 */ + pingrp = "mis7_pins"; + }; + pctl_gpio_g: pctl-gpio-g { /* GPIO bank G */ + pingrp = "gpiog_pins"; + }; + pctl_tsin_p7: pctl-tsin-p7 { /* Parallel TS-in 7 */ + pingrp = "mip7_pins"; + }; + /* Port 5 */ + pctl_gpio_j: pctl-gpio-j { /* GPIO bank J */ + pingrp = "gpioj_pins"; + }; + pctl_gpio_k: pctl-gpio-k { /* GPIO bank K */ + pingrp = "gpiok_pins"; + }; + pctl_ciplus: pctl-ciplus { /* CI+ interface */ + pingrp = "ciplus_pins"; + }; + pctl_mcard: pctl-mcard { /* M-Card interface */ + pingrp = "mcard_pins"; + }; + pctl_stc0: pctl-stc0 { /* Smart card I/F 0 */ + pingrp = "stc0_pins"; + }; + pctl_stc1: pctl-stc1 { /* Smart card I/F 1 */ + pingrp = "stc1_pins"; + }; + /* Port 6 */ + pctl_tsout_p: pctl-tsout-p { /* Parallel TS-out */ + pingrp = "mop_pins"; + }; + pctl_tsout_s0: pctl-tsout-s0 { /* Serial TS-out 0 */ + pingrp = "mos0_pins"; + }; + pctl_tsout_s1: pctl-tsout-s1 { /* Serial TS-out 1 */ + pingrp = "mos1_pins"; + }; + pctl_tsout_s2: pctl-tsout-s2 { /* Serial TS-out 2 */ + pingrp = "mos2_pins"; + }; + pctl_tsout_s3: pctl-tsout-s3 { /* Serial TS-out 3 */ + pingrp = "mos3_pins"; + }; + /* Port 7 */ + pctl_uart0: pctl-uart0 { /* UART 0 */ + pingrp = "uart0_pins"; + }; + pctl_uart1: pctl-uart1 { /* UART 1 */ + pingrp = "uart1_pins"; + }; + pctl_gpio_l: pctl-gpio-l { /* GPIO bank L */ + pingrp = "gpiol_pins"; + }; + pctl_gpio_m: pctl-gpio-m { /* GPIO bank M */ + pingrp = "gpiom_pins"; + }; + /* Port 8 */ + pctl_spi3: pctl-spi3 { + pingrp = "spi3_pins"; + }; + pctl_jtag: pctl-jtag { + pingrp = "jtag_pins"; + }; + /* Port 9 */ + pctl_spi1: pctl-spi1 { + pingrp = "spi1_pins"; + }; + pctl_gpio_n: pctl-gpio-n { + pingrp = "gpion_pins"; + }; + /* Unmuxed GPIOs */ + pctl_gpio_b: pctl-gpio-b { + pingrp = "gpiob_pins"; + }; + pctl_gpio_d: pctl-gpio-d { + pingrp = "gpiod_pins"; + }; + pctl_gpio_f: pctl-gpio-f { + pingrp = "gpiof_pins"; + }; + pctl_gpio_h: pctl-gpio-h { + pingrp = "gpioh_pins"; + }; + pctl_gpio_i: pctl-gpio-i { + pingrp = "gpioi_pins"; + }; + }; + + gpioa: gpio@FF140000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF140000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <0>; + gpio-pins = <&pctl_gpio_a>; + }; + gpiob: gpio@FF141000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF141000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <3>; + gpio-pins = <&pctl_gpio_b>; + }; + gpioc: gpio@FF142000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF142000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <5>; + gpio-pins = <&pctl_gpio_c>; + }; + gpiod: gpio@FF143000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF143000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <8>; + gpio-pins = <&pctl_gpio_d>; + }; + gpioe: gpio@FF144000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF144000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <10>; + gpio-pins = <&pctl_gpio_e>; + }; + gpiof: gpio@FF145000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF145000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <13>; + gpio-pins = <&pctl_gpio_f>; + }; + gpiog: gpio@FF146000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF146000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <15>; + gpio-pins = <&pctl_gpio_g>; + }; + gpioh: gpio@FF147000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF147000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <18>; + gpio-pins = <&pctl_gpio_h>; + }; + gpioi: gpio@FF148000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF148000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <20>; + gpio-pins = <&pctl_gpio_i>; + }; + gpioj: gpio@FF149000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF149000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <32>; + gpio-pins = <&pctl_gpio_j>; + }; + gpiok: gpio@FF14a000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14A000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <64>; + gpio-pins = <&pctl_gpio_k>; + }; + gpiol: gpio@FF14b000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14B000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <86>; + gpio-pins = <&pctl_gpio_l>; + }; + gpiom: gpio@FF14c000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14C000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <90>; + gpio-pins = <&pctl_gpio_m>; + }; + gpion: gpio@FF14d000 { + compatible = "abilis,tb10x-gpio"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <27 1>; + reg = <0xFF14D000 0x1000>; + gpio-controller; + #gpio-cells = <1>; + gpio-base = <94>; + gpio-pins = <&pctl_gpio_n>; + }; + }; +}; diff --git a/arch/arc/boot/dts/abilis_tb101_dvk.dts b/arch/arc/boot/dts/abilis_tb101_dvk.dts new file mode 100644 index 000000000000..6f8c381f6268 --- /dev/null +++ b/arch/arc/boot/dts/abilis_tb101_dvk.dts @@ -0,0 +1,127 @@ +/* + * Abilis Systems TB101 Development Kit PCB device tree + * + * Copyright (C) Abilis Systems 2013 + * + * Author: Christian Ruppert <christian.ruppert@abilis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/dts-v1/; + +/include/ "abilis_tb101.dtsi" + +/ { + chosen { + bootargs = "earlycon=uart8250,mmio32,0xff100000,9600n8 console=ttyS0,9600n8"; + }; + + aliases { }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x08000000>; /* 128M */ + }; + + soc100 { + uart@FF100000 { + pinctrl-names = "abilis,simple-default"; + pinctrl-0 = <&pctl_uart0>; + }; + ethernet@FE100000 { + phy-mode = "rgmii"; + }; + + i2c0: i2c@FF120000 { + sda-hold-time = <432>; + }; + i2c1: i2c@FF121000 { + sda-hold-time = <432>; + }; + i2c2: i2c@FF122000 { + sda-hold-time = <432>; + }; + i2c3: i2c@FF123000 { + sda-hold-time = <432>; + }; + i2c4: i2c@FF124000 { + sda-hold-time = <432>; + }; + + leds { + compatible = "gpio-leds"; + power { + label = "Power"; + gpios = <&gpioi 0>; + linux,default-trigger = "default-on"; + }; + heartbeat { + label = "Heartbeat"; + gpios = <&gpioi 1>; + linux,default-trigger = "heartbeat"; + }; + led2 { + label = "LED2"; + gpios = <&gpioi 2>; + default-state = "off"; + }; + led3 { + label = "LED3"; + gpios = <&gpioi 3>; + default-state = "off"; + }; + led4 { + label = "LED4"; + gpios = <&gpioi 4>; + default-state = "off"; + }; + led5 { + label = "LED5"; + gpios = <&gpioi 5>; + default-state = "off"; + }; + led6 { + label = "LED6"; + gpios = <&gpioi 6>; + default-state = "off"; + }; + led7 { + label = "LED7"; + gpios = <&gpioi 7>; + default-state = "off"; + }; + led8 { + label = "LED8"; + gpios = <&gpioi 8>; + default-state = "off"; + }; + led9 { + label = "LED9"; + gpios = <&gpioi 9>; + default-state = "off"; + }; + led10 { + label = "LED10"; + gpios = <&gpioi 10>; + default-state = "off"; + }; + led11 { + label = "LED11"; + gpios = <&gpioi 11>; + default-state = "off"; + }; + }; + }; +}; diff --git a/arch/arc/boot/dts/abilis_tb10x.dtsi b/arch/arc/boot/dts/abilis_tb10x.dtsi new file mode 100644 index 000000000000..a6139fc5aaa3 --- /dev/null +++ b/arch/arc/boot/dts/abilis_tb10x.dtsi @@ -0,0 +1,247 @@ +/* + * Abilis Systems TB10X SOC device tree + * + * Copyright (C) Abilis Systems 2013 + * + * Author: Christian Ruppert <christian.ruppert@abilis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* interrupt specifiers + * -------------------- + * 0: rising, 1: low, 2: high, 3: falling, + */ + +/ { + compatible = "abilis,arc-tb10x"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; + compatible = "snps,arc770d"; + reg = <0>; + }; + }; + + soc100 { + #address-cells = <1>; + #size-cells = <1>; + device_type = "soc"; + ranges = <0xfe000000 0xfe000000 0x02000000 + 0x000F0000 0x000F0000 0x00010000>; + compatible = "abilis,tb10x", "simple-bus"; + + pll0: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-output-names = "pll0"; + }; + cpu_clk: clkdiv_cpu { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clocks = <&pll0>; + clock-output-names = "cpu_clk"; + }; + ahb_clk: clkdiv_ahb { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clocks = <&pll0>; + clock-output-names = "ahb_clk"; + }; + + iomux: iomux@FF10601c { + #address-cells = <1>; + #size-cells = <1>; + compatible = "abilis,tb10x-iomux"; + reg = <0xFF10601c 0x4>; + }; + + intc: interrupt-controller { + compatible = "snps,arc700-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + tb10x_ictl: pic@fe002000 { + compatible = "abilis,tb10x_ictl"; + reg = <0xFE002000 0x20>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 30 31>; + }; + + uart@FF100000 { + compatible = "snps,dw-apb-uart", + "abilis,simple-pinctrl"; + reg = <0xFF100000 0x100>; + clock-frequency = <166666666>; + interrupts = <25 1>; + reg-shift = <2>; + reg-io-width = <4>; + interrupt-parent = <&tb10x_ictl>; + }; + ethernet@FE100000 { + compatible = "snps,dwmac-3.70a","snps,dwmac"; + reg = <0xFE100000 0x1058>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <6 1>; + interrupt-names = "macirq"; + clocks = <&ahb_clk>; + clock-names = "stmmaceth"; + }; + dma@FE000000 { + compatible = "snps,dma-spear1340"; + reg = <0xFE000000 0x400>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <14 1>; + dma-channels = <6>; + dma-requests = <0>; + dma-masters = <1>; + #dma-cells = <3>; + chan_allocation_order = <0>; + chan_priority = <1>; + block_size = <0x7ff>; + data_width = <2 0 0 0>; + clocks = <&ahb_clk>; + clock-names = "hclk"; + }; + + i2c0: i2c@FF120000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0xFF120000 0x1000>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <12 1>; + clocks = <&ahb_clk>; + }; + i2c1: i2c@FF121000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0xFF121000 0x1000>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <12 1>; + clocks = <&ahb_clk>; + }; + i2c2: i2c@FF122000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0xFF122000 0x1000>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <12 1>; + clocks = <&ahb_clk>; + }; + i2c3: i2c@FF123000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0xFF123000 0x1000>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <12 1>; + clocks = <&ahb_clk>; + }; + i2c4: i2c@FF124000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0xFF124000 0x1000>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <12 1>; + clocks = <&ahb_clk>; + }; + + spi0: spi@0xFE010000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + compatible = "abilis,tb100-spi"; + num-cs = <1>; + reg = <0xFE010000 0x20>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <26 1>; + clocks = <&ahb_clk>; + }; + spi1: spi@0xFE011000 { + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + compatible = "abilis,tb100-spi", + "abilis,simple-pinctrl"; + num-cs = <2>; + reg = <0xFE011000 0x20>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <10 1>; + clocks = <&ahb_clk>; + }; + + tb10x_tsm: tb10x-tsm@ff316000 { + compatible = "abilis,tb100-tsm"; + reg = <0xff316000 0x400>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <17 1>; + output-clkdiv = <4>; + global-packet-delay = <0x21>; + port-packet-delay = <0>; + }; + tb10x_stream_proc: tb10x-stream-proc { + compatible = "abilis,tb100-streamproc"; + reg = <0xfff00000 0x200>, + <0x000f0000 0x10000>, + <0xfff00200 0x105>, + <0xff10600c 0x1>, + <0xfe001018 0x1>; + reg-names = "mbox", + "sp_iccm", + "mbox_irq", + "cpuctrl", + "a6it_int_force"; + interrupt-parent = <&tb10x_ictl>; + interrupts = <20 1>, <19 1>; + interrupt-names = "cmd_irq", "event_irq"; + }; + tb10x_mdsc0: tb10x-mdscr@FF300000 { + compatible = "abilis,tb100-mdscr"; + reg = <0xFF300000 0x7000>; + tb100-mdscr-manage-tsin; + }; + tb10x_mscr0: tb10x-mdscr@FF307000 { + compatible = "abilis,tb100-mdscr"; + reg = <0xFF307000 0x7000>; + }; + tb10x_scr0: tb10x-mdscr@ff30e000 { + compatible = "abilis,tb100-mdscr"; + reg = <0xFF30e000 0x4000>; + tb100-mdscr-manage-tsin; + }; + tb10x_scr1: tb10x-mdscr@ff312000 { + compatible = "abilis,tb100-mdscr"; + reg = <0xFF312000 0x4000>; + tb100-mdscr-manage-tsin; + }; + tb10x_wfb: tb10x-wfb@ff319000 { + compatible = "abilis,tb100-wfb"; + reg = <0xff319000 0x1000>; + interrupt-parent = <&tb10x_ictl>; + interrupts = <16 1>; + }; + }; +}; diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts new file mode 100644 index 000000000000..ea16d782af58 --- /dev/null +++ b/arch/arc/boot/dts/nsimosci.dts @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +/dts-v1/; + +/include/ "skeleton.dtsi" + +/ { + compatible = "snps,nsimosci"; + clock-frequency = <80000000>; /* 80 MHZ */ + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + + chosen { + bootargs = "console=tty0 consoleblank=0"; + }; + + aliases { + serial0 = &uart0; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256M */ + }; + + fpga { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + /* child and parent address space 1:1 mapped */ + ranges; + + intc: interrupt-controller { + compatible = "snps,arc700-intc"; + interrupt-controller; + #interrupt-cells = <1>; + }; + + uart0: serial@c0000000 { + compatible = "snps,dw-apb-uart"; + reg = <0xc0000000 0x2000>; + interrupts = <11>; + #clock-frequency = <80000000>; + clock-frequency = <3686400>; + baud = <115200>; + reg-shift = <2>; + reg-io-width = <4>; + status = "okay"; + }; + + pgu0: pgu@c9000000 { + compatible = "snps,arcpgufb"; + reg = <0xc9000000 0x400>; + }; + + ps2: ps2@c9001000 { + compatible = "snps,arc_ps2"; + reg = <0xc9000400 0x14>; + interrupts = <13>; + interrupt-names = "arc_ps2_irq"; + }; + + eth0: ethernet@c0003000 { + compatible = "snps,oscilan"; + reg = <0xc0003000 0x44>; + interrupts = <7>, <8>; + interrupt-names = "rx", "tx"; + }; + }; +}; diff --git a/arch/arc/configs/fpga_defconfig b/arch/arc/configs/fpga_defconfig index b8698067ebbe..95350be6ef6f 100644 --- a/arch/arc/configs/fpga_defconfig +++ b/arch/arc/configs/fpga_defconfig @@ -9,7 +9,7 @@ CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="../arc_initramfs" +CONFIG_INITRAMFS_SOURCE="../arc_initramfs/" CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_SLUB_DEBUG is not set @@ -24,6 +24,7 @@ CONFIG_ARC_PLAT_FPGA_LEGACY=y CONFIG_ARC_BOARD_ML509=y # CONFIG_ARC_HAS_RTSC is not set CONFIG_ARC_BUILTIN_DTB_NAME="angel4" +CONFIG_PREEMPT=y # CONFIG_COMPACTION is not set # CONFIG_CROSS_MEMORY_ATTACH is not set CONFIG_NET=y diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig new file mode 100644 index 000000000000..446c96c24eff --- /dev/null +++ b/arch/arc/configs/nsimosci_defconfig @@ -0,0 +1,75 @@ +CONFIG_CROSS_COMPILE="arc-elf32-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="ARCLinux" +# CONFIG_SWAP is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="../arc_initramfs" +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_KPROBES=y +CONFIG_MODULES=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARC_PLAT_FPGA_LEGACY=y +CONFIG_ARC_BOARD_ML509=y +# CONFIG_ARC_IDE is not set +# CONFIG_ARCTANGENT_EMAC is not set +# CONFIG_ARC_HAS_RTSC is not set +CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci" +# CONFIG_COMPACTION is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IPV6 is not set +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +# CONFIG_BLK_DEV is not set +CONFIG_NETDEVICES=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +# CONFIG_MOUSE_PS2_ALPS is not set +# CONFIG_MOUSE_PS2_LOGIPS2PP is not set +# CONFIG_MOUSE_PS2_SYNAPTICS is not set +# CONFIG_MOUSE_PS2_TRACKPOINT is not set +CONFIG_MOUSE_PS2_TOUCHKIT=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_ARC_PS2=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_ARC=y +CONFIG_SERIAL_ARC_CONSOLE=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +CONFIG_FB=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_HID is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_XZ_DEC=y diff --git a/arch/arc/configs/tb10x_defconfig b/arch/arc/configs/tb10x_defconfig new file mode 100644 index 000000000000..4fa5cd9f2202 --- /dev/null +++ b/arch/arc/configs/tb10x_defconfig @@ -0,0 +1,117 @@ +CONFIG_CROSS_COMPILE="arc-elf32-" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="tb10x" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="../tb10x-rootfs.cpio" +CONFIG_INITRAMFS_ROOT_UID=2100 +CONFIG_INITRAMFS_ROOT_GID=501 +# CONFIG_RD_GZIP is not set +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_AIO is not set +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLOCK is not set +CONFIG_ARC_PLAT_TB10X=y +CONFIG_ARC_CACHE_LINE_SHIFT=5 +# CONFIG_ARC_HAS_RTSC is not set +CONFIG_ARC_STACK_NONEXEC=y +CONFIG_HZ=250 +CONFIG_ARC_BUILTIN_DTB_NAME="abilis_tb100_dvk" +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_COMPACTION is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_PROC_DEVICETREE=y +CONFIG_NETDEVICES=y +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_DEBUG_FS=y +CONFIG_STMMAC_DA=y +CONFIG_STMMAC_CHAINED=y +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +CONFIG_SERIAL_8250_DW=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_GPIO_SYSFS=y +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=y +CONFIG_DMADEVICES=y +CONFIG_DW_DMAC=y +CONFIG_NET_DMA=y +CONFIG_ASYNC_TX_DMA=y +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +CONFIG_DEBUG_FS=y +CONFIG_HEADERS_CHECK=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index 48af742f8b5a..d8dd660898b9 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -32,7 +32,6 @@ generic-y += resource.h generic-y += scatterlist.h generic-y += sembuf.h generic-y += shmbuf.h -generic-y += shmparam.h generic-y += siginfo.h generic-y += socket.h generic-y += sockios.h diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 6632273861fd..d5555fe4742a 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -55,9 +55,6 @@ : "r"(data), "r"(ptr)); \ }) -/* used to give SHMLBA a value to avoid Cache Aliasing */ -extern unsigned int ARC_shmlba; - #define ARCH_DMA_MINALIGN L1_CACHE_BYTES /* diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h index 97ee96f26505..9f841af41092 100644 --- a/arch/arc/include/asm/cacheflush.h +++ b/arch/arc/include/asm/cacheflush.h @@ -19,13 +19,24 @@ #define _ASM_CACHEFLUSH_H #include <linux/mm.h> +#include <asm/shmparam.h> + +/* + * Semantically we need this because icache doesn't snoop dcache/dma. + * However ARC Cache flush requires paddr as well as vaddr, latter not available + * in the flush_icache_page() API. So we no-op it but do the equivalent work + * in update_mmu_cache() + */ +#define flush_icache_page(vma, page) void flush_cache_all(void); void flush_icache_range(unsigned long start, unsigned long end); -void flush_icache_page(struct vm_area_struct *vma, struct page *page); -void flush_icache_range_vaddr(unsigned long paddr, unsigned long u_vaddr, - int len); +void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len); +void __inv_icache_page(unsigned long paddr, unsigned long vaddr); +void ___flush_dcache_page(unsigned long paddr, unsigned long vaddr); +#define __flush_dcache_page(p, v) \ + ___flush_dcache_page((unsigned long)p, (unsigned long)v) #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 @@ -42,23 +53,60 @@ void dma_cache_wback(unsigned long start, unsigned long sz); #define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all() -/* - * VM callbacks when entire/range of user-space V-P mappings are - * torn-down/get-invalidated - * - * Currently we don't support D$ aliasing configs for our VIPT caches - * NOPS for VIPT Cache with non-aliasing D$ configurations only - */ -#define flush_cache_dup_mm(mm) /* called on fork */ +#define flush_cache_dup_mm(mm) /* called on fork (VIVT only) */ + +#ifndef CONFIG_ARC_CACHE_VIPT_ALIASING + #define flush_cache_mm(mm) /* called on munmap/exit */ #define flush_cache_range(mm, u_vstart, u_vend) #define flush_cache_page(vma, u_vaddr, pfn) /* PF handling/COW-break */ +#else /* VIPT aliasing dcache */ + +/* To clear out stale userspace mappings */ +void flush_cache_mm(struct mm_struct *mm); +void flush_cache_range(struct vm_area_struct *vma, + unsigned long start,unsigned long end); +void flush_cache_page(struct vm_area_struct *vma, + unsigned long user_addr, unsigned long page); + +/* + * To make sure that userspace mapping is flushed to memory before + * get_user_pages() uses a kernel mapping to access the page + */ +#define ARCH_HAS_FLUSH_ANON_PAGE +void flush_anon_page(struct vm_area_struct *vma, + struct page *page, unsigned long u_vaddr); + +#endif /* CONFIG_ARC_CACHE_VIPT_ALIASING */ + +/* + * Simple wrapper over config option + * Bootup code ensures that hardware matches kernel configuration + */ +static inline int cache_is_vipt_aliasing(void) +{ +#ifdef CONFIG_ARC_CACHE_VIPT_ALIASING + return 1; +#else + return 0; +#endif +} + +#define CACHE_COLOR(addr) (((unsigned long)(addr) >> (PAGE_SHIFT)) & 3) + +/* + * checks if two addresses (after page aligning) index into same cache set + */ +#define addr_not_cache_congruent(addr1, addr2) \ + cache_is_vipt_aliasing() ? \ + (CACHE_COLOR(addr1) != CACHE_COLOR(addr2)) : 0 \ + #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { \ memcpy(dst, src, len); \ if (vma->vm_flags & VM_EXEC) \ - flush_icache_range_vaddr((unsigned long)(dst), vaddr, len);\ + __sync_icache_dcache((unsigned long)(dst), vaddr, len); \ } while (0) #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 4c588f9820cf..57898a17eb82 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -9,7 +9,8 @@ #ifndef __ASM_ARC_IRQ_H #define __ASM_ARC_IRQ_H -#define NR_IRQS 32 +#define NR_CPU_IRQS 32 /* number of interrupt lines of ARC770 CPU */ +#define NR_IRQS 128 /* allow some CPU external IRQ handling */ /* Platform Independent IRQs */ #define TIMER0_IRQ 3 diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h index bdf546104551..374a35514116 100644 --- a/arch/arc/include/asm/page.h +++ b/arch/arc/include/asm/page.h @@ -16,13 +16,27 @@ #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) #define free_user_page(page, addr) free_page(addr) -/* TBD: for now don't worry about VIPT D$ aliasing */ #define clear_page(paddr) memset((paddr), 0, PAGE_SIZE) #define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) +#ifndef CONFIG_ARC_CACHE_VIPT_ALIASING + #define clear_user_page(addr, vaddr, pg) clear_page(addr) #define copy_user_page(vto, vfrom, vaddr, pg) copy_page(vto, vfrom) +#else /* VIPT aliasing dcache */ + +struct vm_area_struct; +struct page; + +#define __HAVE_ARCH_COPY_USER_HIGHPAGE + +void copy_user_highpage(struct page *to, struct page *from, + unsigned long u_vaddr, struct vm_area_struct *vma); +void clear_user_page(void *to, unsigned long u_vaddr, struct page *page); + +#endif /* CONFIG_ARC_CACHE_VIPT_ALIASING */ + #undef STRICT_MM_TYPECHECKS #ifdef STRICT_MM_TYPECHECKS diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index b7e36684c091..1cc4720faccb 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -395,6 +395,9 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, #include <asm-generic/pgtable.h> +/* to cope with aliasing VIPT cache */ +#define HAVE_ARCH_UNMAPPED_AREA + /* * No page table caches to initialise */ diff --git a/arch/arc/include/asm/serial.h b/arch/arc/include/asm/serial.h index 4dff5a1e4128..602b0970a764 100644 --- a/arch/arc/include/asm/serial.h +++ b/arch/arc/include/asm/serial.h @@ -22,4 +22,14 @@ #define BASE_BAUD (arc_get_core_freq() / 16) +/* + * This is definitely going to break early 8250 consoles on multi-platform + * images but hey, it won't add any code complexity for a debug feature of + * one broken driver. + */ +#ifdef CONFIG_ARC_PLAT_TB10X +#undef BASE_BAUD +#define BASE_BAUD (arc_get_core_freq() / 16 / 3) +#endif + #endif /* _ASM_ARC_SERIAL_H */ diff --git a/arch/arc/include/asm/shmparam.h b/arch/arc/include/asm/shmparam.h new file mode 100644 index 000000000000..fffeecc04270 --- /dev/null +++ b/arch/arc/include/asm/shmparam.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ARC_ASM_SHMPARAM_H +#define __ARC_ASM_SHMPARAM_H + +/* Handle upto 2 cache bins */ +#define SHMLBA (2 * PAGE_SIZE) + +/* Enforce SHMLBA in shmat */ +#define __ARCH_FORCE_SHMLBA + +#endif diff --git a/arch/arc/include/asm/tlb.h b/arch/arc/include/asm/tlb.h index 3eb2ce0bdfa3..85b6df839bd7 100644 --- a/arch/arc/include/asm/tlb.h +++ b/arch/arc/include/asm/tlb.h @@ -21,20 +21,35 @@ #ifndef __ASSEMBLY__ -#define tlb_flush(tlb) local_flush_tlb_mm((tlb)->mm) +#define tlb_flush(tlb) \ +do { \ + if (tlb->fullmm) \ + flush_tlb_mm((tlb)->mm); \ +} while (0) /* * This pair is called at time of munmap/exit to flush cache and TLB entries * for mappings being torn down. - * 1) cache-flush part -implemented via tlb_start_vma( ) can be NOP (for now) - * as we don't support aliasing configs in our VIPT D$. - * 2) tlb-flush part - implemted via tlb_end_vma( ) can be NOP as well- - * albiet for difft reasons - its better handled by moving to new ASID + * 1) cache-flush part -implemented via tlb_start_vma( ) for VIPT aliasing D$ + * 2) tlb-flush part - implemted via tlb_end_vma( ) flushes the TLB range * * Note, read http://lkml.org/lkml/2004/1/15/6 */ +#ifndef CONFIG_ARC_CACHE_VIPT_ALIASING #define tlb_start_vma(tlb, vma) -#define tlb_end_vma(tlb, vma) +#else +#define tlb_start_vma(tlb, vma) \ +do { \ + if (!tlb->fullmm) \ + flush_cache_range(vma, vma->vm_start, vma->vm_end); \ +} while(0) +#endif + +#define tlb_end_vma(tlb, vma) \ +do { \ + if (!tlb->fullmm) \ + flush_tlb_range(vma, vma->vm_start, vma->vm_end); \ +} while (0) #define __tlb_remove_tlb_entry(tlb, ptep, address) diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 0dc148ebce74..7dcda7025241 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -11,9 +11,9 @@ #include <linux/interrupt.h> #include <linux/thread_info.h> #include <linux/kbuild.h> +#include <linux/ptrace.h> #include <asm/hardirq.h> #include <asm/page.h> -#include <asm/ptrace.h> int main(void) { diff --git a/arch/arc/kernel/clk.c b/arch/arc/kernel/clk.c index 66ce0dc917fb..10c7b0b5a079 100644 --- a/arch/arc/kernel/clk.c +++ b/arch/arc/kernel/clk.c @@ -8,7 +8,7 @@ #include <asm/clk.h> -unsigned long core_freq = 800000000; +unsigned long core_freq = 80000000; /* * As of now we default to device-tree provided clock diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c index d14764ae2c60..b8a549c4f540 100644 --- a/arch/arc/kernel/disasm.c +++ b/arch/arc/kernel/disasm.c @@ -12,8 +12,8 @@ #include <linux/types.h> #include <linux/kprobes.h> #include <linux/slab.h> +#include <linux/uaccess.h> #include <asm/disasm.h> -#include <asm/uaccess.h> #if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \ defined(CONFIG_KPROBES) diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 91eeab81f52d..0c6d664d4a83 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -393,12 +393,14 @@ ARC_ENTRY EV_TLBProtV #ifdef CONFIG_ARC_MISALIGN_ACCESS SAVE_CALLEE_SAVED_USER mov r3, sp ; callee_regs -#endif bl do_misaligned_access -#ifdef CONFIG_ARC_MISALIGN_ACCESS - DISCARD_CALLEE_SAVED_USER + ; TBD: optimize - do this only if a callee reg was involved + ; either a dst of emulated LD/ST or src with address-writeback + RESTORE_CALLEE_SAVED_USER +#else + bl do_misaligned_error #endif b ret_from_exception diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index 551c10dff481..8115fa531575 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -11,6 +11,8 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/irqdomain.h> +#include <linux/irqchip.h> +#include "../../drivers/irqchip/irqchip.h" #include <asm/sections.h> #include <asm/irq.h> #include <asm/mach_desc.h> @@ -26,7 +28,7 @@ * -Disable all IRQs (on CPU side) * -Optionally, setup the High priority Interrupts as Level 2 IRQs */ -void __init arc_init_IRQ(void) +void __cpuinit arc_init_IRQ(void) { int level_mask = 0; @@ -97,15 +99,13 @@ static const struct irq_domain_ops arc_intc_domain_ops = { static struct irq_domain *root_domain; -void __init init_onchip_IRQ(void) +static int __init +init_onchip_IRQ(struct device_node *intc, struct device_node *parent) { - struct device_node *intc = NULL; + if (parent) + panic("DeviceTree incore intc not a root irq controller\n"); - intc = of_find_compatible_node(NULL, NULL, "snps,arc700-intc"); - if(!intc) - panic("DeviceTree Missing incore intc\n"); - - root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0, + root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0, &arc_intc_domain_ops, NULL); if (!root_domain) @@ -113,8 +113,12 @@ void __init init_onchip_IRQ(void) /* with this we don't need to export root_domain */ irq_set_default_host(root_domain); + + return 0; } +IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ); + /* * Late Interrupt system init called from start_kernel for Boot CPU only * @@ -123,12 +127,13 @@ void __init init_onchip_IRQ(void) */ void __init init_IRQ(void) { - init_onchip_IRQ(); - /* Any external intc can be setup here */ if (machine_desc->init_irq) machine_desc->init_irq(); + /* process the entire interrupt tree in one go */ + irqchip_init(); + #ifdef CONFIG_SMP /* Master CPU can initialize it's side of IPI */ if (machine_desc->init_smp) diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c index 3bfeacb674de..5a7b80e2d883 100644 --- a/arch/arc/kernel/kprobes.c +++ b/arch/arc/kernel/kprobes.c @@ -10,7 +10,6 @@ #include <linux/kprobes.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/kprobes.h> #include <linux/kdebug.h> #include <linux/sched.h> #include <linux/uaccess.h> diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c index cdd359352c0a..376e04622962 100644 --- a/arch/arc/kernel/module.c +++ b/arch/arc/kernel/module.c @@ -47,7 +47,7 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, } } #endif - return 0; + return 0; } void module_arch_cleanup(struct module *mod) @@ -141,5 +141,5 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, mod->arch.unw_info = unw; } #endif - return 0; + return 0; } diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 2d95ac07df7b..b2b3731dd1e9 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -14,14 +14,13 @@ #include <linux/module.h> #include <linux/cpu.h> #include <linux/of_fdt.h> +#include <linux/cache.h> #include <asm/sections.h> #include <asm/arcregs.h> #include <asm/tlb.h> -#include <asm/cache.h> #include <asm/setup.h> #include <asm/page.h> #include <asm/irq.h> -#include <asm/arcregs.h> #include <asm/prom.h> #include <asm/unwind.h> #include <asm/clk.h> @@ -32,14 +31,14 @@ int running_on_hw = 1; /* vs. on ISS */ char __initdata command_line[COMMAND_LINE_SIZE]; -struct machine_desc *machine_desc __initdata; +struct machine_desc *machine_desc __cpuinitdata; struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; -void __init read_arc_build_cfg_regs(void) +void __cpuinit read_arc_build_cfg_regs(void) { struct bcr_perip uncached_space; struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; @@ -238,7 +237,7 @@ char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) return buf; } -void __init arc_chk_ccms(void) +void __cpuinit arc_chk_ccms(void) { #if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM) struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; @@ -273,7 +272,7 @@ void __init arc_chk_ccms(void) * hardware has dedicated regs which need to be saved/restored on ctx-sw * (Single Precision uses core regs), thus kernel is kind of oblivious to it */ -void __init arc_chk_fpu(void) +void __cpuinit arc_chk_fpu(void) { struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; @@ -294,7 +293,7 @@ void __init arc_chk_fpu(void) * such as only for boot CPU etc */ -void __init setup_processor(void) +void __cpuinit setup_processor(void) { char str[512]; int cpu_id = smp_processor_id(); @@ -319,23 +318,20 @@ void __init setup_processor(void) void __init setup_arch(char **cmdline_p) { + /* This also populates @boot_command_line from /bootargs */ + machine_desc = setup_machine_fdt(__dtb_start); + if (!machine_desc) + panic("Embedded DT invalid\n"); + + /* Append any u-boot provided cmdline */ #ifdef CONFIG_CMDLINE_UBOOT - /* Make sure that a whitespace is inserted before */ - strlcat(command_line, " ", sizeof(command_line)); + /* Add a whitespace seperator between the 2 cmdlines */ + strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); + strlcat(boot_command_line, command_line, COMMAND_LINE_SIZE); #endif - /* - * Append .config cmdline to base command line, which might already - * contain u-boot "bootargs" (handled by head.S, if so configured) - */ - strlcat(command_line, CONFIG_CMDLINE, sizeof(command_line)); /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); - *cmdline_p = command_line; - - machine_desc = setup_machine_fdt(__dtb_start); - if (!machine_desc) - panic("Embedded DT invalid\n"); + *cmdline_p = boot_command_line; /* To force early parsing of things like mem=xxx */ parse_early_param(); diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index f13f72807aa5..09f4309aa2c0 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -33,7 +33,6 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/kernel.h> -#include <linux/interrupt.h> #include <linux/time.h> #include <linux/init.h> #include <linux/timex.h> diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 7496995371e8..0471d9c9dd54 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -16,11 +16,12 @@ #include <linux/sched.h> #include <linux/kdebug.h> #include <linux/uaccess.h> -#include <asm/ptrace.h> +#include <linux/ptrace.h> +#include <linux/kprobes.h> +#include <linux/kgdb.h> #include <asm/setup.h> -#include <asm/kprobes.h> #include <asm/unaligned.h> -#include <asm/kgdb.h> +#include <asm/kprobes.h> void __init trap_init(void) { @@ -83,6 +84,7 @@ DO_ERROR_INFO(SIGILL, "Invalid Extn Insn", do_extension_fault, ILL_ILLOPC) DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, ILL_ILLOPC) DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", do_memory_error, BUS_ADRERR) DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT) +DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) #ifdef CONFIG_ARC_MISALIGN_ACCESS /* @@ -91,21 +93,11 @@ DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT) int do_misaligned_access(unsigned long cause, unsigned long address, struct pt_regs *regs, struct callee_regs *cregs) { - if (misaligned_fixup(address, regs, cause, cregs) != 0) { - siginfo_t info; - - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRALN; - info.si_addr = (void __user *)address; - return handle_exception(cause, "Misaligned Access", regs, - &info); - } + if (misaligned_fixup(address, regs, cause, cregs) != 0) + return do_misaligned_error(cause, address, regs); + return 0; } - -#else -DO_ERROR_INFO(SIGSEGV, "Misaligned Access", do_misaligned_access, SEGV_ACCERR) #endif /* diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 0aec01985bf9..11c301b81c92 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -26,7 +26,6 @@ static noinline void print_reg_file(long *reg_rev, int start_num) char buf[512]; int n = 0, len = sizeof(buf); - /* weird loop because pt_regs regs rev r12..r0, r25..r13 */ for (i = start_num; i < start_num + 13; i++) { n += scnprintf(buf + n, len - n, "r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev); @@ -34,13 +33,18 @@ static noinline void print_reg_file(long *reg_rev, int start_num) if (((i + 1) % 3) == 0) n += scnprintf(buf + n, len - n, "\n"); + /* because pt_regs has regs reversed: r12..r0, r25..r13 */ reg_rev--; } if (start_num != 0) n += scnprintf(buf + n, len - n, "\n\n"); - pr_info("%s", buf); + /* To continue printing callee regs on same line as scratch regs */ + if (start_num == 0) + pr_info("%s", buf); + else + pr_cont("%s\n", buf); } static void show_callee_regs(struct callee_regs *cregs) @@ -83,6 +87,10 @@ static void show_faulting_vma(unsigned long address, char *buf) dev_t dev = 0; char *nm = buf; + /* can't use print_vma_addr() yet as it doesn't check for + * non-inclusive vma + */ + vma = find_vma(current->active_mm, address); /* check against the find_vma( ) behaviour which returns the next VMA @@ -98,10 +106,13 @@ static void show_faulting_vma(unsigned long address, char *buf) ino = inode->i_ino; } pr_info(" @off 0x%lx in [%s]\n" - " VMA: 0x%08lx to 0x%08lx\n\n", - address - vma->vm_start, nm, vma->vm_start, vma->vm_end); - } else + " VMA: 0x%08lx to 0x%08lx\n", + vma->vm_start < TASK_UNMAPPED_BASE ? + address : address - vma->vm_start, + nm, vma->vm_start, vma->vm_end); + } else { pr_info(" @No matching VMA found\n"); + } } static void show_ecr_verbose(struct pt_regs *regs) @@ -110,7 +121,7 @@ static void show_ecr_verbose(struct pt_regs *regs) unsigned long address; cause_reg = current->thread.cause_code; - pr_info("\n[ECR]: 0x%08x => ", cause_reg); + pr_info("\n[ECR ]: 0x%08x => ", cause_reg); /* For Data fault, this is data address not instruction addr */ address = current->thread.fault_address; @@ -120,7 +131,7 @@ static void show_ecr_verbose(struct pt_regs *regs) /* For DTLB Miss or ProtV, display the memory involved too */ if (vec == ECR_V_DTLB_MISS) { - pr_cont("Invalid (%s) @ 0x%08lx by insn @ 0x%08lx\n", + pr_cont("Invalid %s 0x%08lx by insn @ 0x%08lx\n", (cause_code == 0x01) ? "Read From" : ((cause_code == 0x02) ? "Write to" : "EX"), address, regs->ret); @@ -168,20 +179,23 @@ void show_regs(struct pt_regs *regs) if (current->thread.cause_code) show_ecr_verbose(regs); - pr_info("[EFA]: 0x%08lx\n", current->thread.fault_address); - pr_info("[ERET]: 0x%08lx (PC of Faulting Instr)\n", regs->ret); + pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n", + current->thread.fault_address, + (void *)regs->blink, (void *)regs->ret); - show_faulting_vma(regs->ret, buf); /* faulting code, not data */ + if (user_mode(regs)) + show_faulting_vma(regs->ret, buf); /* faulting code, not data */ - /* can't use print_vma_addr() yet as it doesn't check for - * non-inclusive vma - */ + pr_info("[STAT32]: 0x%08lx", regs->status32); + +#define STS_BIT(r, bit) r->status32 & STATUS_##bit##_MASK ? #bit : "" + if (!user_mode(regs)) + pr_cont(" : %2s %2s %2s %2s %2s\n", + STS_BIT(regs, AE), STS_BIT(regs, A2), STS_BIT(regs, A1), + STS_BIT(regs, E2), STS_BIT(regs, E1)); - /* print special regs */ - pr_info("status32: 0x%08lx\n", regs->status32); - pr_info(" SP: 0x%08lx\tFP: 0x%08lx\n", regs->sp, regs->fp); - pr_info("BTA: 0x%08lx\tBLINK: 0x%08lx\n", - regs->bta, regs->blink); + pr_info("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", + regs->bta, regs->sp, regs->fp); pr_info("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start, regs->lp_end, regs->lp_count); diff --git a/arch/arc/mm/Makefile b/arch/arc/mm/Makefile index 168dc146a8f6..ac95cc239c1e 100644 --- a/arch/arc/mm/Makefile +++ b/arch/arc/mm/Makefile @@ -7,4 +7,4 @@ # obj-y := extable.o ioremap.o dma.o fault.o init.o -obj-y += tlb.o tlbex.o cache_arc700.o +obj-y += tlb.o tlbex.o cache_arc700.o mmap.o diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 88d617d84234..2f12bca8aef3 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -68,20 +68,11 @@ #include <linux/mmu_context.h> #include <linux/syscalls.h> #include <linux/uaccess.h> +#include <linux/pagemap.h> #include <asm/cacheflush.h> #include <asm/cachectl.h> #include <asm/setup.h> - -#ifdef CONFIG_ARC_HAS_ICACHE -static void __ic_line_inv_no_alias(unsigned long, int); -static void __ic_line_inv_2_alias(unsigned long, int); -static void __ic_line_inv_4_alias(unsigned long, int); - -/* Holds the ptr to flush routine, dependign on size due to aliasing issues */ -static void (*___flush_icache_rtn) (unsigned long, int); -#endif - char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) { int n = 0; @@ -109,7 +100,7 @@ char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) * the cpuinfo structure for later use. * No Validation done here, simply read/convert the BCRs */ -void __init read_decode_cache_bcr(void) +void __cpuinit read_decode_cache_bcr(void) { struct bcr_cache ibcr, dbcr; struct cpuinfo_arc_cache *p_ic, *p_dc; @@ -141,13 +132,14 @@ void __init read_decode_cache_bcr(void) * 3. Enable the Caches, setup default flush mode for D-Cache * 3. Calculate the SHMLBA used by user space */ -void __init arc_cache_init(void) +void __cpuinit arc_cache_init(void) { unsigned int temp; unsigned int cpu = smp_processor_id(); struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache; int way_pg_ratio = way_pg_ratio; + int dcache_does_alias; char str[256]; printk(arc_cache_mumbojumbo(0, str, sizeof(str))); @@ -171,30 +163,6 @@ void __init arc_cache_init(void) } #endif - - /* - * if Cache way size is <= page size then no aliasing exhibited - * otherwise ratio determines num of aliases. - * e.g. 32K I$, 2 way set assoc, 8k pg size - * way-sz = 32k/2 = 16k - * way-pg-ratio = 16k/8k = 2, so 2 aliases possible - * (meaning 1 line could be in 2 possible locations). - */ - way_pg_ratio = ic->sz / ARC_ICACHE_WAYS / PAGE_SIZE; - switch (way_pg_ratio) { - case 0: - case 1: - ___flush_icache_rtn = __ic_line_inv_no_alias; - break; - case 2: - ___flush_icache_rtn = __ic_line_inv_2_alias; - break; - case 4: - ___flush_icache_rtn = __ic_line_inv_4_alias; - break; - default: - panic("Unsupported I-Cache Sz\n"); - } #endif /* Enable/disable I-Cache */ @@ -218,9 +186,13 @@ chk_dc: panic("Cache H/W doesn't match kernel Config"); } + dcache_does_alias = (dc->sz / ARC_DCACHE_WAYS) > PAGE_SIZE; + /* check for D-Cache aliasing */ - if ((dc->sz / ARC_DCACHE_WAYS) > PAGE_SIZE) - panic("D$ aliasing not handled right now\n"); + if (dcache_does_alias && !cache_is_vipt_aliasing()) + panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); + else if (!dcache_does_alias && cache_is_vipt_aliasing()) + panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n"); #endif /* Set the default Invalidate Mode to "simpy discard dirty lines" @@ -303,47 +275,57 @@ static inline void __dc_entire_op(const int cacheop) * Per Line Operation on D-Cache * Doesn't deal with type-of-op/IRQ-disabling/waiting-for-flush-to-complete * It's sole purpose is to help gcc generate ZOL + * (aliasing VIPT dcache flushing needs both vaddr and paddr) */ -static inline void __dc_line_loop(unsigned long start, unsigned long sz, - int aux_reg) +static inline void __dc_line_loop(unsigned long paddr, unsigned long vaddr, + unsigned long sz, const int aux_reg) { - int num_lines, slack; + int num_lines; /* Ensure we properly floor/ceil the non-line aligned/sized requests - * and have @start - aligned to cache line and integral @num_lines. + * and have @paddr - aligned to cache line and integral @num_lines. * This however can be avoided for page sized since: - * -@start will be cache-line aligned already (being page aligned) + * -@paddr will be cache-line aligned already (being page aligned) * -@sz will be integral multiple of line size (being page sized). */ if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) { - slack = start & ~DCACHE_LINE_MASK; - sz += slack; - start -= slack; + sz += paddr & ~DCACHE_LINE_MASK; + paddr &= DCACHE_LINE_MASK; + vaddr &= DCACHE_LINE_MASK; } num_lines = DIV_ROUND_UP(sz, ARC_DCACHE_LINE_LEN); +#if (CONFIG_ARC_MMU_VER <= 2) + paddr |= (vaddr >> PAGE_SHIFT) & 0x1F; +#endif + while (num_lines-- > 0) { #if (CONFIG_ARC_MMU_VER > 2) /* * Just as for I$, in MMU v3, D$ ops also require * "tag" bits in DC_PTAG, "index" bits in FLDL,IVDL ops - * But we pass phy addr for both. This works since Linux - * doesn't support aliasing configs for D$, yet. - * Thus paddr is enough to provide both tag and index. */ - write_aux_reg(ARC_REG_DC_PTAG, start); + write_aux_reg(ARC_REG_DC_PTAG, paddr); + + write_aux_reg(aux_reg, vaddr); + vaddr += ARC_DCACHE_LINE_LEN; +#else + /* paddr contains stuffed vaddrs bits */ + write_aux_reg(aux_reg, paddr); #endif - write_aux_reg(aux_reg, start); - start += ARC_DCACHE_LINE_LEN; + paddr += ARC_DCACHE_LINE_LEN; } } +/* For kernel mappings cache operation: index is same as paddr */ +#define __dc_line_op_k(p, sz, op) __dc_line_op(p, p, sz, op) + /* * D-Cache : Per Line INV (discard or wback+discard) or FLUSH (wback) */ -static inline void __dc_line_op(unsigned long start, unsigned long sz, - const int cacheop) +static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr, + unsigned long sz, const int cacheop) { unsigned long flags, tmp = tmp; int aux; @@ -366,7 +348,7 @@ static inline void __dc_line_op(unsigned long start, unsigned long sz, else aux = ARC_REG_DC_FLDL; - __dc_line_loop(start, sz, aux); + __dc_line_loop(paddr, vaddr, sz, aux); if (cacheop & OP_FLUSH) /* flush / flush-n-inv both wait */ wait_for_flush(); @@ -381,7 +363,8 @@ static inline void __dc_line_op(unsigned long start, unsigned long sz, #else #define __dc_entire_op(cacheop) -#define __dc_line_op(start, sz, cacheop) +#define __dc_line_op(paddr, vaddr, sz, cacheop) +#define __dc_line_op_k(paddr, sz, cacheop) #endif /* CONFIG_ARC_HAS_DCACHE */ @@ -391,75 +374,38 @@ static inline void __dc_line_op(unsigned long start, unsigned long sz, /* * I-Cache Aliasing in ARC700 VIPT caches * - * For fetching code from I$, ARC700 uses vaddr (embedded in program code) - * to "index" into SET of cache-line and paddr from MMU to match the TAG - * in the WAYS of SET. - * - * However the CDU iterface (to flush/inv) lines from software, only takes - * paddr (to have simpler hardware interface). For simpler cases, using paddr - * alone suffices. - * e.g. 2-way-set-assoc, 16K I$ (8k MMU pg sz, 32b cache line size): - * way_sz = cache_sz / num_ways = 16k/2 = 8k - * num_sets = way_sz / line_sz = 8k/32 = 256 => 8 bits - * Ignoring the bottom 5 bits corresp to the off within a 32b cacheline, - * bits req for calc set-index = bits 12:5 (0 based). Since this range fits - * inside the bottom 13 bits of paddr, which are same for vaddr and paddr - * (with 8k pg sz), paddr alone can be safely used by CDU to unambigously - * locate a cache-line. + * ARC VIPT I-cache uses vaddr to index into cache and paddr to match the tag. + * The orig Cache Management Module "CDU" only required paddr to invalidate a + * certain line since it sufficed as index in Non-Aliasing VIPT cache-geometry. + * Infact for distinct V1,V2,P: all of {V1-P},{V2-P},{P-P} would end up fetching + * the exact same line. * - * However for a difft sized cache, say 32k I$, above math yields need - * for 14 bits of vaddr to locate a cache line, which can't be provided by - * paddr, since the bit 13 (0 based) might differ between the two. - * - * This lack of extra bits needed for correct line addressing, defines the - * classical problem of Cache aliasing with VIPT architectures - * num_aliases = 1 << extra_bits - * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz => 2 aliases - * 2-way-set-assoc, 64K I$ with 8k MMU pg sz => 4 aliases - * 2-way-set-assoc, 16K I$ with 8k MMU pg sz => NO aliases + * However for larger Caches (way-size > page-size) - i.e. in Aliasing config, + * paddr alone could not be used to correctly index the cache. * * ------------------ * MMU v1/v2 (Fixed Page Size 8k) * ------------------ * The solution was to provide CDU with these additonal vaddr bits. These - * would be bits [x:13], x would depend on cache-geom. + * would be bits [x:13], x would depend on cache-geometry, 13 comes from + * standard page size of 8k. * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the * orig 5 bits of paddr were anyways ignored by CDU line ops, as they * represent the offset within cache-line. The adv of using this "clumsy" - * interface for additional info was no new reg was needed in CDU. + * interface for additional info was no new reg was needed in CDU programming + * model. * * 17:13 represented the max num of bits passable, actual bits needed were * fewer, based on the num-of-aliases possible. * -for 2 alias possibility, only bit 13 needed (32K cache) * -for 4 alias possibility, bits 14:13 needed (64K cache) * - * Since vaddr was not available for all instances of I$ flush req by core - * kernel, the only safe way (non-optimal though) was to kill all possible - * lines which could represent an alias (even if they didnt represent one - * in execution). - * e.g. for 64K I$, 4 aliases possible, so we did - * flush start - * flush start | 0x01 - * flush start | 0x2 - * flush start | 0x3 - * - * The penalty was invoking the operation itself, since tag match is anyways - * paddr based, a line which didn't represent an alias would not match the - * paddr, hence wont be killed - * - * Note that aliasing concerns are independent of line-sz for a given cache - * geometry (size + set_assoc) because the extra bits required by line-sz are - * reduced from the set calc. - * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz and using math above - * 32b line-sz: 9 bits set-index-calc, 5 bits offset-in-line => 1 extra bit - * 64b line-sz: 8 bits set-index-calc, 6 bits offset-in-line => 1 extra bit - * * ------------------ * MMU v3 * ------------------ - * This ver of MMU supports var page sizes (1k-16k) - Linux will support - * 8k (default), 16k and 4k. + * This ver of MMU supports variable page sizes (1k-16k): although Linux will + * only support 8k (default), 16k and 4k. * However from hardware perspective, smaller page sizes aggrevate aliasing * meaning more vaddr bits needed to disambiguate the cache-line-op ; * the existing scheme of piggybacking won't work for certain configurations. @@ -468,144 +414,53 @@ static inline void __dc_line_op(unsigned long start, unsigned long sz, */ /*********************************************************** - * Machine specific helpers for per line I-Cache invalidate. - * 3 routines to accpunt for 1, 2, 4 aliases possible + * Machine specific helper for per line I-Cache invalidate. */ - -static void __ic_line_inv_no_alias(unsigned long start, int num_lines) -{ - while (num_lines-- > 0) { -#if (CONFIG_ARC_MMU_VER > 2) - write_aux_reg(ARC_REG_IC_PTAG, start); -#endif - write_aux_reg(ARC_REG_IC_IVIL, start); - start += ARC_ICACHE_LINE_LEN; - } -} - -static void __ic_line_inv_2_alias(unsigned long start, int num_lines) -{ - while (num_lines-- > 0) { - -#if (CONFIG_ARC_MMU_VER > 2) - /* - * MMU v3, CDU prog model (for line ops) now uses a new IC_PTAG - * reg to pass the "tag" bits and existing IVIL reg only looks - * at bits relevant for "index" (details above) - * Programming Notes: - * -when writing tag to PTAG reg, bit chopping can be avoided, - * CDU ignores non-tag bits. - * -Ideally "index" must be computed from vaddr, but it is not - * avail in these rtns. So to be safe, we kill the lines in all - * possible indexes corresp to num of aliases possible for - * given cache config. - */ - write_aux_reg(ARC_REG_IC_PTAG, start); - write_aux_reg(ARC_REG_IC_IVIL, - start & ~(0x1 << PAGE_SHIFT)); - write_aux_reg(ARC_REG_IC_IVIL, start | (0x1 << PAGE_SHIFT)); -#else - write_aux_reg(ARC_REG_IC_IVIL, start); - write_aux_reg(ARC_REG_IC_IVIL, start | 0x01); -#endif - start += ARC_ICACHE_LINE_LEN; - } -} - -static void __ic_line_inv_4_alias(unsigned long start, int num_lines) -{ - while (num_lines-- > 0) { - -#if (CONFIG_ARC_MMU_VER > 2) - write_aux_reg(ARC_REG_IC_PTAG, start); - - write_aux_reg(ARC_REG_IC_IVIL, - start & ~(0x3 << PAGE_SHIFT)); - write_aux_reg(ARC_REG_IC_IVIL, - start & ~(0x2 << PAGE_SHIFT)); - write_aux_reg(ARC_REG_IC_IVIL, - start & ~(0x1 << PAGE_SHIFT)); - write_aux_reg(ARC_REG_IC_IVIL, start | (0x3 << PAGE_SHIFT)); -#else - write_aux_reg(ARC_REG_IC_IVIL, start); - write_aux_reg(ARC_REG_IC_IVIL, start | 0x01); - write_aux_reg(ARC_REG_IC_IVIL, start | 0x02); - write_aux_reg(ARC_REG_IC_IVIL, start | 0x03); -#endif - start += ARC_ICACHE_LINE_LEN; - } -} - -static void __ic_line_inv(unsigned long start, unsigned long sz) +static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, + unsigned long sz) { unsigned long flags; - int num_lines, slack; + int num_lines; /* - * Ensure we properly floor/ceil the non-line aligned/sized requests - * and have @start - aligned to cache line, and integral @num_lines + * Ensure we properly floor/ceil the non-line aligned/sized requests: * However page sized flushes can be compile time optimised. - * -@start will be cache-line aligned already (being page aligned) + * -@paddr will be cache-line aligned already (being page aligned) * -@sz will be integral multiple of line size (being page sized). */ if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) { - slack = start & ~ICACHE_LINE_MASK; - sz += slack; - start -= slack; + sz += paddr & ~ICACHE_LINE_MASK; + paddr &= ICACHE_LINE_MASK; + vaddr &= ICACHE_LINE_MASK; } num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN); - local_irq_save(flags); - (*___flush_icache_rtn) (start, num_lines); - local_irq_restore(flags); -} - -/* Unlike routines above, having vaddr for flush op (along with paddr), - * prevents the need to speculatively kill the lines in multiple sets - * based on ratio of way_sz : pg_sz - */ -static void __ic_line_inv_vaddr(unsigned long phy_start, - unsigned long vaddr, unsigned long sz) -{ - unsigned long flags; - int num_lines, slack; - unsigned int addr; - - slack = phy_start & ~ICACHE_LINE_MASK; - sz += slack; - phy_start -= slack; - num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN); - -#if (CONFIG_ARC_MMU_VER > 2) - vaddr &= ~ICACHE_LINE_MASK; - addr = phy_start; -#else +#if (CONFIG_ARC_MMU_VER <= 2) /* bits 17:13 of vaddr go as bits 4:0 of paddr */ - addr = phy_start | ((vaddr >> 13) & 0x1F); + paddr |= (vaddr >> PAGE_SHIFT) & 0x1F; #endif local_irq_save(flags); while (num_lines-- > 0) { #if (CONFIG_ARC_MMU_VER > 2) /* tag comes from phy addr */ - write_aux_reg(ARC_REG_IC_PTAG, addr); + write_aux_reg(ARC_REG_IC_PTAG, paddr); /* index bits come from vaddr */ write_aux_reg(ARC_REG_IC_IVIL, vaddr); vaddr += ARC_ICACHE_LINE_LEN; #else - /* this paddr contains vaddrs bits as needed */ - write_aux_reg(ARC_REG_IC_IVIL, addr); + /* paddr contains stuffed vaddrs bits */ + write_aux_reg(ARC_REG_IC_IVIL, paddr); #endif - addr += ARC_ICACHE_LINE_LEN; + paddr += ARC_ICACHE_LINE_LEN; } local_irq_restore(flags); } #else -#define __ic_line_inv(start, sz) #define __ic_line_inv_vaddr(pstart, vstart, sz) #endif /* CONFIG_ARC_HAS_ICACHE */ @@ -615,35 +470,72 @@ static void __ic_line_inv_vaddr(unsigned long phy_start, * Exported APIs */ -/* TBD: use pg_arch_1 to optimize this */ +/* + * Handle cache congruency of kernel and userspace mappings of page when kernel + * writes-to/reads-from + * + * The idea is to defer flushing of kernel mapping after a WRITE, possible if: + * -dcache is NOT aliasing, hence any U/K-mappings of page are congruent + * -U-mapping doesn't exist yet for page (finalised in update_mmu_cache) + * -In SMP, if hardware caches are coherent + * + * There's a corollary case, where kernel READs from a userspace mapped page. + * If the U-mapping is not congruent to to K-mapping, former needs flushing. + */ void flush_dcache_page(struct page *page) { - __dc_line_op((unsigned long)page_address(page), PAGE_SIZE, OP_FLUSH); + struct address_space *mapping; + + if (!cache_is_vipt_aliasing()) { + set_bit(PG_arch_1, &page->flags); + return; + } + + /* don't handle anon pages here */ + mapping = page_mapping(page); + if (!mapping) + return; + + /* + * pagecache page, file not yet mapped to userspace + * Make a note that K-mapping is dirty + */ + if (!mapping_mapped(mapping)) { + set_bit(PG_arch_1, &page->flags); + } else if (page_mapped(page)) { + + /* kernel reading from page with U-mapping */ + void *paddr = page_address(page); + unsigned long vaddr = page->index << PAGE_CACHE_SHIFT; + + if (addr_not_cache_congruent(paddr, vaddr)) + __flush_dcache_page(paddr, vaddr); + } } EXPORT_SYMBOL(flush_dcache_page); void dma_cache_wback_inv(unsigned long start, unsigned long sz) { - __dc_line_op(start, sz, OP_FLUSH_N_INV); + __dc_line_op_k(start, sz, OP_FLUSH_N_INV); } EXPORT_SYMBOL(dma_cache_wback_inv); void dma_cache_inv(unsigned long start, unsigned long sz) { - __dc_line_op(start, sz, OP_INV); + __dc_line_op_k(start, sz, OP_INV); } EXPORT_SYMBOL(dma_cache_inv); void dma_cache_wback(unsigned long start, unsigned long sz) { - __dc_line_op(start, sz, OP_FLUSH); + __dc_line_op_k(start, sz, OP_FLUSH); } EXPORT_SYMBOL(dma_cache_wback); /* - * This is API for making I/D Caches consistent when modifying code - * (loadable modules, kprobes, etc) + * This is API for making I/D Caches consistent when modifying + * kernel code (loadable modules, kprobes, kgdb...) * This is called on insmod, with kernel virtual address for CODE of * the module. ARC cache maintenance ops require PHY address thus we * need to convert vmalloc addr to PHY addr @@ -652,7 +544,6 @@ void flush_icache_range(unsigned long kstart, unsigned long kend) { unsigned int tot_sz, off, sz; unsigned long phy, pfn; - unsigned long flags; /* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */ @@ -673,8 +564,13 @@ void flush_icache_range(unsigned long kstart, unsigned long kend) /* Case: Kernel Phy addr (0x8000_0000 onwards) */ if (likely(kstart > PAGE_OFFSET)) { - __ic_line_inv(kstart, kend - kstart); - __dc_line_op(kstart, kend - kstart, OP_FLUSH); + /* + * The 2nd arg despite being paddr will be used to index icache + * This is OK since no alternate virtual mappings will exist + * given the callers for this case: kprobe/kgdb in built-in + * kernel code only. + */ + __sync_icache_dcache(kstart, kstart, kend - kstart); return; } @@ -692,42 +588,45 @@ void flush_icache_range(unsigned long kstart, unsigned long kend) pfn = vmalloc_to_pfn((void *)kstart); phy = (pfn << PAGE_SHIFT) + off; sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off); - local_irq_save(flags); - __dc_line_op(phy, sz, OP_FLUSH); - __ic_line_inv(phy, sz); - local_irq_restore(flags); + __sync_icache_dcache(phy, kstart, sz); kstart += sz; tot_sz -= sz; } } /* - * Optimised ver of flush_icache_range() with spec callers: ptrace/signals - * where vaddr is also available. This allows passing both vaddr and paddr - * bits to CDU for cache flush, short-circuting the current pessimistic algo - * which kills all possible aliases. - * An added adv of knowing that vaddr is user-vaddr avoids various checks - * and handling for k-vaddr, k-paddr as done in orig ver above + * General purpose helper to make I and D cache lines consistent. + * @paddr is phy addr of region + * @vaddr is typically user or kernel vaddr (vmalloc) + * Howver in one instance, flush_icache_range() by kprobe (for a breakpt in + * builtin kernel code) @vaddr will be paddr only, meaning CDU operation will + * use a paddr to index the cache (despite VIPT). This is fine since since a + * built-in kernel page will not have any virtual mappings (not even kernel) + * kprobe on loadable module is different as it will have kvaddr. */ -void flush_icache_range_vaddr(unsigned long paddr, unsigned long u_vaddr, - int len) +void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len) { - __ic_line_inv_vaddr(paddr, u_vaddr, len); - __dc_line_op(paddr, len, OP_FLUSH); + unsigned long flags; + + local_irq_save(flags); + __ic_line_inv_vaddr(paddr, vaddr, len); + __dc_line_op(paddr, vaddr, len, OP_FLUSH); + local_irq_restore(flags); +} + +/* wrapper to compile time eliminate alignment checks in flush loop */ +void __inv_icache_page(unsigned long paddr, unsigned long vaddr) +{ + __ic_line_inv_vaddr(paddr, vaddr, PAGE_SIZE); } /* - * XXX: This also needs to be optim using pg_arch_1 - * This is called when a page-cache page is about to be mapped into a - * user process' address space. It offers an opportunity for a - * port to ensure d-cache/i-cache coherency if necessary. + * wrapper to clearout kernel or userspace mappings of a page + * For kernel mappings @vaddr == @paddr */ -void flush_icache_page(struct vm_area_struct *vma, struct page *page) +void ___flush_dcache_page(unsigned long paddr, unsigned long vaddr) { - if (!(vma->vm_flags & VM_EXEC)) - return; - - __ic_line_inv((unsigned long)page_address(page), PAGE_SIZE); + __dc_line_op(paddr, vaddr & PAGE_MASK, PAGE_SIZE, OP_FLUSH_N_INV); } void flush_icache_all(void) @@ -756,6 +655,87 @@ noinline void flush_cache_all(void) } +#ifdef CONFIG_ARC_CACHE_VIPT_ALIASING + +void flush_cache_mm(struct mm_struct *mm) +{ + flush_cache_all(); +} + +void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr, + unsigned long pfn) +{ + unsigned int paddr = pfn << PAGE_SHIFT; + + __sync_icache_dcache(paddr, u_vaddr, PAGE_SIZE); +} + +void flush_cache_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + flush_cache_all(); +} + +void copy_user_highpage(struct page *to, struct page *from, + unsigned long u_vaddr, struct vm_area_struct *vma) +{ + void *kfrom = page_address(from); + void *kto = page_address(to); + int clean_src_k_mappings = 0; + + /* + * If SRC page was already mapped in userspace AND it's U-mapping is + * not congruent with K-mapping, sync former to physical page so that + * K-mapping in memcpy below, sees the right data + * + * Note that while @u_vaddr refers to DST page's userspace vaddr, it is + * equally valid for SRC page as well + */ + if (page_mapped(from) && addr_not_cache_congruent(kfrom, u_vaddr)) { + __flush_dcache_page(kfrom, u_vaddr); + clean_src_k_mappings = 1; + } + + copy_page(kto, kfrom); + + /* + * Mark DST page K-mapping as dirty for a later finalization by + * update_mmu_cache(). Although the finalization could have been done + * here as well (given that both vaddr/paddr are available). + * But update_mmu_cache() already has code to do that for other + * non copied user pages (e.g. read faults which wire in pagecache page + * directly). + */ + set_bit(PG_arch_1, &to->flags); + + /* + * if SRC was already usermapped and non-congruent to kernel mapping + * sync the kernel mapping back to physical page + */ + if (clean_src_k_mappings) { + __flush_dcache_page(kfrom, kfrom); + } else { + set_bit(PG_arch_1, &from->flags); + } +} + +void clear_user_page(void *to, unsigned long u_vaddr, struct page *page) +{ + clear_page(to); + set_bit(PG_arch_1, &page->flags); +} + +void flush_anon_page(struct vm_area_struct *vma, struct page *page, + unsigned long u_vaddr) +{ + /* TBD: do we really need to clear the kernel mapping */ + __flush_dcache_page(page_address(page), u_vaddr); + __flush_dcache_page(page_address(page), page_address(page)); + +} + +#endif + /********************************************************************** * Explicit Cache flush request from user space via syscall * Needed for JITs which generate code on the fly diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c index 014172ba8432..aa652e281324 100644 --- a/arch/arc/mm/extable.c +++ b/arch/arc/mm/extable.c @@ -27,7 +27,7 @@ int fixup_exception(struct pt_regs *regs) #ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE -long arc_copy_from_user_noinline(void *to, const void __user * from, +long arc_copy_from_user_noinline(void *to, const void __user *from, unsigned long n) { return __arc_copy_from_user(to, from, n); @@ -48,7 +48,7 @@ unsigned long arc_clear_user_noinline(void __user *to, } EXPORT_SYMBOL(arc_clear_user_noinline); -long arc_strncpy_from_user_noinline (char *dst, const char __user *src, +long arc_strncpy_from_user_noinline(char *dst, const char __user *src, long count) { return __arc_strncpy_from_user(dst, src, count); diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index af55aab803d2..689ffd86d5e9 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -12,7 +12,6 @@ #include <linux/sched.h> #include <linux/errno.h> #include <linux/ptrace.h> -#include <linux/version.h> #include <linux/uaccess.h> #include <linux/kdebug.h> #include <asm/pgalloc.h> diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c index 727d4794ea0f..4a177365b2c4 100644 --- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c @@ -10,9 +10,6 @@ #include <linux/mm.h> #include <linux/bootmem.h> #include <linux/memblock.h> -#ifdef CONFIG_BLOCK_DEV_RAM -#include <linux/blk.h> -#endif #include <linux/swap.h> #include <linux/module.h> #include <asm/page.h> diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c index 3e5c92c79936..739e65f355de 100644 --- a/arch/arc/mm/ioremap.c +++ b/arch/arc/mm/ioremap.c @@ -12,7 +12,7 @@ #include <linux/io.h> #include <linux/mm.h> #include <linux/slab.h> -#include <asm/cache.h> +#include <linux/cache.h> void __iomem *ioremap(unsigned long paddr, unsigned long size) { diff --git a/arch/arc/mm/mmap.c b/arch/arc/mm/mmap.c new file mode 100644 index 000000000000..2e06d56e987b --- /dev/null +++ b/arch/arc/mm/mmap.c @@ -0,0 +1,78 @@ +/* + * ARC700 mmap + * + * (started from arm version - for VIPT alias handling) + * + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/mman.h> +#include <linux/sched.h> +#include <asm/cacheflush.h> + +#define COLOUR_ALIGN(addr, pgoff) \ + ((((addr) + SHMLBA - 1) & ~(SHMLBA - 1)) + \ + (((pgoff) << PAGE_SHIFT) & (SHMLBA - 1))) + +/* + * Ensure that shared mappings are correctly aligned to + * avoid aliasing issues with VIPT caches. + * We need to ensure that + * a specific page of an object is always mapped at a multiple of + * SHMLBA bytes. + */ +unsigned long +arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + int do_align = 0; + int aliasing = cache_is_vipt_aliasing(); + struct vm_unmapped_area_info info; + + /* + * We only need to do colour alignment if D cache aliases. + */ + if (aliasing) + do_align = filp || (flags & MAP_SHARED); + + /* + * We enforce the MAP_FIXED case. + */ + if (flags & MAP_FIXED) { + if (aliasing && flags & MAP_SHARED && + (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) + return -EINVAL; + return addr; + } + + if (len > TASK_SIZE) + return -ENOMEM; + + if (addr) { + if (do_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } + + info.flags = 0; + info.length = len; + info.low_limit = mm->mmap_base; + info.high_limit = TASK_SIZE; + info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; + info.align_offset = pgoff << PAGE_SHIFT; + return vm_unmapped_area(&info); +} diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 9b9ce23f4ec3..066145b5f348 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -418,23 +418,52 @@ void create_tlb(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) local_irq_restore(flags); } -/* arch hook called by core VM at the end of handle_mm_fault( ), - * when a new PTE is entered in Page Tables or an existing one - * is modified. We aggresively pre-install a TLB entry +/* + * Called at the end of pagefault, for a userspace mapped page + * -pre-install the corresponding TLB entry into MMU + * -Finalize the delayed D-cache flush of kernel mapping of page due to + * flush_dcache_page(), copy_user_page() + * + * Note that flush (when done) involves both WBACK - so physical page is + * in sync as well as INV - so any non-congruent aliases don't remain */ - -void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddress, +void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, pte_t *ptep) { + unsigned long vaddr = vaddr_unaligned & PAGE_MASK; + unsigned long paddr = pte_val(*ptep) & PAGE_MASK; + + create_tlb(vma, vaddr, ptep); + + /* + * Exec page : Independent of aliasing/page-color considerations, + * since icache doesn't snoop dcache on ARC, any dirty + * K-mapping of a code page needs to be wback+inv so that + * icache fetch by userspace sees code correctly. + * !EXEC page: If K-mapping is NOT congruent to U-mapping, flush it + * so userspace sees the right data. + * (Avoids the flush for Non-exec + congruent mapping case) + */ + if (vma->vm_flags & VM_EXEC || addr_not_cache_congruent(paddr, vaddr)) { + struct page *page = pfn_to_page(pte_pfn(*ptep)); + + int dirty = test_and_clear_bit(PG_arch_1, &page->flags); + if (dirty) { + /* wback + inv dcache lines */ + __flush_dcache_page(paddr, paddr); - create_tlb(vma, vaddress, ptep); + /* invalidate any existing icache lines */ + if (vma->vm_flags & VM_EXEC) + __inv_icache_page(paddr, vaddr); + } + } } /* Read the Cache Build Confuration Registers, Decode them and save into * the cpuinfo structure for later use. * No Validation is done here, simply read/convert the BCRs */ -void __init read_decode_mmu_bcr(void) +void __cpuinit read_decode_mmu_bcr(void) { unsigned int tmp; struct bcr_mmu_1_2 *mmu2; /* encoded MMU2 attr */ @@ -466,7 +495,7 @@ void __init read_decode_mmu_bcr(void) char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len) { int n = 0; - struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[smp_processor_id()].mmu; + struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu; n += scnprintf(buf + n, len - n, "ARC700 MMU [v%x]\t: %dk PAGE, ", p_mmu->ver, TO_KB(p_mmu->pg_sz)); @@ -480,7 +509,7 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len) return buf; } -void __init arc_mmu_init(void) +void __cpuinit arc_mmu_init(void) { char str[256]; struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c index 4e20a1a5104d..b3700c064c06 100644 --- a/arch/arc/plat-arcfpga/platform.c +++ b/arch/arc/plat-arcfpga/platform.c @@ -224,3 +224,15 @@ MACHINE_START(ML509, "ml509") .init_smp = iss_model_init_smp, #endif MACHINE_END + +static const char *nsimosci_compat[] __initdata = { + "snps,nsimosci", + NULL, +}; + +MACHINE_START(NSIMOSCI, "nsimosci") + .dt_compat = nsimosci_compat, + .init_early = NULL, + .init_machine = plat_fpga_populate_dev, + .init_irq = NULL, +MACHINE_END diff --git a/arch/arc/plat-tb10x/Kconfig b/arch/arc/plat-tb10x/Kconfig new file mode 100644 index 000000000000..1d3452100f1f --- /dev/null +++ b/arch/arc/plat-tb10x/Kconfig @@ -0,0 +1,29 @@ +# Abilis Systems TB10x platform kernel configuration file +# +# Author: Christian Ruppert <christian.ruppert@abilis.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +menuconfig ARC_PLAT_TB10X + bool "Abilis TB10x" + select COMMON_CLK + select PINCTRL + select PINMUX + select ARCH_REQUIRE_GPIOLIB + help + Support for platforms based on the TB10x home media gateway SOC by + Abilis Systems. TB10x is based on the ARC700 CPU architecture. + Say Y if you are building a kernel for one of the SOCs in this + series (e.g. TB100 or TB101). If in doubt say N. diff --git a/arch/arc/plat-tb10x/Makefile b/arch/arc/plat-tb10x/Makefile new file mode 100644 index 000000000000..89611d25ef35 --- /dev/null +++ b/arch/arc/plat-tb10x/Makefile @@ -0,0 +1,21 @@ +# Abilis Systems TB10x platform Makefile +# +# Author: Christian Ruppert <christian.ruppert@abilis.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +KBUILD_CFLAGS += -Iarch/arc/plat-tb10x/include + +obj-y += tb10x.o diff --git a/arch/arc/plat-tb10x/tb10x.c b/arch/arc/plat-tb10x/tb10x.c new file mode 100644 index 000000000000..d3567691c7e1 --- /dev/null +++ b/arch/arc/plat-tb10x/tb10x.c @@ -0,0 +1,71 @@ +/* + * Abilis Systems TB10x platform initialisation + * + * Copyright (C) Abilis Systems 2012 + * + * Author: Christian Ruppert <christian.ruppert@abilis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include <linux/init.h> +#include <linux/of_platform.h> +#include <linux/clk-provider.h> +#include <linux/pinctrl/consumer.h> + +#include <asm/mach_desc.h> + + +static void __init tb10x_platform_init(void) +{ + of_clk_init(NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static void __init tb10x_platform_late_init(void) +{ + struct device_node *dn; + + /* + * Pinctrl documentation recommends setting up the iomux here for + * all modules which don't require control over the pins themselves. + * Modules which need this kind of assistance are compatible with + * "abilis,simple-pinctrl", i.e. we can easily iterate over them. + * TODO: Does this recommended method work cleanly with pins required + * by modules? + */ + for_each_compatible_node(dn, NULL, "abilis,simple-pinctrl") { + struct platform_device *pd = of_find_device_by_node(dn); + struct pinctrl *pctl; + + pctl = pinctrl_get_select(&pd->dev, "abilis,simple-default"); + if (IS_ERR(pctl)) { + int ret = PTR_ERR(pctl); + dev_err(&pd->dev, "Could not set up pinctrl: %d\n", + ret); + } + } +} + +static const char *tb10x_compat[] __initdata = { + "abilis,arc-tb10x", + NULL, +}; + +MACHINE_START(TB10x, "tb10x") + .dt_compat = tb10x_compat, + .init_machine = tb10x_platform_init, + .init_late = tb10x_platform_late_init, +MACHINE_END diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1e31dac36a5f..49d993cee512 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -38,6 +38,7 @@ config ARM select HAVE_GENERIC_HARDIRQS select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)) select HAVE_IDE if PCI || ISA || PCMCIA + select HAVE_IRQ_TIME_ACCOUNTING select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZMA select HAVE_KERNEL_LZO @@ -109,9 +110,6 @@ config MIGHT_HAVE_PCI config SYS_SUPPORTS_APM_EMULATION bool -config GENERIC_GPIO - bool - config HAVE_TCM bool select GENERIC_ALLOCATOR @@ -491,13 +489,14 @@ config ARCH_IXP4XX config ARCH_DOVE bool "Marvell Dove" select ARCH_REQUIRE_GPIOLIB - select CPU_V7 + select CPU_PJ4 select GENERIC_CLOCKEVENTS select MIGHT_HAVE_PCI select PINCTRL select PINCTRL_DOVE select PLAT_ORION_LEGACY select USB_ARCH_HAS_EHCI + select MVEBU_MBUS help Support for the Marvell Dove SoC 88AP510 @@ -511,6 +510,7 @@ config ARCH_KIRKWOOD select PINCTRL select PINCTRL_KIRKWOOD select PLAT_ORION_LEGACY + select MVEBU_MBUS help Support for the following Marvell Kirkwood series SoCs: 88F6180, 88F6192 and 88F6281. @@ -522,6 +522,7 @@ config ARCH_MV78XX0 select GENERIC_CLOCKEVENTS select PCI select PLAT_ORION_LEGACY + select MVEBU_MBUS help Support for the following Marvell MV78xx0 series SoCs: MV781x0, MV782x0. @@ -534,6 +535,7 @@ config ARCH_ORION5X select GENERIC_CLOCKEVENTS select PCI select PLAT_ORION_LEGACY + select MVEBU_MBUS help Support for the following Marvell Orion 5x series SoCs: Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182), @@ -643,7 +645,7 @@ config ARCH_SHMOBILE select MULTI_IRQ_HANDLER select NEED_MACH_MEMORY_H select NO_IOPORT - select PINCTRL + select PINCTRL if ARCH_WANT_OPTIONAL_GPIOLIB select PM_GENERIC_DOMAINS if PM select SPARSE_IRQ help @@ -896,7 +898,6 @@ config ARCH_MULTI_V7 bool "ARMv7 based platforms (Cortex-A, PJ4, Scorpion, Krait)" default y select ARCH_MULTI_V6_V7 - select ARCH_VEXPRESS select CPU_V7 config ARCH_MULTI_V6_V7 @@ -1055,6 +1056,7 @@ config PLAT_VERSATILE config ARM_TIMER_SP804 bool select CLKSRC_MMIO + select CLKSRC_OF if OF source arch/arm/mm/Kconfig @@ -1789,6 +1791,7 @@ config XEN depends on ARM && AEABI && OF depends on CPU_V7 && !CPU_V6 depends on !GENERIC_ATOMIC64 + select ARM_PSCI help Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index f57a6ba26e04..1d41908d5cda 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -245,11 +245,11 @@ choice on i.MX53. config DEBUG_IMX6Q_UART - bool "i.MX6Q Debug UART" + bool "i.MX6Q/DL Debug UART" depends on SOC_IMX6Q help Say Y here if you want kernel low-level debugging support - on i.MX6Q. + on i.MX6Q/DL. config DEBUG_MMP_UART2 bool "Kernel low-level debugging message via MMP UART2" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 47374085befd..1ba358ba16b8 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -309,7 +309,7 @@ define archhelp echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)' echo '* xipImage - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)' echo ' uImage - U-Boot wrapped zImage' - echo ' bootpImage - Combined zImage and initial RAM disk' + echo ' bootpImage - Combined zImage and initial RAM disk' echo ' (supply initrd image via make variable INITRD=<path>)' echo '* dtbs - Build device tree blobs for enabled boards' echo ' install - Install uncompressed kernel' diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 853e199ea89f..b9f7121e6ecf 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -49,10 +49,12 @@ dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ exynos4210-smdkv310.dtb \ exynos4210-trats.dtb \ + exynos4210-universal_c210.dtb \ exynos4412-odroidx.dtb \ exynos4412-smdk4412.dtb \ exynos4412-origen.dtb \ exynos5250-arndale.dtb \ + exynos5440-sd5v1.dtb \ exynos5250-smdk5250.dtb \ exynos5250-snow.dtb \ exynos5440-ssdk5440.dtb @@ -134,10 +136,14 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \ imx28-tx28.dtb dtb-$(CONFIG_ARCH_NOMADIK) += ste-nomadik-s8815.dtb dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ + omap3430-sdp.dtb \ omap3-beagle.dtb \ + omap3-devkit8000.dtb \ omap3-beagle-xm.dtb \ omap3-evm.dtb \ omap3-tobi.dtb \ + omap3-igep0020.dtb \ + omap3-igep0030.dtb \ omap4-panda.dtb \ omap4-panda-a4.dtb \ omap4-panda-es.dtb \ @@ -155,9 +161,12 @@ dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \ ccu9540.dtb dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \ r8a7740-armadillo800eva.dtb \ + r8a7778-bockw.dtb \ r8a7779-marzen-reference.dtb \ + r8a7790-lager.dtb \ sh73a0-kzm9g.dtb \ sh73a0-kzm9g-reference.dtb \ + r8a73a4-ape6evm.dtb \ sh7372-mackerel.dtb dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5.dtb \ socfpga_vt.dtb @@ -186,11 +195,13 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ tegra30-cardhu-a04.dtb \ tegra114-dalmore.dtb \ tegra114-pluto.dtb +dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \ + versatile-pb.dtb dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \ - vexpress-v2p-ca15_a7.dtb \ - xenvm-4.2.dtb + vexpress-v2p-ca15_a7.dtb +dtb-$(CONFIG_ARCH_VIRT) += xenvm-4.2.dtb dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ wm8505-ref.dtb \ wm8650-mid.dtb \ diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts index 11b240c5d323..5302f79c05b7 100644 --- a/arch/arm/boot/dts/am335x-bone.dts +++ b/arch/arm/boot/dts/am335x-bone.dts @@ -43,7 +43,7 @@ status = "okay"; }; - i2c1: i2c@44e0b000 { + i2c0: i2c@44e0b000 { status = "okay"; clock-frequency = <400000>; @@ -59,27 +59,27 @@ led@2 { label = "beaglebone:green:heartbeat"; - gpios = <&gpio2 21 0>; + gpios = <&gpio1 21 0>; linux,default-trigger = "heartbeat"; default-state = "off"; }; led@3 { label = "beaglebone:green:mmc0"; - gpios = <&gpio2 22 0>; + gpios = <&gpio1 22 0>; linux,default-trigger = "mmc0"; default-state = "off"; }; led@4 { label = "beaglebone:green:usr2"; - gpios = <&gpio2 23 0>; + gpios = <&gpio1 23 0>; default-state = "off"; }; led@5 { label = "beaglebone:green:usr3"; - gpios = <&gpio2 24 0>; + gpios = <&gpio1 24 0>; default-state = "off"; }; }; diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts index d6496440fcea..0423298a26fe 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/am335x-evm.dts @@ -51,7 +51,7 @@ status = "okay"; }; - i2c1: i2c@44e0b000 { + i2c0: i2c@44e0b000 { status = "okay"; clock-frequency = <400000>; @@ -60,7 +60,7 @@ }; }; - i2c2: i2c@4802a000 { + i2c1: i2c@4802a000 { status = "okay"; clock-frequency = <100000>; @@ -123,12 +123,12 @@ debounce-delay-ms = <5>; col-scan-delay-us = <2>; - row-gpios = <&gpio2 25 0 /* Bank1, pin25 */ - &gpio2 26 0 /* Bank1, pin26 */ - &gpio2 27 0>; /* Bank1, pin27 */ + row-gpios = <&gpio1 25 0 /* Bank1, pin25 */ + &gpio1 26 0 /* Bank1, pin26 */ + &gpio1 27 0>; /* Bank1, pin27 */ - col-gpios = <&gpio2 21 0 /* Bank1, pin21 */ - &gpio2 22 0>; /* Bank1, pin22 */ + col-gpios = <&gpio1 21 0 /* Bank1, pin21 */ + &gpio1 22 0>; /* Bank1, pin22 */ linux,keymap = <0x0000008b /* MENU */ 0x0100009e /* BACK */ @@ -147,14 +147,14 @@ switch@9 { label = "volume-up"; linux,code = <115>; - gpios = <&gpio1 2 1>; + gpios = <&gpio0 2 1>; gpio-key,wakeup; }; switch@10 { label = "volume-down"; linux,code = <114>; - gpios = <&gpio1 3 1>; + gpios = <&gpio0 3 1>; gpio-key,wakeup; }; }; diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index f5a6162a4ff2..f67c360844f4 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -58,7 +58,7 @@ status = "okay"; }; - i2c1: i2c@44e0b000 { + i2c0: i2c@44e0b000 { status = "okay"; clock-frequency = <400000>; @@ -115,26 +115,26 @@ led@1 { label = "evmsk:green:usr0"; - gpios = <&gpio2 4 0>; + gpios = <&gpio1 4 0>; default-state = "off"; }; led@2 { label = "evmsk:green:usr1"; - gpios = <&gpio2 5 0>; + gpios = <&gpio1 5 0>; default-state = "off"; }; led@3 { label = "evmsk:green:mmc0"; - gpios = <&gpio2 6 0>; + gpios = <&gpio1 6 0>; linux,default-trigger = "mmc0"; default-state = "off"; }; led@4 { label = "evmsk:green:heartbeat"; - gpios = <&gpio2 7 0>; + gpios = <&gpio1 7 0>; linux,default-trigger = "heartbeat"; default-state = "off"; }; @@ -148,26 +148,26 @@ switch@1 { label = "button0"; linux,code = <0x100>; - gpios = <&gpio3 3 0>; + gpios = <&gpio2 3 0>; }; switch@2 { label = "button1"; linux,code = <0x101>; - gpios = <&gpio3 2 0>; + gpios = <&gpio2 2 0>; }; switch@3 { label = "button2"; linux,code = <0x102>; - gpios = <&gpio1 30 0>; + gpios = <&gpio0 30 0>; gpio-key,wakeup; }; switch@4 { label = "button3"; linux,code = <0x103>; - gpios = <&gpio3 5 0>; + gpios = <&gpio2 5 0>; }; }; }; diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 91fe4f148f80..1460d9b88adf 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -21,6 +21,8 @@ serial3 = &uart4; serial4 = &uart5; serial5 = &uart6; + d_can0 = &dcan0; + d_can1 = &dcan1; }; cpus { @@ -87,7 +89,7 @@ reg = <0x48200000 0x1000>; }; - gpio1: gpio@44e07000 { + gpio0: gpio@44e07000 { compatible = "ti,omap4-gpio"; ti,hwmods = "gpio1"; gpio-controller; @@ -98,7 +100,7 @@ interrupts = <96>; }; - gpio2: gpio@4804c000 { + gpio1: gpio@4804c000 { compatible = "ti,omap4-gpio"; ti,hwmods = "gpio2"; gpio-controller; @@ -109,7 +111,7 @@ interrupts = <98>; }; - gpio3: gpio@481ac000 { + gpio2: gpio@481ac000 { compatible = "ti,omap4-gpio"; ti,hwmods = "gpio3"; gpio-controller; @@ -120,7 +122,7 @@ interrupts = <32>; }; - gpio4: gpio@481ae000 { + gpio3: gpio@481ae000 { compatible = "ti,omap4-gpio"; ti,hwmods = "gpio4"; gpio-controller; @@ -185,7 +187,7 @@ status = "disabled"; }; - i2c1: i2c@44e0b000 { + i2c0: i2c@44e0b000 { compatible = "ti,omap4-i2c"; #address-cells = <1>; #size-cells = <0>; @@ -195,7 +197,7 @@ status = "disabled"; }; - i2c2: i2c@4802a000 { + i2c1: i2c@4802a000 { compatible = "ti,omap4-i2c"; #address-cells = <1>; #size-cells = <0>; @@ -205,7 +207,7 @@ status = "disabled"; }; - i2c3: i2c@4819c000 { + i2c2: i2c@4819c000 { compatible = "ti,omap4-i2c"; #address-cells = <1>; #size-cells = <0>; @@ -225,7 +227,8 @@ dcan0: d_can@481cc000 { compatible = "bosch,d_can"; ti,hwmods = "d_can0"; - reg = <0x481cc000 0x2000>; + reg = <0x481cc000 0x2000 + 0x44e10644 0x4>; interrupts = <52>; status = "disabled"; }; @@ -233,13 +236,14 @@ dcan1: d_can@481d0000 { compatible = "bosch,d_can"; ti,hwmods = "d_can1"; - reg = <0x481d0000 0x2000>; + reg = <0x481d0000 0x2000 + 0x44e10644 0x4>; interrupts = <55>; status = "disabled"; }; timer1: timer@44e31000 { - compatible = "ti,omap2-timer"; + compatible = "ti,am335x-timer-1ms"; reg = <0x44e31000 0x400>; interrupts = <67>; ti,hwmods = "timer1"; @@ -247,21 +251,21 @@ }; timer2: timer@48040000 { - compatible = "ti,omap2-timer"; + compatible = "ti,am335x-timer"; reg = <0x48040000 0x400>; interrupts = <68>; ti,hwmods = "timer2"; }; timer3: timer@48042000 { - compatible = "ti,omap2-timer"; + compatible = "ti,am335x-timer"; reg = <0x48042000 0x400>; interrupts = <69>; ti,hwmods = "timer3"; }; timer4: timer@48044000 { - compatible = "ti,omap2-timer"; + compatible = "ti,am335x-timer"; reg = <0x48044000 0x400>; interrupts = <92>; ti,hwmods = "timer4"; @@ -269,7 +273,7 @@ }; timer5: timer@48046000 { - compatible = "ti,omap2-timer"; + compatible = "ti,am335x-timer"; reg = <0x48046000 0x400>; interrupts = <93>; ti,hwmods = "timer5"; @@ -277,7 +281,7 @@ }; timer6: timer@48048000 { - compatible = "ti,omap2-timer"; + compatible = "ti,am335x-timer"; reg = <0x48048000 0x400>; interrupts = <94>; ti,hwmods = "timer6"; @@ -285,7 +289,7 @@ }; timer7: timer@4804a000 { - compatible = "ti,omap2-timer"; + compatible = "ti,am335x-timer"; reg = <0x4804a000 0x400>; interrupts = <95>; ti,hwmods = "timer7"; @@ -305,7 +309,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x48030000 0x400>; - interrupt = <65>; + interrupts = <65>; ti,spi-num-cs = <2>; ti,hwmods = "spi0"; status = "disabled"; @@ -316,7 +320,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x481a0000 0x400>; - interrupt = <125>; + interrupts = <125>; ti,spi-num-cs = <2>; ti,hwmods = "spi1"; status = "disabled"; @@ -399,5 +403,17 @@ 0x44d80000 0x2000>; /* M3 DMEM */ ti,hwmods = "wkup_m3"; }; + + gpmc: gpmc@50000000 { + compatible = "ti,am3352-gpmc"; + ti,hwmods = "gpmc"; + reg = <0x50000000 0x2000>; + interrupts = <100>; + num-cs = <7>; + num-waitpins = <2>; + #address-cells = <2>; + #size-cells = <1>; + status = "disabled"; + }; }; }; diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/am3517-evm.dts index 474f760ecadf..e9b5bdae4908 100644 --- a/arch/arm/boot/dts/am3517-evm.dts +++ b/arch/arm/boot/dts/am3517-evm.dts @@ -7,7 +7,7 @@ */ /dts-v1/; -/include/ "omap3.dtsi" +/include/ "omap34xx.dtsi" / { model = "TI AM3517 EVM (AM3517/05)"; diff --git a/arch/arm/boot/dts/am3517_mt_ventoux.dts b/arch/arm/boot/dts/am3517_mt_ventoux.dts index 5eb26d7d9b4e..556868388a23 100644 --- a/arch/arm/boot/dts/am3517_mt_ventoux.dts +++ b/arch/arm/boot/dts/am3517_mt_ventoux.dts @@ -7,7 +7,7 @@ */ /dts-v1/; -/include/ "omap3.dtsi" +/include/ "omap34xx.dtsi" / { model = "TeeJet Mt.Ventoux"; diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 6403acdbb75f..2353b1f13704 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts @@ -30,85 +30,87 @@ }; soc { - serial@d0012000 { - clock-frequency = <200000000>; - status = "okay"; - }; - sata@d00a0000 { - nr-ports = <2>; - status = "okay"; - }; - - mdio { - phy0: ethernet-phy@0 { - reg = <0>; + internal-regs { + serial@12000 { + clock-frequency = <200000000>; + status = "okay"; }; - - phy1: ethernet-phy@1 { - reg = <1>; + sata@a0000 { + nr-ports = <2>; + status = "okay"; }; - }; - ethernet@d0070000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "rgmii-id"; - }; - ethernet@d0074000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "rgmii-id"; - }; + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; - mvsdio@d00d4000 { - pinctrl-0 = <&sdio_pins1>; - pinctrl-names = "default"; - /* - * This device is disabled by default, because - * using the SD card connector requires - * changing the default CON40 connector - * "DB-88F6710_MPP_2xRGMII_DEVICE_Jumper" to a - * different connector - * "DB-88F6710_MPP_RGMII_SD_Jumper". - */ - status = "disabled"; - /* No CD or WP GPIOs */ - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; - usb@d0050000 { - status = "okay"; - }; + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + ethernet@74000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; - usb@d0051000 { - status = "okay"; - }; + mvsdio@d4000 { + pinctrl-0 = <&sdio_pins1>; + pinctrl-names = "default"; + /* + * This device is disabled by default, because + * using the SD card connector requires + * changing the default CON40 connector + * "DB-88F6710_MPP_2xRGMII_DEVICE_Jumper" to a + * different connector + * "DB-88F6710_MPP_RGMII_SD_Jumper". + */ + status = "disabled"; + /* No CD or WP GPIOs */ + }; - spi0: spi@d0010600 { - status = "okay"; + usb@50000 { + status = "okay"; + }; - spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "mx25l25635e"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <50000000>; + usb@51000 { + status = "okay"; }; - }; - pcie-controller { - status = "okay"; - /* - * The two PCIe units are accessible through - * both standard PCIe slots and mini-PCIe - * slots on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ + spi0: spi@10600 { status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l25635e"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + }; }; - pcie@2,0 { - /* Port 1, Lane 0 */ + + pcie-controller { status = "okay"; + /* + * The two PCIe units are accessible through + * both standard PCIe slots and mini-PCIe + * slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts index 58ee79372206..14e36e19d515 100644 --- a/arch/arm/boot/dts/armada-370-mirabox.dts +++ b/arch/arm/boot/dts/armada-370-mirabox.dts @@ -25,113 +25,115 @@ }; soc { - serial@d0012000 { - clock-frequency = <200000000>; - status = "okay"; - }; - timer@d0020300 { - clock-frequency = <600000000>; - status = "okay"; - }; - - pinctrl { - pwr_led_pin: pwr-led-pin { - marvell,pins = "mpp63"; - marvell,function = "gpo"; + internal-regs { + serial@12000 { + clock-frequency = <200000000>; + status = "okay"; }; - - stat_led_pins: stat-led-pins { - marvell,pins = "mpp64", "mpp65"; - marvell,function = "gpio"; + timer@20300 { + clock-frequency = <600000000>; + status = "okay"; }; - }; - gpio_leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&pwr_led_pin &stat_led_pins>; + pinctrl { + pwr_led_pin: pwr-led-pin { + marvell,pins = "mpp63"; + marvell,function = "gpo"; + }; - green_pwr_led { - label = "mirabox:green:pwr"; - gpios = <&gpio1 31 1>; - linux,default-trigger = "heartbeat"; + stat_led_pins: stat-led-pins { + marvell,pins = "mpp64", "mpp65"; + marvell,function = "gpio"; + }; }; - blue_stat_led { - label = "mirabox:blue:stat"; - gpios = <&gpio2 0 1>; - linux,default-trigger = "cpu0"; + gpio_leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_led_pin &stat_led_pins>; + + green_pwr_led { + label = "mirabox:green:pwr"; + gpios = <&gpio1 31 1>; + linux,default-trigger = "heartbeat"; + }; + + blue_stat_led { + label = "mirabox:blue:stat"; + gpios = <&gpio2 0 1>; + linux,default-trigger = "cpu0"; + }; + + green_stat_led { + label = "mirabox:green:stat"; + gpios = <&gpio2 1 1>; + default-state = "off"; + }; }; - green_stat_led { - label = "mirabox:green:stat"; - gpios = <&gpio2 1 1>; - default-state = "off"; - }; - }; + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; - mdio { - phy0: ethernet-phy@0 { - reg = <0>; + phy1: ethernet-phy@1 { + reg = <1>; + }; }; - - phy1: ethernet-phy@1 { - reg = <1>; + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + ethernet@74000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; }; - }; - ethernet@d0070000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "rgmii-id"; - }; - ethernet@d0074000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "rgmii-id"; - }; - - mvsdio@d00d4000 { - pinctrl-0 = <&sdio_pins3>; - pinctrl-names = "default"; - status = "okay"; - /* - * No CD or WP GPIOs: SDIO interface used for - * Wifi/Bluetooth chip - */ - }; - - usb@d0050000 { - status = "okay"; - }; - usb@d0051000 { - status = "okay"; - }; + mvsdio@d4000 { + pinctrl-0 = <&sdio_pins3>; + pinctrl-names = "default"; + status = "okay"; + /* + * No CD or WP GPIOs: SDIO interface used for + * Wifi/Bluetooth chip + */ + }; - i2c@d0011000 { - status = "okay"; - clock-frequency = <100000>; - pca9505: pca9505@25 { - compatible = "nxp,pca9505"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x25>; + usb@50000 { + status = "okay"; }; - }; - pcie-controller { - status = "okay"; + usb@51000 { + status = "okay"; + }; - /* Internal mini-PCIe connector */ - pcie@1,0 { - /* Port 0, Lane 0 */ + i2c@11000 { status = "okay"; + clock-frequency = <100000>; + pca9505: pca9505@25 { + compatible = "nxp,pca9505"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x25>; + }; }; - /* Connected on the PCB to a USB 3.0 XHCI controller */ - pcie@2,0 { - /* Port 1, Lane 0 */ + pcie-controller { status = "okay"; + + /* Internal mini-PCIe connector */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + /* Connected on the PCB to a USB 3.0 XHCI controller */ + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts index 516dec31b469..130f8390a7e4 100644 --- a/arch/arm/boot/dts/armada-370-rd.dts +++ b/arch/arm/boot/dts/armada-370-rd.dts @@ -28,60 +28,62 @@ }; soc { - serial@d0012000 { - clock-frequency = <200000000>; - status = "okay"; - }; - sata@d00a0000 { - nr-ports = <2>; - status = "okay"; - }; - - mdio { - phy0: ethernet-phy@0 { - reg = <0>; + internal-regs { + serial@12000 { + clock-frequency = <200000000>; + status = "okay"; }; + sata@a0000 { + nr-ports = <2>; + status = "okay"; + }; + + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; - phy1: ethernet-phy@1 { - reg = <1>; + phy1: ethernet-phy@1 { + reg = <1>; + }; }; - }; - ethernet@d0070000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "sgmii"; - }; - ethernet@d0074000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "rgmii-id"; - }; + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "sgmii"; + }; + ethernet@74000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; - mvsdio@d00d4000 { - pinctrl-0 = <&sdio_pins1>; - pinctrl-names = "default"; - status = "okay"; - /* No CD or WP GPIOs */ - }; + mvsdio@d4000 { + pinctrl-0 = <&sdio_pins1>; + pinctrl-names = "default"; + status = "okay"; + /* No CD or WP GPIOs */ + }; - usb@d0050000 { - status = "okay"; - }; + usb@50000 { + status = "okay"; + }; - usb@d0051000 { - status = "okay"; - }; - }; + usb@51000 { + status = "okay"; + }; - gpio-keys { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; - button@1 { - label = "Software Button"; - linux,code = <116>; - gpios = <&gpio0 6 1>; + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + button@1 { + label = "Software Button"; + linux,code = <116>; + gpios = <&gpio0 6 1>; + }; + }; }; }; -}; + }; diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi index 758c4ea90344..272bbc65fab0 100644 --- a/arch/arm/boot/dts/armada-370-xp.dtsi +++ b/arch/arm/boot/dts/armada-370-xp.dtsi @@ -16,7 +16,7 @@ * 370 and Armada XP SoC. */ -/include/ "skeleton.dtsi" +/include/ "skeleton64.dtsi" / { model = "Marvell Armada 370 and XP SoC"; @@ -28,204 +28,203 @@ }; }; - mpic: interrupt-controller@d0020000 { - compatible = "marvell,mpic"; - #interrupt-cells = <1>; - #size-cells = <1>; - interrupt-controller; - }; - - coherency-fabric@d0020200 { - compatible = "marvell,coherency-fabric"; - reg = <0xd0020200 0xb0>, - <0xd0021810 0x1c>; - }; - soc { #address-cells = <1>; #size-cells = <1>; compatible = "simple-bus"; interrupt-parent = <&mpic>; - ranges; + ranges = <0 0 0xd0000000 0x100000>; + + internal-regs { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mpic: interrupt-controller@20000 { + compatible = "marvell,mpic"; + #interrupt-cells = <1>; + #size-cells = <1>; + interrupt-controller; + }; + + coherency-fabric@20200 { + compatible = "marvell,coherency-fabric"; + reg = <0x20200 0xb0>, <0x21810 0x1c>; + }; - serial@d0012000 { + serial@12000 { compatible = "snps,dw-apb-uart"; - reg = <0xd0012000 0x100>; + reg = <0x12000 0x100>; reg-shift = <2>; interrupts = <41>; reg-io-width = <1>; status = "disabled"; - }; - serial@d0012100 { + }; + serial@12100 { compatible = "snps,dw-apb-uart"; - reg = <0xd0012100 0x100>; + reg = <0x12100 0x100>; reg-shift = <2>; interrupts = <42>; reg-io-width = <1>; status = "disabled"; - }; - - timer@d0020300 { - compatible = "marvell,armada-370-xp-timer"; - reg = <0xd0020300 0x30>, - <0xd0021040 0x30>; - interrupts = <37>, <38>, <39>, <40>, <5>, <6>; - clocks = <&coreclk 2>; - }; - - addr-decoding@d0020000 { - compatible = "marvell,armada-addr-decoding-controller"; - reg = <0xd0020000 0x258>; - }; - - sata@d00a0000 { - compatible = "marvell,orion-sata"; - reg = <0xd00a0000 0x2400>; - interrupts = <55>; - clocks = <&gateclk 15>, <&gateclk 30>; - clock-names = "0", "1"; - status = "disabled"; - }; + }; + + timer@20300 { + compatible = "marvell,armada-370-xp-timer"; + reg = <0x20300 0x30>, <0x21040 0x30>; + interrupts = <37>, <38>, <39>, <40>, <5>, <6>; + clocks = <&coreclk 2>; + }; + + sata@a0000 { + compatible = "marvell,orion-sata"; + reg = <0xa0000 0x2400>; + interrupts = <55>; + clocks = <&gateclk 15>, <&gateclk 30>; + clock-names = "0", "1"; + status = "disabled"; + }; - mdio { - #address-cells = <1>; - #size-cells = <0>; - compatible = "marvell,orion-mdio"; - reg = <0xd0072004 0x4>; - }; + mdio { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,orion-mdio"; + reg = <0x72004 0x4>; + }; - ethernet@d0070000 { + ethernet@70000 { compatible = "marvell,armada-370-neta"; - reg = <0xd0070000 0x2500>; + reg = <0x70000 0x2500>; interrupts = <8>; clocks = <&gateclk 4>; status = "disabled"; - }; + }; - ethernet@d0074000 { + ethernet@74000 { compatible = "marvell,armada-370-neta"; - reg = <0xd0074000 0x2500>; + reg = <0x74000 0x2500>; interrupts = <10>; clocks = <&gateclk 3>; status = "disabled"; - }; - - i2c0: i2c@d0011000 { - compatible = "marvell,mv64xxx-i2c"; - reg = <0xd0011000 0x20>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = <31>; - timeout-ms = <1000>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - - i2c1: i2c@d0011100 { - compatible = "marvell,mv64xxx-i2c"; - reg = <0xd0011100 0x20>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = <32>; - timeout-ms = <1000>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - - rtc@10300 { - compatible = "marvell,orion-rtc"; - reg = <0xd0010300 0x20>; - interrupts = <50>; - }; - - mvsdio@d00d4000 { - compatible = "marvell,orion-sdio"; - reg = <0xd00d4000 0x200>; - interrupts = <54>; - clocks = <&gateclk 17>; - status = "disabled"; - }; - - usb@d0050000 { - compatible = "marvell,orion-ehci"; - reg = <0xd0050000 0x500>; - interrupts = <45>; - status = "disabled"; - }; - - usb@d0051000 { - compatible = "marvell,orion-ehci"; - reg = <0xd0051000 0x500>; - interrupts = <46>; - status = "disabled"; - }; - - spi0: spi@d0010600 { - compatible = "marvell,orion-spi"; - reg = <0xd0010600 0x28>; - #address-cells = <1>; - #size-cells = <0>; - cell-index = <0>; - interrupts = <30>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - - spi1: spi@d0010680 { - compatible = "marvell,orion-spi"; - reg = <0xd0010680 0x28>; - #address-cells = <1>; - #size-cells = <0>; - cell-index = <1>; - interrupts = <92>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - - devbus-bootcs@d0010400 { - compatible = "marvell,mvebu-devbus"; - reg = <0xd0010400 0x8>; - #address-cells = <1>; - #size-cells = <1>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - - devbus-cs0@d0010408 { - compatible = "marvell,mvebu-devbus"; - reg = <0xd0010408 0x8>; - #address-cells = <1>; - #size-cells = <1>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - - devbus-cs1@d0010410 { - compatible = "marvell,mvebu-devbus"; - reg = <0xd0010410 0x8>; - #address-cells = <1>; - #size-cells = <1>; - clocks = <&coreclk 0>; - status = "disabled"; - }; + }; + + i2c0: i2c@11000 { + compatible = "marvell,mv64xxx-i2c"; + reg = <0x11000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <31>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + i2c1: i2c@11100 { + compatible = "marvell,mv64xxx-i2c"; + reg = <0x11100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <32>; + timeout-ms = <1000>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + rtc@10300 { + compatible = "marvell,orion-rtc"; + reg = <0x10300 0x20>; + interrupts = <50>; + }; + + mvsdio@d4000 { + compatible = "marvell,orion-sdio"; + reg = <0xd4000 0x200>; + interrupts = <54>; + clocks = <&gateclk 17>; + status = "disabled"; + }; - devbus-cs2@d0010418 { - compatible = "marvell,mvebu-devbus"; - reg = <0xd0010418 0x8>; - #address-cells = <1>; - #size-cells = <1>; - clocks = <&coreclk 0>; - status = "disabled"; - }; + usb@50000 { + compatible = "marvell,orion-ehci"; + reg = <0x50000 0x500>; + interrupts = <45>; + status = "disabled"; + }; - devbus-cs3@d0010420 { - compatible = "marvell,mvebu-devbus"; - reg = <0xd0010420 0x8>; - #address-cells = <1>; - #size-cells = <1>; - clocks = <&coreclk 0>; - status = "disabled"; + usb@51000 { + compatible = "marvell,orion-ehci"; + reg = <0x51000 0x500>; + interrupts = <46>; + status = "disabled"; + }; + + spi0: spi@10600 { + compatible = "marvell,orion-spi"; + reg = <0x10600 0x28>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = <30>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + spi1: spi@10680 { + compatible = "marvell,orion-spi"; + reg = <0x10680 0x28>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + interrupts = <92>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-bootcs@10400 { + compatible = "marvell,mvebu-devbus"; + reg = <0x10400 0x8>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs0@10408 { + compatible = "marvell,mvebu-devbus"; + reg = <0x10408 0x8>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs1@10410 { + compatible = "marvell,mvebu-devbus"; + reg = <0x10410 0x8>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs2@10418 { + compatible = "marvell,mvebu-devbus"; + reg = <0x10418 0x8>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + devbus-cs3@10420 { + compatible = "marvell,mvebu-devbus"; + reg = <0x10420 0x8>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&coreclk 0>; + status = "disabled"; + }; }; }; -}; - + }; diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi index 18f6eb47cc50..b2c1b5af9749 100644 --- a/arch/arm/boot/dts/armada-370.dtsi +++ b/arch/arm/boot/dts/armada-370.dtsi @@ -16,16 +16,11 @@ */ /include/ "armada-370-xp.dtsi" +/include/ "skeleton.dtsi" / { model = "Marvell Armada 370 family SoC"; compatible = "marvell,armada370", "marvell,armada-370-xp"; - L2: l2-cache { - compatible = "marvell,aurora-outer-cache"; - reg = <0xd0008000 0x1000>; - cache-id-part = <0x100>; - wt-override; - }; aliases { gpio0 = &gpio0; @@ -33,188 +28,197 @@ gpio2 = &gpio2; }; - mpic: interrupt-controller@d0020000 { - reg = <0xd0020a00 0x1d0>, - <0xd0021870 0x58>; - }; - soc { - system-controller@d0018200 { + ranges = <0 0xd0000000 0x100000>; + internal-regs { + system-controller@18200 { compatible = "marvell,armada-370-xp-system-controller"; - reg = <0xd0018200 0x100>; - }; - - pinctrl { - compatible = "marvell,mv88f6710-pinctrl"; - reg = <0xd0018000 0x38>; - - sdio_pins1: sdio-pins1 { - marvell,pins = "mpp9", "mpp11", "mpp12", - "mpp13", "mpp14", "mpp15"; - marvell,function = "sd0"; + reg = <0x18200 0x100>; }; - sdio_pins2: sdio-pins2 { - marvell,pins = "mpp47", "mpp48", "mpp49", - "mpp50", "mpp51", "mpp52"; - marvell,function = "sd0"; + L2: l2-cache { + compatible = "marvell,aurora-outer-cache"; + reg = <0xd0008000 0x1000>; + cache-id-part = <0x100>; + wt-override; }; - sdio_pins3: sdio-pins3 { - marvell,pins = "mpp48", "mpp49", "mpp50", - "mpp51", "mpp52", "mpp53"; - marvell,function = "sd0"; + mpic: interrupt-controller@20000 { + reg = <0x20a00 0x1d0>, <0x21870 0x58>; }; - }; - - gpio0: gpio@d0018100 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018100 0x40>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <82>, <83>, <84>, <85>; - }; - - gpio1: gpio@d0018140 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018140 0x40>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <87>, <88>, <89>, <90>; - }; - - gpio2: gpio@d0018180 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018180 0x40>; - ngpios = <2>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <91>; - }; - coreclk: mvebu-sar@d0018230 { - compatible = "marvell,armada-370-core-clock"; - reg = <0xd0018230 0x08>; - #clock-cells = <1>; - }; - - gateclk: clock-gating-control@d0018220 { - compatible = "marvell,armada-370-gating-clock"; - reg = <0xd0018220 0x4>; - clocks = <&coreclk 0>; - #clock-cells = <1>; - }; - - xor@d0060800 { - compatible = "marvell,orion-xor"; - reg = <0xd0060800 0x100 - 0xd0060A00 0x100>; - status = "okay"; - - xor00 { - interrupts = <51>; - dmacap,memcpy; - dmacap,xor; + pinctrl { + compatible = "marvell,mv88f6710-pinctrl"; + reg = <0x18000 0x38>; + + sdio_pins1: sdio-pins1 { + marvell,pins = "mpp9", "mpp11", "mpp12", + "mpp13", "mpp14", "mpp15"; + marvell,function = "sd0"; + }; + + sdio_pins2: sdio-pins2 { + marvell,pins = "mpp47", "mpp48", "mpp49", + "mpp50", "mpp51", "mpp52"; + marvell,function = "sd0"; + }; + + sdio_pins3: sdio-pins3 { + marvell,pins = "mpp48", "mpp49", "mpp50", + "mpp51", "mpp52", "mpp53"; + marvell,function = "sd0"; + }; }; - xor01 { - interrupts = <52>; - dmacap,memcpy; - dmacap,xor; - dmacap,memset; - }; - }; - - xor@d0060900 { - compatible = "marvell,orion-xor"; - reg = <0xd0060900 0x100 - 0xd0060b00 0x100>; - status = "okay"; - xor10 { - interrupts = <94>; - dmacap,memcpy; - dmacap,xor; + gpio0: gpio@18100 { + compatible = "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <82>, <83>, <84>, <85>; }; - xor11 { - interrupts = <95>; - dmacap,memcpy; - dmacap,xor; - dmacap,memset; - }; - }; - usb@d0050000 { - clocks = <&coreclk 0>; - }; - - usb@d0051000 { - clocks = <&coreclk 0>; - }; + gpio1: gpio@18140 { + compatible = "marvell,orion-gpio"; + reg = <0x18140 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <87>, <88>, <89>, <90>; + }; - thermal@d0018300 { - compatible = "marvell,armada370-thermal"; - reg = <0xd0018300 0x4 - 0xd0018304 0x4>; - status = "okay"; - }; + gpio2: gpio@18180 { + compatible = "marvell,orion-gpio"; + reg = <0x18180 0x40>; + ngpios = <2>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <91>; + }; - pcie-controller { - compatible = "marvell,armada-370-pcie"; - status = "disabled"; - device_type = "pci"; + coreclk: mvebu-sar@18230 { + compatible = "marvell,armada-370-core-clock"; + reg = <0x18230 0x08>; + #clock-cells = <1>; + }; - #address-cells = <3>; - #size-cells = <2>; + gateclk: clock-gating-control@18220 { + compatible = "marvell,armada-370-gating-clock"; + reg = <0x18220 0x4>; + clocks = <&coreclk 0>; + #clock-cells = <1>; + }; - bus-range = <0x00 0xff>; + xor@60800 { + compatible = "marvell,orion-xor"; + reg = <0x60800 0x100 + 0x60A00 0x100>; + status = "okay"; + + xor00 { + interrupts = <51>; + dmacap,memcpy; + dmacap,xor; + }; + xor01 { + interrupts = <52>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; - reg = <0xd0040000 0x2000>, <0xd0080000 0x2000>; + xor@60900 { + compatible = "marvell,orion-xor"; + reg = <0x60900 0x100 + 0x60b00 0x100>; + status = "okay"; + + xor10 { + interrupts = <94>; + dmacap,memcpy; + dmacap,xor; + }; + xor11 { + interrupts = <95>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; - reg-names = "pcie0.0", "pcie1.0"; + usb@50000 { + clocks = <&coreclk 0>; + }; - ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */ - 0x82000000 0 0xd0080000 0xd0080000 0 0x00002000 /* Port 1.0 registers */ - 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ - 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + usb@51000 { + clocks = <&coreclk 0>; + }; - pcie@1,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>; - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 58>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 5>; - status = "disabled"; + thermal@18300 { + compatible = "marvell,armada370-thermal"; + reg = <0x18300 0x4 + 0x18304 0x4>; + status = "okay"; }; - pcie@2,0 { + pcie-controller { + compatible = "marvell,armada-370-pcie"; + status = "disabled"; device_type = "pci"; - assigned-addresses = <0x82002800 0 0xd0080000 0 0x2000>; - reg = <0x1000 0 0 0 0>; + #address-cells = <3>; #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 62>; - marvell,pcie-port = <1>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 9>; - status = "disabled"; + + bus-range = <0x00 0xff>; + + reg = <0x40000 0x2000>, <0x80000 0x2000>; + + reg-names = "pcie0.0", "pcie1.0"; + + ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0 0x80000 0x80000 0 0x00002000 /* Port 1.0 registers */ + 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ + 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + + pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + pcie@2,0 { + device_type = "pci"; + assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 62>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 9>; + status = "disabled"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts index 54cc5bb705fb..d6cc8bf8272e 100644 --- a/arch/arm/boot/dts/armada-xp-db.dts +++ b/arch/arm/boot/dts/armada-xp-db.dts @@ -26,132 +26,134 @@ memory { device_type = "memory"; - reg = <0x00000000 0x80000000>; /* 2 GB */ + reg = <0 0x00000000 0 0x80000000>; /* 2 GB */ }; soc { - serial@d0012000 { - clock-frequency = <250000000>; - status = "okay"; - }; - serial@d0012100 { - clock-frequency = <250000000>; - status = "okay"; - }; - serial@d0012200 { - clock-frequency = <250000000>; - status = "okay"; - }; - serial@d0012300 { - clock-frequency = <250000000>; - status = "okay"; - }; - - sata@d00a0000 { - nr-ports = <2>; - status = "okay"; - }; - - mdio { - phy0: ethernet-phy@0 { - reg = <0>; + internal-regs { + serial@12000 { + clock-frequency = <250000000>; + status = "okay"; }; - - phy1: ethernet-phy@1 { - reg = <1>; + serial@12100 { + clock-frequency = <250000000>; + status = "okay"; }; - - phy2: ethernet-phy@2 { - reg = <25>; + serial@12200 { + clock-frequency = <250000000>; + status = "okay"; }; - - phy3: ethernet-phy@3 { - reg = <27>; + serial@12300 { + clock-frequency = <250000000>; + status = "okay"; }; - }; - - ethernet@d0070000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "rgmii-id"; - }; - ethernet@d0074000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "rgmii-id"; - }; - ethernet@d0030000 { - status = "okay"; - phy = <&phy2>; - phy-mode = "sgmii"; - }; - ethernet@d0034000 { - status = "okay"; - phy = <&phy3>; - phy-mode = "sgmii"; - }; - - mvsdio@d00d4000 { - pinctrl-0 = <&sdio_pins>; - pinctrl-names = "default"; - status = "okay"; - /* No CD or WP GPIOs */ - }; - usb@d0050000 { - status = "okay"; - }; + sata@a0000 { + nr-ports = <2>; + status = "okay"; + }; - usb@d0051000 { - status = "okay"; - }; + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; - usb@d0052000 { - status = "okay"; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; - spi0: spi@d0010600 { - status = "okay"; + phy2: ethernet-phy@2 { + reg = <25>; + }; - spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "m25p64"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <20000000>; + phy3: ethernet-phy@3 { + reg = <27>; + }; }; - }; - pcie-controller { - status = "okay"; + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + ethernet@74000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + ethernet@30000 { + status = "okay"; + phy = <&phy2>; + phy-mode = "sgmii"; + }; + ethernet@34000 { + status = "okay"; + phy = <&phy3>; + phy-mode = "sgmii"; + }; - /* - * All 6 slots are physically present as - * standard PCIe slots on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ + mvsdio@d4000 { + pinctrl-0 = <&sdio_pins>; + pinctrl-names = "default"; status = "okay"; + /* No CD or WP GPIOs */ }; - pcie@2,0 { - /* Port 0, Lane 1 */ + + usb@50000 { status = "okay"; }; - pcie@3,0 { - /* Port 0, Lane 2 */ + + usb@51000 { status = "okay"; }; - pcie@4,0 { - /* Port 0, Lane 3 */ + + usb@52000 { status = "okay"; }; - pcie@9,0 { - /* Port 2, Lane 0 */ + + spi0: spi@10600 { status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p64"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <20000000>; + }; }; - pcie@10,0 { - /* Port 3, Lane 0 */ + + pcie-controller { status = "okay"; + + /* + * All 6 slots are physically present as + * standard PCIe slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@2,0 { + /* Port 0, Lane 1 */ + status = "okay"; + }; + pcie@3,0 { + /* Port 0, Lane 2 */ + status = "okay"; + }; + pcie@4,0 { + /* Port 0, Lane 3 */ + status = "okay"; + }; + pcie@9,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + pcie@10,0 { + /* Port 3, Lane 0 */ + status = "okay"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts index 04f28a712b98..26ad06fc147e 100644 --- a/arch/arm/boot/dts/armada-xp-gp.dts +++ b/arch/arm/boot/dts/armada-xp-gp.dts @@ -26,137 +26,141 @@ memory { device_type = "memory"; - /* - * 4 GB of plug-in RAM modules by default but only 3GB - * are visible, the amount of memory available can be - * changed by the bootloader according the size of the - * module actually plugged + * 8 GB of plug-in RAM modules by default.The amount + * of memory available can be changed by the + * bootloader according the size of the module + * actually plugged. Only 7GB are usable because + * addresses from 0xC0000000 to 0xffffffff are used by + * the internal registers of the SoC. */ - reg = <0x00000000 0xC0000000>; + reg = <0x00000000 0x00000000 0x00000000 0xC0000000>, + <0x00000001 0x00000000 0x00000001 0x00000000>; }; soc { - serial@d0012000 { - clock-frequency = <250000000>; - status = "okay"; - }; - serial@d0012100 { - clock-frequency = <250000000>; - status = "okay"; - }; - serial@d0012200 { - clock-frequency = <250000000>; - status = "okay"; - }; - serial@d0012300 { - clock-frequency = <250000000>; - status = "okay"; - }; - - sata@d00a0000 { - nr-ports = <2>; - status = "okay"; - }; - - mdio { - phy0: ethernet-phy@0 { - reg = <16>; + internal-regs { + serial@12000 { + clock-frequency = <250000000>; + status = "okay"; }; - - phy1: ethernet-phy@1 { - reg = <17>; + serial@12100 { + clock-frequency = <250000000>; + status = "okay"; }; - - phy2: ethernet-phy@2 { - reg = <18>; + serial@12200 { + clock-frequency = <250000000>; + status = "okay"; + }; + serial@12300 { + clock-frequency = <250000000>; + status = "okay"; }; - phy3: ethernet-phy@3 { - reg = <19>; + sata@a0000 { + nr-ports = <2>; + status = "okay"; }; - }; - ethernet@d0070000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "rgmii-id"; - }; - ethernet@d0074000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "rgmii-id"; - }; - ethernet@d0030000 { - status = "okay"; - phy = <&phy2>; - phy-mode = "rgmii-id"; - }; - ethernet@d0034000 { - status = "okay"; - phy = <&phy3>; - phy-mode = "rgmii-id"; - }; + mdio { + phy0: ethernet-phy@0 { + reg = <16>; + }; - spi0: spi@d0010600 { - status = "okay"; + phy1: ethernet-phy@1 { + reg = <17>; + }; - spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "n25q128a13"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <108000000>; - }; - }; + phy2: ethernet-phy@2 { + reg = <18>; + }; - devbus-bootcs@d0010400 { - status = "okay"; - ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf000000, size 0x1000000 */ - - /* Device Bus parameters are required */ - - /* Read parameters */ - devbus,bus-width = <8>; - devbus,turn-off-ps = <60000>; - devbus,badr-skew-ps = <0>; - devbus,acc-first-ps = <124000>; - devbus,acc-next-ps = <248000>; - devbus,rd-setup-ps = <0>; - devbus,rd-hold-ps = <0>; - - /* Write parameters */ - devbus,sync-enable = <0>; - devbus,wr-high-ps = <60000>; - devbus,wr-low-ps = <60000>; - devbus,ale-wr-ps = <60000>; - - /* NOR 16 MiB */ - nor@0 { - compatible = "cfi-flash"; - reg = <0 0x1000000>; - bank-width = <2>; + phy3: ethernet-phy@3 { + reg = <19>; + }; }; - }; - pcie-controller { - status = "okay"; + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + ethernet@74000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + ethernet@30000 { + status = "okay"; + phy = <&phy2>; + phy-mode = "rgmii-id"; + }; + ethernet@34000 { + status = "okay"; + phy = <&phy3>; + phy-mode = "rgmii-id"; + }; - /* - * The 3 slots are physically present as - * standard PCIe slots on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ + spi0: spi@10600 { status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; }; - pcie@9,0 { - /* Port 2, Lane 0 */ + + devbus-bootcs@10400 { status = "okay"; + ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf000000, size 0x1000000 */ + + /* Device Bus parameters are required */ + + /* Read parameters */ + devbus,bus-width = <8>; + devbus,turn-off-ps = <60000>; + devbus,badr-skew-ps = <0>; + devbus,acc-first-ps = <124000>; + devbus,acc-next-ps = <248000>; + devbus,rd-setup-ps = <0>; + devbus,rd-hold-ps = <0>; + + /* Write parameters */ + devbus,sync-enable = <0>; + devbus,wr-high-ps = <60000>; + devbus,wr-low-ps = <60000>; + devbus,ale-wr-ps = <60000>; + + /* NOR 16 MiB */ + nor@0 { + compatible = "cfi-flash"; + reg = <0 0x1000000>; + bank-width = <2>; + }; }; - pcie@10,0 { - /* Port 3, Lane 0 */ + + pcie-controller { status = "okay"; + + /* + * The 3 slots are physically present as + * standard PCIe slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@9,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + pcie@10,0 { + /* Port 3, Lane 0 */ + status = "okay"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi index c2c78459a4d4..f8eaa383e07f 100644 --- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi @@ -25,159 +25,161 @@ }; cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <0>; - clocks = <&cpuclk 0>; - }; - - cpu@1 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <1>; - clocks = <&cpuclk 1>; - }; - }; - - soc { - pinctrl { - compatible = "marvell,mv78230-pinctrl"; - reg = <0xd0018000 0x38>; - - sdio_pins: sdio-pins { - marvell,pins = "mpp30", "mpp31", "mpp32", - "mpp33", "mpp34", "mpp35"; - marvell,function = "sd0"; - }; - }; - - gpio0: gpio@d0018100 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018100 0x40>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <82>, <83>, <84>, <85>; + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <0>; + clocks = <&cpuclk 0>; }; - gpio1: gpio@d0018140 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018140 0x40>; - ngpios = <17>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <87>, <88>, <89>; + cpu@1 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <1>; + clocks = <&cpuclk 1>; }; + }; - /* - * MV78230 has 2 PCIe units Gen2.0: One unit can be - * configured as x4 or quad x1 lanes. One unit is - * x4/x1. - */ - pcie-controller { - compatible = "marvell,armada-xp-pcie"; - status = "disabled"; - device_type = "pci"; - - #address-cells = <3>; - #size-cells = <2>; - - bus-range = <0x00 0xff>; - - ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */ - 0x82000000 0 0xd0042000 0xd0042000 0 0x00002000 /* Port 2.0 registers */ - 0x82000000 0 0xd0044000 0xd0044000 0 0x00002000 /* Port 0.1 registers */ - 0x82000000 0 0xd0048000 0xd0048000 0 0x00002000 /* Port 0.2 registers */ - 0x82000000 0 0xd004c000 0xd004c000 0 0x00002000 /* Port 0.3 registers */ - 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ - 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ - - pcie@1,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>; - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 58>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 5>; - status = "disabled"; + soc { + internal-regs { + pinctrl { + compatible = "marvell,mv78230-pinctrl"; + reg = <0x18000 0x38>; + + sdio_pins: sdio-pins { + marvell,pins = "mpp30", "mpp31", "mpp32", + "mpp33", "mpp34", "mpp35"; + marvell,function = "sd0"; + }; }; - pcie@2,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0044000 0 0x2000>; - reg = <0x1000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 59>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <1>; - clocks = <&gateclk 6>; - status = "disabled"; + gpio0: gpio@18100 { + compatible = "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <82>, <83>, <84>, <85>; }; - pcie@3,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0048000 0 0x2000>; - reg = <0x1800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 60>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <2>; - clocks = <&gateclk 7>; - status = "disabled"; + gpio1: gpio@18140 { + compatible = "marvell,orion-gpio"; + reg = <0x18140 0x40>; + ngpios = <17>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <87>, <88>, <89>; }; - pcie@4,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd004c000 0 0x2000>; - reg = <0x2000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 61>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <3>; - clocks = <&gateclk 8>; + /* + * MV78230 has 2 PCIe units Gen2.0: One unit can be + * configured as x4 or quad x1 lanes. One unit is + * x4/x1. + */ + pcie-controller { + compatible = "marvell,armada-xp-pcie"; status = "disabled"; - }; - - pcie@9,0 { device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0042000 0 0x2000>; - reg = <0x4800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 99>; - marvell,pcie-port = <2>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 26>; - status = "disabled"; + +#address-cells = <3>; +#size-cells = <2>; + + bus-range = <0x00 0xff>; + + ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0 0x42000 0x42000 0 0x00002000 /* Port 2.0 registers */ + 0x82000000 0 0x44000 0x44000 0 0x00002000 /* Port 0.1 registers */ + 0x82000000 0 0x48000 0x48000 0 0x00002000 /* Port 0.2 registers */ + 0x82000000 0 0x4c000 0x4c000 0 0x00002000 /* Port 0.3 registers */ + 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ + 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + + pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + pcie@2,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 59>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 6>; + status = "disabled"; + }; + + pcie@3,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 60>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 7>; + status = "disabled"; + }; + + pcie@4,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 61>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 8>; + status = "disabled"; + }; + + pcie@9,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x42000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 99>; + marvell,pcie-port = <2>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 26>; + status = "disabled"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index 885bf229eef7..f4029f015aff 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi @@ -26,196 +26,198 @@ }; cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <0>; - clocks = <&cpuclk 0>; - }; - - cpu@1 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <1>; - clocks = <&cpuclk 1>; - }; + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <0>; + clocks = <&cpuclk 0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <1>; + clocks = <&cpuclk 1>; + }; }; soc { - pinctrl { - compatible = "marvell,mv78260-pinctrl"; - reg = <0xd0018000 0x38>; - - sdio_pins: sdio-pins { - marvell,pins = "mpp30", "mpp31", "mpp32", - "mpp33", "mpp34", "mpp35"; - marvell,function = "sd0"; + internal-regs { + pinctrl { + compatible = "marvell,mv78260-pinctrl"; + reg = <0x18000 0x38>; + + sdio_pins: sdio-pins { + marvell,pins = "mpp30", "mpp31", "mpp32", + "mpp33", "mpp34", "mpp35"; + marvell,function = "sd0"; + }; }; - }; - gpio0: gpio@d0018100 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018100 0x40>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <82>, <83>, <84>, <85>; - }; + gpio0: gpio@18100 { + compatible = "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <82>, <83>, <84>, <85>; + }; - gpio1: gpio@d0018140 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018140 0x40>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <87>, <88>, <89>, <90>; - }; + gpio1: gpio@18140 { + compatible = "marvell,orion-gpio"; + reg = <0x18140 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <87>, <88>, <89>, <90>; + }; - gpio2: gpio@d0018180 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018180 0x40>; - ngpios = <3>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <91>; - }; + gpio2: gpio@18180 { + compatible = "marvell,orion-gpio"; + reg = <0x18180 0x40>; + ngpios = <3>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <91>; + }; - ethernet@d0034000 { + ethernet@34000 { compatible = "marvell,armada-370-neta"; - reg = <0xd0034000 0x2500>; + reg = <0x34000 0x2500>; interrupts = <14>; clocks = <&gateclk 1>; status = "disabled"; - }; - - /* - * MV78260 has 3 PCIe units Gen2.0: Two units can be - * configured as x4 or quad x1 lanes. One unit is - * x4/x1. - */ - pcie-controller { - compatible = "marvell,armada-xp-pcie"; - status = "disabled"; - device_type = "pci"; - - #address-cells = <3>; - #size-cells = <2>; - - bus-range = <0x00 0xff>; - - ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */ - 0x82000000 0 0xd0042000 0xd0042000 0 0x00002000 /* Port 2.0 registers */ - 0x82000000 0 0xd0044000 0xd0044000 0 0x00002000 /* Port 0.1 registers */ - 0x82000000 0 0xd0048000 0xd0048000 0 0x00002000 /* Port 0.2 registers */ - 0x82000000 0 0xd004c000 0xd004c000 0 0x00002000 /* Port 0.3 registers */ - 0x82000000 0 0xd0080000 0xd0080000 0 0x00002000 /* Port 1.0 registers */ - 0x82000000 0 0xd0082000 0xd0082000 0 0x00002000 /* Port 3.0 registers */ - 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ - 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ - - pcie@1,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>; - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 58>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 5>; - status = "disabled"; - }; - - pcie@2,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0044000 0 0x2000>; - reg = <0x1000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 59>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <1>; - clocks = <&gateclk 6>; - status = "disabled"; }; - pcie@3,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0048000 0 0x2000>; - reg = <0x1800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 60>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <2>; - clocks = <&gateclk 7>; + /* + * MV78260 has 3 PCIe units Gen2.0: Two units can be + * configured as x4 or quad x1 lanes. One unit is + * x4/x1. + */ + pcie-controller { + compatible = "marvell,armada-xp-pcie"; status = "disabled"; - }; - - pcie@4,0 { device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd004c000 0 0x2000>; - reg = <0x2000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 61>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <3>; - clocks = <&gateclk 8>; - status = "disabled"; - }; - pcie@9,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0042000 0 0x2000>; - reg = <0x4800 0 0 0 0>; #address-cells = <3>; #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 99>; - marvell,pcie-port = <2>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 26>; - status = "disabled"; - }; - pcie@10,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0082000 0 0x2000>; - reg = <0x5000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 103>; - marvell,pcie-port = <3>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 27>; - status = "disabled"; + bus-range = <0x00 0xff>; + + ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0 0x42000 0x42000 0 0x00002000 /* Port 2.0 registers */ + 0x82000000 0 0x44000 0x44000 0 0x00002000 /* Port 0.1 registers */ + 0x82000000 0 0x48000 0x48000 0 0x00002000 /* Port 0.2 registers */ + 0x82000000 0 0x4c000 0x4c000 0 0x00002000 /* Port 0.3 registers */ + 0x82000000 0 0x80000 0x80000 0 0x00002000 /* Port 1.0 registers */ + 0x82000000 0 0x82000 0x82000 0 0x00002000 /* Port 3.0 registers */ + 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ + 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + + pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + + pcie@2,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 59>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 6>; + status = "disabled"; + }; + + pcie@3,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 60>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 7>; + status = "disabled"; + }; + + pcie@4,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 61>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 8>; + status = "disabled"; + }; + + pcie@9,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x42000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 99>; + marvell,pcie-port = <2>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 26>; + status = "disabled"; + }; + + pcie@10,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x82000 0 0x2000>; + reg = <0x5000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 103>; + marvell,pcie-port = <3>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 27>; + status = "disabled"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi index 23a5ac4490a8..6ab56bd35de9 100644 --- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi @@ -27,277 +27,279 @@ cpus { - #address-cells = <1>; - #size-cells = <0>; + #address-cells = <1>; + #size-cells = <0>; - cpu@0 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <0>; - clocks = <&cpuclk 0>; - }; + cpu@0 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <0>; + clocks = <&cpuclk 0>; + }; - cpu@1 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <1>; - clocks = <&cpuclk 1>; - }; + cpu@1 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <1>; + clocks = <&cpuclk 1>; + }; - cpu@2 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <2>; - clocks = <&cpuclk 2>; - }; + cpu@2 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <2>; + clocks = <&cpuclk 2>; + }; - cpu@3 { - device_type = "cpu"; - compatible = "marvell,sheeva-v7"; - reg = <3>; - clocks = <&cpuclk 3>; - }; + cpu@3 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <3>; + clocks = <&cpuclk 3>; + }; }; soc { - pinctrl { - compatible = "marvell,mv78460-pinctrl"; - reg = <0xd0018000 0x38>; + internal-regs { + pinctrl { + compatible = "marvell,mv78460-pinctrl"; + reg = <0x18000 0x38>; - sdio_pins: sdio-pins { - marvell,pins = "mpp30", "mpp31", "mpp32", - "mpp33", "mpp34", "mpp35"; - marvell,function = "sd0"; + sdio_pins: sdio-pins { + marvell,pins = "mpp30", "mpp31", "mpp32", + "mpp33", "mpp34", "mpp35"; + marvell,function = "sd0"; + }; }; - }; - gpio0: gpio@d0018100 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018100 0x40>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <82>, <83>, <84>, <85>; - }; + gpio0: gpio@18100 { + compatible = "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <82>, <83>, <84>, <85>; + }; - gpio1: gpio@d0018140 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018140 0x40>; - ngpios = <32>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <87>, <88>, <89>, <90>; - }; + gpio1: gpio@18140 { + compatible = "marvell,orion-gpio"; + reg = <0x18140 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <87>, <88>, <89>, <90>; + }; - gpio2: gpio@d0018180 { - compatible = "marvell,orion-gpio"; - reg = <0xd0018180 0x40>; - ngpios = <3>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; - #interrupts-cells = <2>; - interrupts = <91>; - }; + gpio2: gpio@18180 { + compatible = "marvell,orion-gpio"; + reg = <0x18180 0x40>; + ngpios = <3>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupts-cells = <2>; + interrupts = <91>; + }; - ethernet@d0034000 { + ethernet@34000 { compatible = "marvell,armada-370-neta"; - reg = <0xd0034000 0x2500>; + reg = <0x34000 0x2500>; interrupts = <14>; clocks = <&gateclk 1>; status = "disabled"; - }; + }; - /* - * MV78460 has 4 PCIe units Gen2.0: Two units can be - * configured as x4 or quad x1 lanes. Two units are - * x4/x1. - */ - pcie-controller { - compatible = "marvell,armada-xp-pcie"; - status = "disabled"; - device_type = "pci"; + /* + * MV78460 has 4 PCIe units Gen2.0: Two units can be + * configured as x4 or quad x1 lanes. Two units are + * x4/x1. + */ + pcie-controller { + compatible = "marvell,armada-xp-pcie"; + status = "disabled"; + device_type = "pci"; - #address-cells = <3>; - #size-cells = <2>; + #address-cells = <3>; + #size-cells = <2>; - bus-range = <0x00 0xff>; + bus-range = <0x00 0xff>; - ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */ - 0x82000000 0 0xd0042000 0xd0042000 0 0x00002000 /* Port 2.0 registers */ - 0x82000000 0 0xd0044000 0xd0044000 0 0x00002000 /* Port 0.1 registers */ - 0x82000000 0 0xd0048000 0xd0048000 0 0x00002000 /* Port 0.2 registers */ - 0x82000000 0 0xd004c000 0xd004c000 0 0x00002000 /* Port 0.3 registers */ - 0x82000000 0 0xd0080000 0xd0080000 0 0x00002000 /* Port 1.0 registers */ - 0x82000000 0 0xd0082000 0xd0082000 0 0x00002000 /* Port 3.0 registers */ - 0x82000000 0 0xd0084000 0xd0084000 0 0x00002000 /* Port 1.1 registers */ - 0x82000000 0 0xd0088000 0xd0088000 0 0x00002000 /* Port 1.2 registers */ - 0x82000000 0 0xd008c000 0xd008c000 0 0x00002000 /* Port 1.3 registers */ - 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ - 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ + ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0 0x42000 0x42000 0 0x00002000 /* Port 2.0 registers */ + 0x82000000 0 0x44000 0x44000 0 0x00002000 /* Port 0.1 registers */ + 0x82000000 0 0x48000 0x48000 0 0x00002000 /* Port 0.2 registers */ + 0x82000000 0 0x4c000 0x4c000 0 0x00002000 /* Port 0.3 registers */ + 0x82000000 0 0x80000 0x80000 0 0x00002000 /* Port 1.0 registers */ + 0x82000000 0 0x82000 0x82000 0 0x00002000 /* Port 3.0 registers */ + 0x82000000 0 0x84000 0x84000 0 0x00002000 /* Port 1.1 registers */ + 0x82000000 0 0x88000 0x88000 0 0x00002000 /* Port 1.2 registers */ + 0x82000000 0 0x8c000 0x8c000 0 0x00002000 /* Port 1.3 registers */ + 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */ + 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */ - pcie@1,0 { - device_type = "pci"; - assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>; - reg = <0x0800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 58>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 5>; - status = "disabled"; - }; + pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; - pcie@2,0 { - device_type = "pci"; - assigned-addresses = <0x82001000 0 0xd0044000 0 0x2000>; - reg = <0x1000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 59>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <1>; - clocks = <&gateclk 6>; - status = "disabled"; - }; + pcie@2,0 { + device_type = "pci"; + assigned-addresses = <0x82001000 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 59>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 6>; + status = "disabled"; + }; - pcie@3,0 { - device_type = "pci"; - assigned-addresses = <0x82001800 0 0xd0048000 0 0x2000>; - reg = <0x1800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 60>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <2>; - clocks = <&gateclk 7>; - status = "disabled"; - }; + pcie@3,0 { + device_type = "pci"; + assigned-addresses = <0x82001800 0 0x48000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 60>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 7>; + status = "disabled"; + }; - pcie@4,0 { - device_type = "pci"; - assigned-addresses = <0x82002000 0 0xd004c000 0 0x2000>; - reg = <0x2000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 61>; - marvell,pcie-port = <0>; - marvell,pcie-lane = <3>; - clocks = <&gateclk 8>; - status = "disabled"; - }; + pcie@4,0 { + device_type = "pci"; + assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 61>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 8>; + status = "disabled"; + }; - pcie@5,0 { - device_type = "pci"; - assigned-addresses = <0x82002800 0 0xd0080000 0 0x2000>; - reg = <0x2800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 62>; - marvell,pcie-port = <1>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 9>; - status = "disabled"; - }; + pcie@5,0 { + device_type = "pci"; + assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; + reg = <0x2800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 62>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 9>; + status = "disabled"; + }; - pcie@6,0 { - device_type = "pci"; - assigned-addresses = <0x82003000 0 0xd0084000 0 0x2000>; - reg = <0x3000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 63>; - marvell,pcie-port = <1>; - marvell,pcie-lane = <1>; - clocks = <&gateclk 10>; - status = "disabled"; - }; + pcie@6,0 { + device_type = "pci"; + assigned-addresses = <0x82003000 0 0x84000 0 0x2000>; + reg = <0x3000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 63>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <1>; + clocks = <&gateclk 10>; + status = "disabled"; + }; - pcie@7,0 { - device_type = "pci"; - assigned-addresses = <0x82003800 0 0xd0088000 0 0x2000>; - reg = <0x3800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 64>; - marvell,pcie-port = <1>; - marvell,pcie-lane = <2>; - clocks = <&gateclk 11>; - status = "disabled"; - }; + pcie@7,0 { + device_type = "pci"; + assigned-addresses = <0x82003800 0 0x88000 0 0x2000>; + reg = <0x3800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 64>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <2>; + clocks = <&gateclk 11>; + status = "disabled"; + }; - pcie@8,0 { - device_type = "pci"; - assigned-addresses = <0x82004000 0 0xd008c000 0 0x2000>; - reg = <0x4000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 65>; - marvell,pcie-port = <1>; - marvell,pcie-lane = <3>; - clocks = <&gateclk 12>; - status = "disabled"; - }; - pcie@9,0 { - device_type = "pci"; - assigned-addresses = <0x82004800 0 0xd0042000 0 0x2000>; - reg = <0x4800 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 99>; - marvell,pcie-port = <2>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 26>; - status = "disabled"; - }; + pcie@8,0 { + device_type = "pci"; + assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>; + reg = <0x4000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 65>; + marvell,pcie-port = <1>; + marvell,pcie-lane = <3>; + clocks = <&gateclk 12>; + status = "disabled"; + }; + pcie@9,0 { + device_type = "pci"; + assigned-addresses = <0x82004800 0 0x42000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 99>; + marvell,pcie-port = <2>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 26>; + status = "disabled"; + }; - pcie@10,0 { - device_type = "pci"; - assigned-addresses = <0x82005000 0 0xd0082000 0 0x2000>; - reg = <0x5000 0 0 0 0>; - #address-cells = <3>; - #size-cells = <2>; - #interrupt-cells = <1>; - ranges; - interrupt-map-mask = <0 0 0 0>; - interrupt-map = <0 0 0 0 &mpic 103>; - marvell,pcie-port = <3>; - marvell,pcie-lane = <0>; - clocks = <&gateclk 27>; - status = "disabled"; + pcie@10,0 { + device_type = "pci"; + assigned-addresses = <0x82005000 0 0x82000 0 0x2000>; + reg = <0x5000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 103>; + marvell,pcie-port = <3>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 27>; + status = "disabled"; + }; }; }; }; - }; +}; diff --git a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts index 9d04f04d4e39..f14d36c46159 100644 --- a/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts +++ b/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts @@ -23,158 +23,160 @@ memory { device_type = "memory"; - reg = <0x00000000 0xC0000000>; /* 3 GB */ + reg = <0 0x00000000 0 0xC0000000>; /* 3 GB */ }; soc { - serial@d0012000 { - clock-frequency = <250000000>; - status = "okay"; - }; - serial@d0012100 { - clock-frequency = <250000000>; - status = "okay"; - }; - pinctrl { - led_pins: led-pins-0 { - marvell,pins = "mpp49", "mpp51", "mpp53"; - marvell,function = "gpio"; + internal-regs { + serial@12000 { + clock-frequency = <250000000>; + status = "okay"; }; - }; - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&led_pins>; - - red_led { - label = "red_led"; - gpios = <&gpio1 17 1>; - default-state = "off"; + serial@12100 { + clock-frequency = <250000000>; + status = "okay"; }; - - yellow_led { - label = "yellow_led"; - gpios = <&gpio1 19 1>; - default-state = "off"; + pinctrl { + led_pins: led-pins-0 { + marvell,pins = "mpp49", "mpp51", "mpp53"; + marvell,function = "gpio"; + }; }; - - green_led { - label = "green_led"; - gpios = <&gpio1 21 1>; - default-state = "off"; - linux,default-trigger = "heartbeat"; + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + red_led { + label = "red_led"; + gpios = <&gpio1 17 1>; + default-state = "off"; + }; + + yellow_led { + label = "yellow_led"; + gpios = <&gpio1 19 1>; + default-state = "off"; + }; + + green_led { + label = "green_led"; + gpios = <&gpio1 21 1>; + default-state = "off"; + linux,default-trigger = "heartbeat"; + }; }; - }; - gpio_keys { - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; - button@1 { - label = "Init Button"; - linux,code = <116>; - gpios = <&gpio1 28 0>; + button@1 { + label = "Init Button"; + linux,code = <116>; + gpios = <&gpio1 28 0>; + }; }; - }; - mdio { - phy0: ethernet-phy@0 { - reg = <0>; - }; + mdio { + phy0: ethernet-phy@0 { + reg = <0>; + }; - phy1: ethernet-phy@1 { - reg = <1>; - }; + phy1: ethernet-phy@1 { + reg = <1>; + }; - phy2: ethernet-phy@2 { - reg = <2>; - }; + phy2: ethernet-phy@2 { + reg = <2>; + }; - phy3: ethernet-phy@3 { - reg = <3>; + phy3: ethernet-phy@3 { + reg = <3>; + }; }; - }; - ethernet@d0070000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "sgmii"; - }; - ethernet@d0074000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "sgmii"; - }; - ethernet@d0030000 { - status = "okay"; - phy = <&phy2>; - phy-mode = "sgmii"; - }; - ethernet@d0034000 { - status = "okay"; - phy = <&phy3>; - phy-mode = "sgmii"; - }; - i2c@d0011000 { - status = "okay"; - clock-frequency = <400000>; - }; - i2c@d0011100 { - status = "okay"; - clock-frequency = <400000>; + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "sgmii"; + }; + ethernet@74000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; + }; + ethernet@30000 { + status = "okay"; + phy = <&phy2>; + phy-mode = "sgmii"; + }; + ethernet@34000 { + status = "okay"; + phy = <&phy3>; + phy-mode = "sgmii"; + }; + i2c@11000 { + status = "okay"; + clock-frequency = <400000>; + }; + i2c@11100 { + status = "okay"; + clock-frequency = <400000>; - s35390a: s35390a@30 { - compatible = "s35390a"; - reg = <0x30>; + s35390a: s35390a@30 { + compatible = "s35390a"; + reg = <0x30>; + }; + }; + sata@a0000 { + nr-ports = <2>; + status = "okay"; + }; + usb@50000 { + status = "okay"; + }; + usb@51000 { + status = "okay"; }; - }; - sata@d00a0000 { - nr-ports = <2>; - status = "okay"; - }; - usb@d0050000 { - status = "okay"; - }; - usb@d0051000 { - status = "okay"; - }; - devbus-bootcs@d0010400 { - status = "okay"; - ranges = <0 0xf0000000 0x8000000>; /* @addr 0xf000000, size 0x8000000 */ - - /* Device Bus parameters are required */ - - /* Read parameters */ - devbus,bus-width = <8>; - devbus,turn-off-ps = <60000>; - devbus,badr-skew-ps = <0>; - devbus,acc-first-ps = <124000>; - devbus,acc-next-ps = <248000>; - devbus,rd-setup-ps = <0>; - devbus,rd-hold-ps = <0>; - - /* Write parameters */ - devbus,sync-enable = <0>; - devbus,wr-high-ps = <60000>; - devbus,wr-low-ps = <60000>; - devbus,ale-wr-ps = <60000>; - - /* NOR 128 MiB */ - nor@0 { - compatible = "cfi-flash"; - reg = <0 0x8000000>; - bank-width = <2>; + devbus-bootcs@10400 { + status = "okay"; + ranges = <0 0xf0000000 0x8000000>; /* @addr 0xf000000, size 0x8000000 */ + + /* Device Bus parameters are required */ + + /* Read parameters */ + devbus,bus-width = <8>; + devbus,turn-off-ps = <60000>; + devbus,badr-skew-ps = <0>; + devbus,acc-first-ps = <124000>; + devbus,acc-next-ps = <248000>; + devbus,rd-setup-ps = <0>; + devbus,rd-hold-ps = <0>; + + /* Write parameters */ + devbus,sync-enable = <0>; + devbus,wr-high-ps = <60000>; + devbus,wr-low-ps = <60000>; + devbus,ale-wr-ps = <60000>; + + /* NOR 128 MiB */ + nor@0 { + compatible = "cfi-flash"; + reg = <0 0x8000000>; + bank-width = <2>; + }; }; - }; - pcie-controller { - status = "okay"; - /* Internal mini-PCIe connector */ - pcie@1,0 { - /* Port 0, Lane 0 */ + pcie-controller { status = "okay"; + /* Internal mini-PCIe connector */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; }; }; }; diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi index 29dfeb6d4a26..bacab11c10dc 100644 --- a/arch/arm/boot/dts/armada-xp.dtsi +++ b/arch/arm/boot/dts/armada-xp.dtsi @@ -22,140 +22,140 @@ model = "Marvell Armada XP family SoC"; compatible = "marvell,armadaxp", "marvell,armada-370-xp"; - L2: l2-cache { - compatible = "marvell,aurora-system-cache"; - reg = <0xd0008000 0x1000>; - cache-id-part = <0x100>; - wt-override; - }; + soc { + internal-regs { + L2: l2-cache { + compatible = "marvell,aurora-system-cache"; + reg = <0x08000 0x1000>; + cache-id-part = <0x100>; + wt-override; + }; - mpic: interrupt-controller@d0020000 { - reg = <0xd0020a00 0x2d0>, - <0xd0021070 0x58>; - }; + mpic: interrupt-controller@20000 { + reg = <0x20a00 0x2d0>, <0x21070 0x58>; + }; - armada-370-xp-pmsu@d0022000 { - compatible = "marvell,armada-370-xp-pmsu"; - reg = <0xd0022100 0x430>, - <0xd0020800 0x20>; - }; + armada-370-xp-pmsu@22000 { + compatible = "marvell,armada-370-xp-pmsu"; + reg = <0x22100 0x430>, <0x20800 0x20>; + }; - soc { - serial@d0012200 { + serial@12200 { compatible = "snps,dw-apb-uart"; - reg = <0xd0012200 0x100>; + reg = <0x12200 0x100>; reg-shift = <2>; interrupts = <43>; reg-io-width = <1>; status = "disabled"; - }; - serial@d0012300 { + }; + serial@12300 { compatible = "snps,dw-apb-uart"; - reg = <0xd0012300 0x100>; + reg = <0x12300 0x100>; reg-shift = <2>; interrupts = <44>; reg-io-width = <1>; status = "disabled"; - }; + }; - timer@d0020300 { + timer@20300 { marvell,timer-25Mhz; - }; + }; - coreclk: mvebu-sar@d0018230 { - compatible = "marvell,armada-xp-core-clock"; - reg = <0xd0018230 0x08>; - #clock-cells = <1>; - }; + coreclk: mvebu-sar@18230 { + compatible = "marvell,armada-xp-core-clock"; + reg = <0x18230 0x08>; + #clock-cells = <1>; + }; - cpuclk: clock-complex@d0018700 { - #clock-cells = <1>; - compatible = "marvell,armada-xp-cpu-clock"; - reg = <0xd0018700 0xA0>; - clocks = <&coreclk 1>; - }; + cpuclk: clock-complex@18700 { + #clock-cells = <1>; + compatible = "marvell,armada-xp-cpu-clock"; + reg = <0x18700 0xA0>; + clocks = <&coreclk 1>; + }; - gateclk: clock-gating-control@d0018220 { - compatible = "marvell,armada-xp-gating-clock"; - reg = <0xd0018220 0x4>; - clocks = <&coreclk 0>; - #clock-cells = <1>; - }; + gateclk: clock-gating-control@18220 { + compatible = "marvell,armada-xp-gating-clock"; + reg = <0x18220 0x4>; + clocks = <&coreclk 0>; + #clock-cells = <1>; + }; - system-controller@d0018200 { + system-controller@18200 { compatible = "marvell,armada-370-xp-system-controller"; - reg = <0xd0018200 0x500>; - }; + reg = <0x18200 0x500>; + }; - ethernet@d0030000 { + ethernet@30000 { compatible = "marvell,armada-370-neta"; - reg = <0xd0030000 0x2500>; + reg = <0x30000 0x2500>; interrupts = <12>; clocks = <&gateclk 2>; status = "disabled"; - }; - - xor@d0060900 { - compatible = "marvell,orion-xor"; - reg = <0xd0060900 0x100 - 0xd0060b00 0x100>; - clocks = <&gateclk 22>; - status = "okay"; - - xor10 { - interrupts = <51>; - dmacap,memcpy; - dmacap,xor; - }; - xor11 { - interrupts = <52>; - dmacap,memcpy; - dmacap,xor; - dmacap,memset; }; - }; - xor@d00f0900 { - compatible = "marvell,orion-xor"; - reg = <0xd00F0900 0x100 - 0xd00F0B00 0x100>; - clocks = <&gateclk 28>; - status = "okay"; - - xor00 { - interrupts = <94>; - dmacap,memcpy; - dmacap,xor; + xor@60900 { + compatible = "marvell,orion-xor"; + reg = <0x60900 0x100 + 0x60b00 0x100>; + clocks = <&gateclk 22>; + status = "okay"; + + xor10 { + interrupts = <51>; + dmacap,memcpy; + dmacap,xor; + }; + xor11 { + interrupts = <52>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; }; - xor01 { - interrupts = <95>; - dmacap,memcpy; - dmacap,xor; - dmacap,memset; + + xor@f0900 { + compatible = "marvell,orion-xor"; + reg = <0xF0900 0x100 + 0xF0B00 0x100>; + clocks = <&gateclk 28>; + status = "okay"; + + xor00 { + interrupts = <94>; + dmacap,memcpy; + dmacap,xor; + }; + xor01 { + interrupts = <95>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; }; - }; - usb@d0050000 { - clocks = <&gateclk 18>; - }; + usb@50000 { + clocks = <&gateclk 18>; + }; - usb@d0051000 { - clocks = <&gateclk 19>; - }; + usb@51000 { + clocks = <&gateclk 19>; + }; - usb@d0052000 { - compatible = "marvell,orion-ehci"; - reg = <0xd0052000 0x500>; - interrupts = <47>; - clocks = <&gateclk 20>; - status = "disabled"; - }; + usb@52000 { + compatible = "marvell,orion-ehci"; + reg = <0x52000 0x500>; + interrupts = <47>; + clocks = <&gateclk 20>; + status = "disabled"; + }; - thermal@d00182b0 { - compatible = "marvell,armadaxp-thermal"; - reg = <0xd00182b0 0x4 - 0xd00184d0 0x4>; - status = "okay"; + thermal@182b0 { + compatible = "marvell,armadaxp-thermal"; + reg = <0x182b0 0x4 + 0x184d0 0x4>; + status = "okay"; + }; }; }; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index f8f7370e8669..bf18a735c37d 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -108,6 +108,7 @@ compatible = "atmel,at91sam9g45-dma"; reg = <0xffffec00 0x200>; interrupts = <21 4 0>; + #dma-cells = <2>; }; pinctrl@fffff200 { @@ -533,6 +534,8 @@ compatible = "atmel,hsmci"; reg = <0xfff80000 0x600>; interrupts = <11 4 0>; + dmas = <&dma 1 0>; + dma-names = "rxtx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -542,6 +545,8 @@ compatible = "atmel,hsmci"; reg = <0xfffd0000 0x600>; interrupts = <29 4 0>; + dmas = <&dma 1 13>; + dma-names = "rxtx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi index b2961f1ea51b..3de8e6dfbcb1 100644 --- a/arch/arm/boot/dts/at91sam9n12.dtsi +++ b/arch/arm/boot/dts/at91sam9n12.dtsi @@ -89,6 +89,8 @@ compatible = "atmel,hsmci"; reg = <0xf0008000 0x600>; interrupts = <12 4 0>; + dmas = <&dma 1 0>; + dma-names = "rxtx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -110,6 +112,7 @@ compatible = "atmel,at91sam9g45-dma"; reg = <0xffffec00 0x200>; interrupts = <20 4 0>; + #dma-cells = <2>; }; pinctrl@fffff400 { @@ -378,6 +381,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf8010000 0x100>; interrupts = <9 4 6>; + dmas = <&dma 1 13>, + <&dma 1 14>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -387,6 +393,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf8014000 0x100>; interrupts = <10 4 6>; + dmas = <&dma 1 15>, + <&dma 1 16>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 640b3bbbb706..1145ac330fb7 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -104,12 +104,14 @@ compatible = "atmel,at91sam9g45-dma"; reg = <0xffffec00 0x200>; interrupts = <20 4 0>; + #dma-cells = <2>; }; dma1: dma-controller@ffffee00 { compatible = "atmel,at91sam9g45-dma"; reg = <0xffffee00 0x200>; interrupts = <21 4 0>; + #dma-cells = <2>; }; pinctrl@fffff400 { @@ -465,6 +467,8 @@ compatible = "atmel,hsmci"; reg = <0xf0008000 0x600>; interrupts = <12 4 0>; + dmas = <&dma0 1 0>; + dma-names = "rxtx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -474,6 +478,8 @@ compatible = "atmel,hsmci"; reg = <0xf000c000 0x600>; interrupts = <26 4 0>; + dmas = <&dma1 1 0>; + dma-names = "rxtx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -535,6 +541,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf8010000 0x100>; interrupts = <9 4 6>; + dmas = <&dma0 1 7>, + <&dma0 1 8>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -546,6 +555,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf8014000 0x100>; interrupts = <10 4 6>; + dmas = <&dma1 1 5>, + <&dma1 1 6>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; @@ -557,6 +569,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf8018000 0x100>; interrupts = <11 4 6>; + dmas = <&dma0 1 9>, + <&dma0 1 10>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi index 62eceb4f0d3f..3f0239ec1bc5 100644 --- a/arch/arm/boot/dts/cros5250-common.dtsi +++ b/arch/arm/boot/dts/cros5250-common.dtsi @@ -19,11 +19,19 @@ chosen { }; + pinctrl@11400000 { + /* + * Disabled pullups since external part has its own pullups and + * double-pulling gets us out of spec in some cases. + */ + i2c2_bus: i2c2-bus { + samsung,pin-pud = <0>; + }; + }; + i2c@12C60000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <378000>; - gpios = <&gpb3 0 2 3 0>, - <&gpb3 1 2 3 0>; max77686@09 { compatible = "maxim,max77686"; @@ -167,21 +175,20 @@ i2c@12C70000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <378000>; - gpios = <&gpb3 2 2 3 0>, - <&gpb3 3 2 3 0>; + + trackpad { + reg = <0x67>; + compatible = "cypress,cyapa"; + interrupts = <2 0>; + interrupt-parent = <&gpx1>; + wakeup-source; + }; }; i2c@12C80000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <66000>; - /* - * Disabled pullups since external part has its own pullups and - * double-pulling gets us out of spec in some cases. - */ - gpios = <&gpa0 6 3 0 0>, - <&gpa0 7 3 0 0>; - hdmiddc@50 { compatible = "samsung,exynos5-hdmiddc"; reg = <0x50>; @@ -191,19 +198,16 @@ i2c@12C90000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <66000>; - gpios = <&gpa1 2 3 3 0>, - <&gpa1 3 3 3 0>; }; i2c@12CA0000 { - status = "disabled"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; }; i2c@12CB0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <66000>; - gpios = <&gpa2 2 3 3 0>, - <&gpa2 3 3 3 0>; }; i2c@12CC0000 { @@ -213,8 +217,6 @@ i2c@12CD0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <66000>; - gpios = <&gpb2 2 3 3 0>, - <&gpb2 3 3 3 0>; }; i2c@12CE0000 { @@ -236,15 +238,12 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <2 3>; samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4 &sd0_bus8>; 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>; }; }; @@ -260,15 +259,13 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <2 3>; samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; slot@0 { reg = <0>; bus-width = <4>; - samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>; - wp-gpios = <&gpc2 1 0 0 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>; + wp-gpios = <&gpc2 1 0>; }; }; @@ -281,11 +278,11 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <2 3>; samsung,dw-mshc-ddr-timing = <1 2>; + /* See board-specific dts files for pin setup */ slot@0 { reg = <0>; bus-width = <4>; - /* See board-specific dts files for GPIOs */ }; }; @@ -294,9 +291,6 @@ }; spi_1: spi@12d30000 { - gpios = <&gpa2 4 2 3 0>, - <&gpa2 6 2 3 0>, - <&gpa2 7 2 3 0>; samsung,spi-src-clk = <0>; num-cs = <1>; }; @@ -306,7 +300,7 @@ }; hdmi { - hpd-gpio = <&gpx3 7 0xf 1 3>; + hpd-gpio = <&gpx3 7 0>; }; gpio-keys { @@ -314,7 +308,7 @@ power { label = "Power"; - gpios = <&gpx1 3 0 0x10000 0>; + gpios = <&gpx1 3 1>; linux,code = <116>; /* KEY_POWER */ gpio-key,wakeup; }; diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts index c5834a6c5bf4..c914357c0d89 100644 --- a/arch/arm/boot/dts/da850-evm.dts +++ b/arch/arm/boot/dts/da850-evm.dts @@ -50,6 +50,46 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; }; + spi1: spi@1f0e000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins &spi1_cs0_pin>; + flash: m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "m25p64"; + spi-max-frequency = <30000000>; + reg = <0>; + partition@0 { + label = "U-Boot-SPL"; + reg = <0x00000000 0x00010000>; + read-only; + }; + partition@1 { + label = "U-Boot"; + reg = <0x00010000 0x00080000>; + read-only; + }; + partition@2 { + label = "U-Boot-Env"; + reg = <0x00090000 0x00010000>; + read-only; + }; + partition@3 { + label = "Kernel"; + reg = <0x000a0000 0x00280000>; + }; + partition@4 { + label = "Filesystem"; + reg = <0x00320000 0x00400000>; + }; + partition@5 { + label = "MAC-Address"; + reg = <0x007f0000 0x00010000>; + read-only; + }; + }; + }; }; nand_cs3@62000000 { status = "okay"; diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index 3ade343f13cc..2c88313d2c7a 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -71,6 +71,60 @@ 0x28 0x00222222 0x00ffffff >; }; + ehrpwm0a_pins: pinmux_ehrpwm0a_pins { + pinctrl-single,bits = < + /* EPWM0A */ + 0xc 0x00000002 0x0000000f + >; + }; + ehrpwm0b_pins: pinmux_ehrpwm0b_pins { + pinctrl-single,bits = < + /* EPWM0B */ + 0xc 0x00000020 0x000000f0 + >; + }; + ehrpwm1a_pins: pinmux_ehrpwm1a_pins { + pinctrl-single,bits = < + /* EPWM1A */ + 0x14 0x00000002 0x0000000f + >; + }; + ehrpwm1b_pins: pinmux_ehrpwm1b_pins { + pinctrl-single,bits = < + /* EPWM1B */ + 0x14 0x00000020 0x000000f0 + >; + }; + ecap0_pins: pinmux_ecap0_pins { + pinctrl-single,bits = < + /* ECAP0_APWM0 */ + 0x8 0x20000000 0xf0000000 + >; + }; + ecap1_pins: pinmux_ecap1_pins { + pinctrl-single,bits = < + /* ECAP1_APWM1 */ + 0x4 0x40000000 0xf0000000 + >; + }; + ecap2_pins: pinmux_ecap2_pins { + pinctrl-single,bits = < + /* ECAP2_APWM2 */ + 0x4 0x00000004 0x0000000f + >; + }; + spi1_pins: pinmux_spi_pins { + pinctrl-single,bits = < + /* SIMO, SOMI, CLK */ + 0x14 0x00110100 0x00ff0f00 + >; + }; + spi1_cs0_pin: pinmux_spi1_cs0 { + pinctrl-single,bits = < + /* CS0 */ + 0x14 0x00000010 0x000000f0 + >; + }; }; serial0: serial@1c42000 { compatible = "ns16550a"; @@ -122,6 +176,46 @@ interrupts = <16>; status = "disabled"; }; + ehrpwm0: ehrpwm@01f00000 { + compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x300000 0x2000>; + status = "disabled"; + }; + ehrpwm1: ehrpwm@01f02000 { + compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm"; + #pwm-cells = <3>; + reg = <0x302000 0x2000>; + status = "disabled"; + }; + ecap0: ecap@01f06000 { + compatible = "ti,da850-ecap", "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x306000 0x80>; + status = "disabled"; + }; + ecap1: ecap@01f07000 { + compatible = "ti,da850-ecap", "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x307000 0x80>; + status = "disabled"; + }; + ecap2: ecap@01f08000 { + compatible = "ti,da850-ecap", "ti,am33xx-ecap"; + #pwm-cells = <3>; + reg = <0x308000 0x80>; + status = "disabled"; + }; + spi1: spi@1f0e000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "ti,da830-spi"; + reg = <0x30e000 0x1000>; + num-cs = <4>; + ti,davinci-spi-intr-line = <1>; + interrupts = <56>; + status = "disabled"; + }; }; nand_cs3@62000000 { compatible = "ti,davinci-nand"; diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi index 9ac47d51c407..359694c78918 100644 --- a/arch/arm/boot/dts/exynos4.dtsi +++ b/arch/arm/boot/dts/exynos4.dtsi @@ -38,6 +38,11 @@ i2c7 = &i2c_7; }; + chipid@10000000 { + compatible = "samsung,exynos4210-chipid"; + reg = <0x10000000 0x100>; + }; + pd_mfc: mfc-power-domain@10023C40 { compatible = "samsung,exynos4210-pd"; reg = <0x10023C40 0x20>; @@ -82,6 +87,11 @@ reg = <0x10440000 0x1000>; }; + sys_reg: sysreg { + compatible = "samsung,exynos4-sysreg", "syscon"; + reg = <0x10010000 0x400>; + }; + watchdog@10060000 { compatible = "samsung,s3c2410-wdt"; reg = <0x10060000 0x100>; @@ -197,6 +207,8 @@ interrupts = <0 58 0>; clocks = <&clock 317>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_bus>; status = "disabled"; }; @@ -208,6 +220,8 @@ interrupts = <0 59 0>; clocks = <&clock 318>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_bus>; status = "disabled"; }; @@ -287,6 +301,8 @@ #size-cells = <0>; clocks = <&clock 327>, <&clock 159>; clock-names = "spi", "spi_busclk0"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_bus>; status = "disabled"; }; @@ -300,6 +316,8 @@ #size-cells = <0>; clocks = <&clock 328>, <&clock 160>; clock-names = "spi", "spi_busclk0"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_bus>; status = "disabled"; }; @@ -313,6 +331,16 @@ #size-cells = <0>; clocks = <&clock 329>, <&clock 161>; clock-names = "spi", "spi_busclk0"; + pinctrl-names = "default"; + pinctrl-0 = <&spi2_bus>; + status = "disabled"; + }; + + pwm@139D0000 { + compatible = "samsung,exynos4210-pwm"; + reg = <0x139D0000 0x1000>; + interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, <0 41 0>; + #pwm-cells = <2>; status = "disabled"; }; @@ -356,4 +384,16 @@ #dma-requests = <1>; }; }; + + fimd: fimd@11c00000 { + compatible = "samsung,exynos4210-fimd"; + interrupt-parent = <&combiner>; + reg = <0x11c00000 0x20000>; + interrupt-names = "fifo", "vsync", "lcd_sys"; + interrupts = <11 0>, <11 1>, <11 2>; + clocks = <&clock 140>, <&clock 283>; + clock-names = "sclk_fimd", "fimd"; + samsung,power-domain = <&pd_lcd0>; + status = "disabled"; + }; }; diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts index 1b30bc8e2654..524b90846df5 100644 --- a/arch/arm/boot/dts/exynos4210-origen.dts +++ b/arch/arm/boot/dts/exynos4210-origen.dts @@ -57,6 +57,10 @@ status = "okay"; }; + g2d@12800000 { + status = "okay"; + }; + codec@13400000 { samsung,mfc-r = <0x43000000 0x800000>; samsung,mfc-l = <0x51000000 0x800000>; diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts index f52c86e2d424..91332b72acf5 100644 --- a/arch/arm/boot/dts/exynos4210-smdkv310.dts +++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts @@ -30,16 +30,13 @@ }; sdhci@12530000 { - samsung,sdhci-bus-width = <4>; - linux,mmc_cap_4_bit_data; - samsung,sdhci-cd-internal; - gpio-cd = <&gpk2 2 2 3 3>; - gpios = <&gpk2 0 2 0 3>, - <&gpk2 1 2 0 3>, - <&gpk2 3 2 3 3>, - <&gpk2 4 2 3 3>, - <&gpk2 5 2 3 3>, - <&gpk2 6 2 3 3>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; + status = "okay"; + }; + + g2d@12800000 { status = "okay"; }; @@ -65,25 +62,32 @@ status = "okay"; }; + pinctrl@11000000 { + keypad_rows: keypad-rows { + samsung,pins = "gpx2-0", "gpx2-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + keypad_cols: keypad-cols { + samsung,pins = "gpx1-0", "gpx1-1", "gpx1-2", "gpx1-3", + "gpx1-4", "gpx1-5", "gpx1-6", "gpx1-7"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + }; + keypad@100A0000 { samsung,keypad-num-rows = <2>; samsung,keypad-num-columns = <8>; linux,keypad-no-autorepeat; linux,keypad-wakeup; + pinctrl-names = "default"; + pinctrl-0 = <&keypad_rows &keypad_cols>; status = "okay"; - row-gpios = <&gpx2 0 3 3 0>, - <&gpx2 1 3 3 0>; - - col-gpios = <&gpx1 0 3 0 0>, - <&gpx1 1 3 0 0>, - <&gpx1 2 3 0 0>, - <&gpx1 3 3 0 0>, - <&gpx1 4 3 0 0>, - <&gpx1 5 3 0 0>, - <&gpx1 6 3 0 0>, - <&gpx1 7 3 0 0>; - key_1 { keypad,row = <0>; keypad,column = <3>; @@ -149,9 +153,7 @@ #address-cells = <1>; #size-cells = <0>; samsung,i2c-sda-delay = <100>; - samsung,i2c-max-bus-freq = <20000>; - gpios = <&gpd1 0 2 3 0>, - <&gpd1 1 2 3 0>; + samsung,i2c-max-bus-freq = <100000>; status = "okay"; eeprom@50 { @@ -166,9 +168,6 @@ }; spi_2: spi@13940000 { - gpios = <&gpc1 1 5 3 0>, - <&gpc1 3 5 3 0>, - <&gpc1 4 5 3 0>; status = "okay"; w25x80@0 { @@ -179,7 +178,7 @@ spi-max-frequency = <1000000>; controller-data { - cs-gpio = <&gpc1 2 1 0 3>; + cs-gpio = <&gpc1 2 0>; samsung,spi-feedback-delay = <0>; }; diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts new file mode 100644 index 000000000000..345cdb51dcb7 --- /dev/null +++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts @@ -0,0 +1,352 @@ +/* + * Samsung's Exynos4210 based Universal C210 board device tree source + * + * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Device tree source file for Samsung's Universal C210 board which is based on + * Samsung's Exynos4210 rev0 SoC. + * + * 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/ "exynos4210.dtsi" + +/ { + model = "Samsung Universal C210 based on Exynos4210 rev0"; + compatible = "samsung,universal_c210", "samsung,exynos4210"; + + memory { + reg = <0x40000000 0x10000000 + 0x50000000 0x10000000>; + }; + + chosen { + bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1"; + }; + + mct@10050000 { + compatible = "none"; + }; + + fixed-rate-clocks { + xxti { + compatible = "samsung,clock-xxti"; + clock-frequency = <0>; + }; + + xusbxti { + compatible = "samsung,clock-xusbxti"; + clock-frequency = <24000000>; + }; + }; + + vemmc_reg: voltage-regulator { + compatible = "regulator-fixed"; + regulator-name = "VMEM_VDD_2_8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpe1 3 0>; + enable-active-high; + }; + + sdhci_emmc: sdhci@12510000 { + bus-width = <8>; + non-removable; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus8>; + pinctrl-names = "default"; + vmmc-supply = <&vemmc_reg>; + status = "okay"; + }; + + serial@13800000 { + status = "okay"; + }; + + serial@13810000 { + status = "okay"; + }; + + serial@13820000 { + status = "okay"; + }; + + serial@13830000 { + status = "okay"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + vol-up-key { + gpios = <&gpx2 0 1>; + linux,code = <115>; + label = "volume up"; + debounce-interval = <1>; + }; + + vol-down-key { + gpios = <&gpx2 1 1>; + linux,code = <114>; + label = "volume down"; + debounce-interval = <1>; + }; + + config-key { + gpios = <&gpx2 2 1>; + linux,code = <171>; + label = "config"; + debounce-interval = <1>; + gpio-key,wakeup; + }; + + camera-key { + gpios = <&gpx2 3 1>; + linux,code = <212>; + label = "camera"; + debounce-interval = <1>; + }; + + power-key { + gpios = <&gpx2 7 1>; + linux,code = <116>; + label = "power"; + debounce-interval = <1>; + gpio-key,wakeup; + }; + + ok-key { + gpios = <&gpx3 5 1>; + linux,code = <352>; + label = "ok"; + debounce-interval = <1>; + }; + }; + + tsp_reg: voltage-regulator { + compatible = "regulator-fixed"; + regulator-name = "TSP_2_8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpe2 3 0>; + enable-active-high; + }; + + i2c@13890000 { + samsung,i2c-sda-delay = <100>; + samsung,i2c-slave-addr = <0x10>; + samsung,i2c-max-bus-freq = <100000>; + pinctrl-0 = <&i2c3_bus>; + pinctrl-names = "default"; + status = "okay"; + + tsp@4a { + /* TBD: Atmel maXtouch touchscreen */ + reg = <0x4a>; + }; + }; + + i2c@138B0000 { + samsung,i2c-sda-delay = <100>; + samsung,i2c-slave-addr = <0x10>; + samsung,i2c-max-bus-freq = <100000>; + pinctrl-0 = <&i2c5_bus>; + pinctrl-names = "default"; + status = "okay"; + + vdd_arm_reg: pmic@60 { + compatible = "maxim,max8952"; + reg = <0x60>; + + max8952,vid-gpios = <&gpx0 3 0>, <&gpx0 4 0>; + max8952,default-mode = <0>; + max8952,dvs-mode-microvolt = <1250000>, <1200000>, + <1050000>, <950000>; + max8952,sync-freq = <0>; + max8952,ramp-speed = <0>; + + regulator-name = "vdd_arm"; + regulator-min-microvolt = <770000>; + regulator-max-microvolt = <1400000>; + regulator-always-on; + regulator-boot-on; + }; + + pmic@66 { + compatible = "national,lp3974"; + reg = <0x66>; + + max8998,pmic-buck1-default-dvs-idx = <0>; + max8998,pmic-buck1-dvs-gpios = <&gpx0 5 0>, + <&gpx0 6 0>; + max8998,pmic-buck1-dvs-voltage = <1100000>, <1000000>, + <1100000>, <1000000>; + + max8998,pmic-buck2-default-dvs-idx = <0>; + max8998,pmic-buck2-dvs-gpio = <&gpe2 0 0>; + max8998,pmic-buck2-dvs-voltage = <1200000>, <1100000>; + + regulators { + ldo2_reg: LDO2 { + regulator-name = "VALIVE_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + ldo3_reg: LDO3 { + regulator-name = "VUSB+MIPI_1.1V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + ldo4_reg: LDO4 { + regulator-name = "VADC_3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo5_reg: LDO5 { + regulator-name = "VTF_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo6_reg: LDO6 { + regulator-name = "LDO6"; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + }; + + ldo7_reg: LDO7 { + regulator-name = "VLCD+VMIPI_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo8_reg: LDO8 { + regulator-name = "VUSB+VDAC_3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo9_reg: LDO9 { + regulator-name = "VCC_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + ldo10_reg: LDO10 { + regulator-name = "VPLL_1.1V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo11_reg: LDO11 { + regulator-name = "CAM_AF_3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo12_reg: LDO12 { + regulator-name = "PS_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo13_reg: LDO13 { + regulator-name = "VHIC_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + ldo14_reg: LDO14 { + regulator-name = "CAM_I_HOST_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo15_reg: LDO15 { + regulator-name = "CAM_S_DIG+FM33_CORE_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + ldo16_reg: LDO16 { + regulator-name = "CAM_S_ANA_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + ldo17_reg: LDO17 { + regulator-name = "VCC_3.0V_LCD"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + }; + + buck1_reg: BUCK1 { + regulator-name = "VINT_1.1V"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + regulator-always-on; + }; + + buck2_reg: BUCK2 { + regulator-name = "VG3D_1.1V"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1500000>; + regulator-boot-on; + }; + + buck3_reg: BUCK3 { + regulator-name = "VCC_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + buck4_reg: BUCK4 { + regulator-name = "VMEM_1.2V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + ap32khz_reg: EN32KHz-AP { + regulator-name = "32KHz AP"; + regulator-always-on; + }; + + cp32khz_reg: EN32KHz-CP { + regulator-name = "32KHz CP"; + }; + + vichg_reg: ENVICHG { + regulator-name = "VICHG"; + }; + + safeout1_reg: ESAFEOUT1 { + regulator-name = "SAFEOUT1"; + regulator-always-on; + }; + + safeout2_reg: ESAFEOUT2 { + regulator-name = "SAFEOUT2"; + regulator-boot-on; + }; + }; + }; + }; + + pwm@139D0000 { + compatible = "samsung,s5p6440-pwm"; + status = "okay"; + }; +}; diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index 15143bdbafb8..54710de82908 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -41,6 +41,7 @@ }; combiner:interrupt-controller@10440000 { + samsung,combiner-nr = <16>; interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, @@ -112,4 +113,11 @@ reg = <0x100C0000 0x100>; interrupts = <2 4>; }; + + g2d@12800000 { + compatible = "samsung,s5pv210-g2d"; + reg = <0x12800000 0x1000>; + interrupts = <0 89 0>; + status = "disabled"; + }; }; diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi index 36d4299789ef..c0f60f49cea6 100644 --- a/arch/arm/boot/dts/exynos4212.dtsi +++ b/arch/arm/boot/dts/exynos4212.dtsi @@ -26,6 +26,15 @@ cpu-offset = <0x8000>; }; + interrupt-controller@10440000 { + samsung,combiner-nr = <18>; + interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, + <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, + <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, + <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>, + <0 107 0>, <0 108 0>; + }; + mct@10050000 { compatible = "samsung,exynos4412-mct"; reg = <0x10050000 0x800>; diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts index 1fecf7666dc0..1c21bad32ca9 100644 --- a/arch/arm/boot/dts/exynos4412-origen.dts +++ b/arch/arm/boot/dts/exynos4412-origen.dts @@ -72,6 +72,27 @@ status = "okay"; }; + fimd@11c00000 { + pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>; + pinctrl-names = "default"; + status = "okay"; + }; + + display-timings { + native-mode = <&timing0>; + timing0: timing { + clock-frequency = <50000>; + hactive = <1024>; + vactive = <600>; + hfront-porch = <64>; + hback-porch = <16>; + hsync-len = <48>; + vback-porch = <64>; + vfront-porch = <16>; + vsync-len = <3>; + }; + }; + serial@13800000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/exynos4412-smdk4412.dts index 874beeaef99d..dd564310d4a5 100644 --- a/arch/arm/boot/dts/exynos4412-smdk4412.dts +++ b/arch/arm/boot/dts/exynos4412-smdk4412.dts @@ -27,6 +27,14 @@ bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc"; }; + g2d@10800000 { + status = "okay"; + }; + + g2d@10800000 { + status = "okay"; + }; + sdhci@12530000 { bus-width = <4>; pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>; diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi index d75c047e80a9..270b389e0a1b 100644 --- a/arch/arm/boot/dts/exynos4412.dtsi +++ b/arch/arm/boot/dts/exynos4412.dtsi @@ -26,6 +26,15 @@ cpu-offset = <0x4000>; }; + interrupt-controller@10440000 { + samsung,combiner-nr = <20>; + interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, + <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, + <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, + <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>, + <0 107 0>, <0 108 0>, <0 48 0>, <0 42 0>; + }; + mct@10050000 { compatible = "samsung,exynos4412-mct"; reg = <0x10050000 0x800>; @@ -51,4 +60,12 @@ <0x7 0 &gic 1 12 0>; }; }; + + mshc@12550000 { + compatible = "samsung,exynos4412-dw-mshc"; + reg = <0x12550000 0x1000>; + interrupts = <0 77 0>; + #address-cells = <1>; + #size-cells = <0>; + }; }; diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi index 7496b8d633ea..e3380a7a285c 100644 --- a/arch/arm/boot/dts/exynos4x12.dtsi +++ b/arch/arm/boot/dts/exynos4x12.dtsi @@ -72,4 +72,11 @@ reg = <0x106E0000 0x1000>; interrupts = <0 72 0>; }; + + g2d@10800000 { + compatible = "samsung,exynos4212-g2d"; + reg = <0x10800000 0x1000>; + interrupts = <0 89 0>; + status = "disabled"; + }; }; diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 5de019cb0e58..02cfc76d002f 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -24,8 +24,266 @@ bootargs = "console=ttySAC2,115200"; }; + codec@11000000 { + samsung,mfc-r = <0x43000000 0x800000>; + samsung,mfc-l = <0x51000000 0x800000>; + }; + i2c@12C60000 { - status = "disabled"; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <20000>; + samsung,i2c-slave-addr = <0x66>; + + 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 0>, + <&gpd1 1 0>, + <&gpd1 2 0>; + s5m8767,pmic-buck-ds-gpios = <&gpx2 3 0>, + <&gpx2 4 0>, + <&gpx2 5 0>; + 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>; + }; + + ldo2_reg: LDO2 { + regulator-name = "VDD_28IO_DP_1.35V"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo3_reg: LDO3 { + regulator-name = "VDD_COMMON1_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo4_reg: LDO4 { + regulator-name = "VDD_IOPERI_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + op_mode = <1>; + }; + + ldo5_reg: LDO5 { + regulator-name = "VDD_EXT_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo6_reg: LDO6 { + regulator-name = "VDD_MPLL_1.1V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo7_reg: LDO7 { + regulator-name = "VDD_XPLL_1.1V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo8_reg: LDO8 { + regulator-name = "VDD_COMMON2_1.0V"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo9_reg: LDO9 { + regulator-name = "VDD_33ON_3.0V"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + op_mode = <1>; + }; + + ldo10_reg: LDO10 { + regulator-name = "VDD_COMMON3_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo11_reg: LDO11 { + regulator-name = "VDD_ABB2_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo12_reg: LDO12 { + regulator-name = "VDD_USB_3.0V"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo13_reg: LDO13 { + regulator-name = "VDDQ_C2C_W_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo14_reg: LDO14 { + regulator-name = "VDD18_ABB0_3_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo15_reg: LDO15 { + regulator-name = "VDD10_COMMON4_1.0V"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo16_reg: LDO16 { + regulator-name = "VDD18_HSIC_1.8V"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo17_reg: LDO17 { + regulator-name = "VDDQ_MMC2_3_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + ldo18_reg: LDO18 { + regulator-name = "VDD_33ON_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + op_mode = <1>; + }; + + ldo22_reg: LDO22 { + regulator-name = "EXT_33_OFF"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + op_mode = <1>; + }; + + ldo23_reg: LDO23 { + regulator-name = "EXT_28_OFF"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + op_mode = <1>; + }; + + ldo25_reg: LDO25 { + regulator-name = "PVDD_LDO25"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + op_mode = <1>; + }; + + ldo26_reg: LDO26 { + regulator-name = "EXT_18_OFF"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + op_mode = <1>; + }; + + buck1_reg: BUCK1 { + regulator-name = "vdd_mif"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + buck2_reg: BUCK2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + buck3_reg: BUCK3 { + regulator-name = "vdd_int"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + regulator-boot-on; + op_mode = <1>; + }; + + buck4_reg: BUCK4 { + regulator-name = "vdd_g3d"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-boot-on; + op_mode = <1>; + }; + + 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>; + }; + + buck9_reg: BUCK9 { + regulator-name = "VDD_33_OFF_EXT1"; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <3000000>; + op_mode = <1>; + }; + }; + }; }; i2c@12C70000 { @@ -69,15 +327,13 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <2 3>; samsung,dw-mshc-ddr-timing = <1 2>; + vmmc-supply = <&mmc_reg>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>; slot@0 { reg = <0>; bus-width = <8>; - gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>, - <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>, - <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>, - <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>, - <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>; }; }; @@ -93,14 +349,14 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <2 3>; samsung,dw-mshc-ddr-timing = <1 2>; + vmmc-supply = <&mmc_reg>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; 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>; + disable-wp; }; }; @@ -120,6 +376,73 @@ status = "disabled"; }; + gpio_keys { + compatible = "gpio-keys"; + + menu { + label = "SW-TACT2"; + gpios = <&gpx1 4 1>; + linux,code = <139>; + gpio-key,wakeup; + }; + + home { + label = "SW-TACT3"; + gpios = <&gpx1 5 1>; + linux,code = <102>; + gpio-key,wakeup; + }; + + up { + label = "SW-TACT4"; + gpios = <&gpx1 6 1>; + linux,code = <103>; + gpio-key,wakeup; + }; + + down { + label = "SW-TACT5"; + gpios = <&gpx1 7 1>; + linux,code = <108>; + gpio-key,wakeup; + }; + + back { + label = "SW-TACT6"; + gpios = <&gpx2 0 1>; + linux,code = <158>; + gpio-key,wakeup; + }; + + wakeup { + label = "SW-TACT7"; + gpios = <&gpx2 1 1>; + linux,code = <143>; + gpio-key,wakeup; + }; + }; + + hdmi { + hpd-gpio = <&gpx3 7 2>; + vdd_osc-supply = <&ldo10_reg>; + vdd_pll-supply = <&ldo8_reg>; + vdd-supply = <&ldo8_reg>; + }; + + mmc_reg: voltage-regulator { + compatible = "regulator-fixed"; + regulator-name = "VDD_33ON_2.8V"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpx1 1 1>; + enable-active-high; + }; + + reg_hdmi_en: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "hdmi-en"; + }; + fixed-rate-clocks { xxti { compatible = "samsung,clock-xxti"; diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi new file mode 100644 index 000000000000..d1650fb34c0a --- /dev/null +++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi @@ -0,0 +1,783 @@ +/* + * Samsung's Exynos5250 SoC pin-mux and pin-config device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos5250 SoC pin-mux and pin-config optiosn are listed as device + * tree nodes are listed in this file. + * + * 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. +*/ + +/ { + pinctrl@11400000 { + gpa0: gpa0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpa1: gpa1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpa2: gpa2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpb0: gpb0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpb1: gpb1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpb2: gpb2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpb3: gpb3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc2: gpc2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc3: gpc3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd0: gpd0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpy0: gpy0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy1: gpy1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy2: gpy2 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy3: gpy3 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy4: gpy4 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy5: gpy5 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy6: gpy6 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc4: gpc4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpx0: gpx0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&combiner>; + #interrupt-cells = <2>; + interrupts = <23 0>, <24 0>, <25 0>, <25 1>, + <26 0>, <26 1>, <27 0>, <27 1>; + }; + + gpx1: gpx1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&combiner>; + #interrupt-cells = <2>; + interrupts = <28 0>, <28 1>, <29 0>, <29 1>, + <30 0>, <30 1>, <31 0>, <31 1>; + }; + + gpx2: gpx2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpx3: gpx3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + uart0_data: uart0-data { + samsung,pins = "gpa0-0", "gpa0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart0_fctl: uart0-fctl { + samsung,pins = "gpa0-2", "gpa0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + + i2c2_bus: i2c2-bus { + samsung,pins = "gpa0-6", "gpa0-7"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + i2c2_hs_bus: i2c2-hs-bus { + samsung,pins = "gpa0-6", "gpa0-7"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + uart2_data: uart2-data { + samsung,pins = "gpa1-0", "gpa1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart2_fctl: uart2-fctl { + samsung,pins = "gpa1-2", "gpa1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + + i2c3_bus: i2c3-bus { + samsung,pins = "gpa1-2", "gpa1-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + i2c3_hs_bus: i2c3-hs-bus { + samsung,pins = "gpa1-2", "gpa1-3"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + uart3_data: uart3-data { + samsung,pins = "gpa1-4", "gpa1-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spi0_bus: spi0-bus { + samsung,pins = "gpa2-0", "gpa2-2", "gpa2-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c4_bus: i2c4-bus { + samsung,pins = "gpa2-0", "gpa2-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + i2c5_bus: i2c5-bus { + samsung,pins = "gpa2-2", "gpa2-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + spi1_bus: spi1-bus { + samsung,pins = "gpa2-4", "gpa2-6", "gpa2-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2s1_bus: i2s1-bus { + samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3", + "gpb0-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pcm1_bus: pcm1-bus { + samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3", + "gpb0-4"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + ac97_bus: ac97-bus { + samsung,pins = "gpb0-0", "gpb0-1", "gpb0-2", "gpb0-3", + "gpb0-4"; + samsung,pin-function = <4>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2s2_bus: i2s2-bus { + samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2", "gpb1-3", + "gpb1-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pcm2_bus: pcm2-bus { + samsung,pins = "gpb1-0", "gpb1-1", "gpb1-2", "gpb1-3", + "gpb1-4"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spdif_bus: spdif-bus { + samsung,pins = "gpb1-0", "gpb1-1"; + samsung,pin-function = <4>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spi2_bus: spi2-bus { + samsung,pins = "gpb1-1", "gpb1-3", "gpb1-4"; + samsung,pin-function = <5>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c6_bus: i2c6-bus { + samsung,pins = "gpb1-3", "gpb1-4"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c7_bus: i2c7-bus { + samsung,pins = "gpb2-2", "gpb2-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c0_bus: i2c0-bus { + samsung,pins = "gpb3-0", "gpb3-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c1_bus: i2c1-bus { + samsung,pins = "gpb3-2", "gpb3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c0_hs_bus: i2c0-hs-bus { + samsung,pins = "gpb3-0", "gpb3-1"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + i2c1_hs_bus: i2c1-hs-bus { + samsung,pins = "gpb3-2", "gpb3-3"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + sd0_clk: sd0-clk { + samsung,pins = "gpc0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd0_cmd: sd0-cmd { + samsung,pins = "gpc0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd0_cd: sd0-cd { + samsung,pins = "gpc0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus1: sd0-bus-width1 { + samsung,pins = "gpc0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus4: sd0-bus-width4 { + samsung,pins = "gpc0-3", "gpc0-4", "gpc0-5", "gpc0-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus8: sd0-bus-width8 { + samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_clk: sd1-clk { + samsung,pins = "gpc2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd1_cmd: sd1-cmd { + samsung,pins = "gpc2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd1_cd: sd1-cd { + samsung,pins = "gpc2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_bus1: sd1-bus-width1 { + samsung,pins = "gpc2-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_bus4: sd1-bus-width4 { + samsung,pins = "gpc2-3", "gpc2-4", "gpc2-5", "gpc2-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_clk: sd2-clk { + samsung,pins = "gpc3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cmd: sd2-cmd { + samsung,pins = "gpc3-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cd: sd2-cd { + samsung,pins = "gpc3-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus1: sd2-bus-width1 { + samsung,pins = "gpc3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus4: sd2-bus-width4 { + samsung,pins = "gpc3-3", "gpc3-4", "gpc3-5", "gpc3-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus8: sd2-bus-width8 { + samsung,pins = "gpc4-3", "gpc4-4", "gpc4-5", "gpc4-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd3_clk: sd3-clk { + samsung,pins = "gpc4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd3_cmd: sd3-cmd { + samsung,pins = "gpc4-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd3_cd: sd3-cd { + samsung,pins = "gpc4-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd3_bus1: sd3-bus-width1 { + samsung,pins = "gpc4-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd3_bus4: sd3-bus-width4 { + samsung,pins = "gpc4-3", "gpc4-4", "gpc4-5", "gpc4-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + uart1_data: uart1-data { + samsung,pins = "gpd0-0", "gpd0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart1_fctl: uart1-fctl { + samsung,pins = "gpd0-2", "gpd0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + }; + + pinctrl@13400000 { + gpe0: gpe0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpe1: gpe1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf0: gpf0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf1: gpf1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg0: gpg0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg1: gpg1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg2: gpg2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gph0: gph0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gph1: gph1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + cam_gpio_a: cam-gpio-a { + samsung,pins = "gpe0-0", "gpe0-1", "gpe0-2", "gpe0-3", + "gpe0-4", "gpe0-5", "gpe0-6", "gpe0-7", + "gpe1-0", "gpe1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + cam_gpio_b: cam-gpio-b { + samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3", + "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + + cam_i2c2_bus: cam-i2c2-bus { + samsung,pins = "gpe0-6", "gpe1-0"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + cam_spi1_bus: cam-spi1-bus { + samsung,pins = "gpe0-4", "gpe0-5", "gpf0-2", "gpf0-3"; + samsung,pin-function = <4>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + + cam_i2c1_bus: cam-i2c1-bus { + samsung,pins = "gpf0-2", "gpf0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + cam_i2c0_bus: cam-i2c0-bus { + samsung,pins = "gpf0-0", "gpf0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samaung,pin-drv = <0>; + }; + + cam_spi0_bus: cam-spi0-bus { + samsung,pins = "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + + cam_bayrgb_bus: cam-bayrgb-bus { + samsung,pins = "gpg0-0", "gpg0-1", "gpg0-2", "gpg0-3", + "gpg0-4", "gpg0-5", "gpg0-6", "gpg0-7", + "gpg1-0", "gpg1-1", "gpg1-2", "gpg1-3", + "gpg1-4", "gpg1-5", "gpg1-6", "gpg1-7", + "gpg2-0", "gpg2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + + cam_port_a: cam-port-a { + samsung,pins = "gph0-0", "gph0-1", "gph0-2", "gph0-3", + "gph1-0", "gph1-1", "gph1-2", "gph1-3", + "gph1-4", "gph1-5", "gph1-6", "gph1-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + }; + + pinctrl@10d10000 { + gpv0: gpv0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv1: gpv1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv2: gpv2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv3: gpv3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv4: gpv4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + c2c_rxd: c2c-rxd { + samsung,pins = "gpv0-0", "gpv0-1", "gpv0-2", "gpv0-3", + "gpv0-4", "gpv0-5", "gpv0-6", "gpv0-7", + "gpv1-0", "gpv1-1", "gpv1-2", "gpv1-3", + "gpv1-4", "gpv1-5", "gpv1-6", "gpv1-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + + c2c_txd: c2c-txd { + samsung,pins = "gpv2-0", "gpv2-1", "gpv2-2", "gpv2-3", + "gpv2-4", "gpv2-5", "gpv2-6", "gpv2-7", + "gpv3-0", "gpv3-1", "gpv3-2", "gpv3-3", + "gpv3-4", "gpv3-5", "gpv3-6", "gpv3-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samaung,pin-drv = <0>; + }; + }; + + pinctrl@03680000 { + gpz: gpz { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + i2s0_bus: i2s0-bus { + samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3", + "gpz-4", "gpz-5", "gpz-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + }; +}; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 872ae1f93c75..3e0c792e2767 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -30,8 +30,6 @@ i2c@12C60000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <20000>; - gpios = <&gpb3 0 2 3 0>, - <&gpb3 1 2 3 0>; eeprom@50 { compatible = "samsung,s524ad0xd1"; @@ -42,8 +40,6 @@ i2c@12C70000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <20000>; - gpios = <&gpb3 2 2 3 0>, - <&gpb3 3 2 3 0>; eeprom@51 { compatible = "samsung,s524ad0xd1"; @@ -74,8 +70,6 @@ i2c@12C80000 { samsung,i2c-sda-delay = <100>; samsung,i2c-max-bus-freq = <66000>; - gpios = <&gpa0 6 3 3 0>, - <&gpa0 7 3 3 0>; hdmiddc@50 { compatible = "samsung,exynos5-hdmiddc"; @@ -122,15 +116,12 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <2 3>; samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>; 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>; }; }; @@ -146,17 +137,13 @@ samsung,dw-mshc-ciu-div = <3>; samsung,dw-mshc-sdr-timing = <2 3>; samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; slot@0 { reg = <0>; bus-width = <4>; - samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>; disable-wp; - 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>; }; }; @@ -169,10 +156,6 @@ }; spi_1: spi@12d30000 { - gpios = <&gpa2 4 2 3 0>, - <&gpa2 6 2 3 0>, - <&gpa2 7 2 3 0>; - w25q80bw@0 { #address-cells = <1>; #size-cells = <1>; @@ -181,7 +164,7 @@ spi-max-frequency = <1000000>; controller-data { - cs-gpio = <&gpa2 5 1 0 3>; + cs-gpio = <&gpa2 5 0>; samsung,spi-feedback-delay = <0>; }; @@ -203,7 +186,7 @@ }; hdmi { - hpd-gpio = <&gpx3 7 0xf 1 3>; + hpd-gpio = <&gpx3 7 0>; }; codec@11000000 { @@ -212,9 +195,7 @@ }; i2s0: i2s@03830000 { - gpios = <&gpz 0 2 0 0>, <&gpz 1 2 0 0>, <&gpz 2 2 0 0>, - <&gpz 3 2 0 0>, <&gpz 4 2 0 0>, <&gpz 5 2 0 0>, - <&gpz 6 2 0 0>; + status = "okay"; }; i2s1: i2s@12D60000 { @@ -233,7 +214,7 @@ }; usb@12110000 { - samsung,vbus-gpio = <&gpx2 6 1 3 3>; + samsung,vbus-gpio = <&gpx2 6 0>; }; dp-controller { @@ -245,6 +226,22 @@ samsung,lane-count = <4>; }; + display-timings { + native-mode = <&timing0>; + timing0: timing@0 { + /* 1280x800 */ + clock-frequency = <50000>; + hactive = <1280>; + vactive = <800>; + hfront-porch = <4>; + hback-porch = <4>; + hsync-len = <4>; + vback-porch = <4>; + vfront-porch = <4>; + vsync-len = <4>; + }; + }; + fixed-rate-clocks { xxti { compatible = "samsung,clock-xxti"; diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index babd9f9b1bf9..d449feb7e143 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -16,12 +16,31 @@ model = "Google Snow"; compatible = "google,snow", "samsung,exynos5250"; + aliases { + i2c104 = &i2c_104; + }; + + pinctrl@11400000 { + sd3_clk: sd3-clk { + samsung,pin-drv = <0>; + }; + + sd3_cmd: sd3-cmd { + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd3_bus4: sd3-bus-width4 { + samsung,pin-drv = <0>; + }; + }; + gpio-keys { compatible = "gpio-keys"; lid-switch { label = "Lid"; - gpios = <&gpx3 5 0 0x10000 0>; + gpios = <&gpx3 5 1>; linux,input-type = <5>; /* EV_SW */ linux,code = <0>; /* SW_LID */ debounce-interval = <1>; @@ -29,20 +48,142 @@ }; }; + i2c-arbitrator { + compatible = "i2c-arb-gpio-challenge"; + #address-cells = <1>; + #size-cells = <0>; + + i2c-parent = <&{/i2c@12CA0000}>; + + our-claim-gpio = <&gpf0 3 1>; + their-claim-gpios = <&gpe0 4 1>; + slew-delay-us = <10>; + wait-retry-us = <3000>; + wait-free-us = <50000>; + + /* Use ID 104 as a hint that we're on physical bus 4 */ + i2c_104: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + battery: sbs-battery@b { + compatible = "sbs,sbs-battery"; + reg = <0xb>; + sbs,poll-retry-count = <1>; + }; + + ec: embedded-controller { + compatible = "google,cros-ec-i2c"; + reg = <0x1e>; + interrupts = <6 0>; + interrupt-parent = <&gpx1>; + wakeup-source; + + keyboard-controller { + compatible = "google,cros-ec-keyb"; + keypad,num-rows = <8>; + keypad,num-columns = <13>; + google,needs-ghost-filter; + linux,keymap = <0x0001003a /* CAPSLK */ + 0x0002003b /* F1 */ + 0x00030030 /* B */ + 0x00040044 /* F10 */ + 0x00060031 /* N */ + 0x0008000d /* = */ + 0x000a0064 /* R_ALT */ + + 0x01010001 /* ESC */ + 0x0102003e /* F4 */ + 0x01030022 /* G */ + 0x01040041 /* F7 */ + 0x01060023 /* H */ + 0x01080028 /* ' */ + 0x01090043 /* F9 */ + 0x010b000e /* BKSPACE */ + + 0x0200001d /* L_CTRL */ + 0x0201000f /* TAB */ + 0x0202003d /* F3 */ + 0x02030014 /* T */ + 0x02040040 /* F6 */ + 0x0205001b /* ] */ + 0x02060015 /* Y */ + 0x02070056 /* 102ND */ + 0x0208001a /* [ */ + 0x02090042 /* F8 */ + + 0x03010029 /* GRAVE */ + 0x0302003c /* F2 */ + 0x03030006 /* 5 */ + 0x0304003f /* F5 */ + 0x03060007 /* 6 */ + 0x0308000c /* - */ + 0x030b002b /* \ */ + + 0x04000061 /* R_CTRL */ + 0x0401001e /* A */ + 0x04020020 /* D */ + 0x04030021 /* F */ + 0x0404001f /* S */ + 0x04050025 /* K */ + 0x04060024 /* J */ + 0x04080027 /* ; */ + 0x04090026 /* L */ + 0x040b001c /* ENTER */ + + 0x0501002c /* Z */ + 0x0502002e /* C */ + 0x0503002f /* V */ + 0x0504002d /* X */ + 0x05050033 /* , */ + 0x05060032 /* M */ + 0x0507002a /* L_SHIFT */ + 0x05080035 /* / */ + 0x05090034 /* . */ + 0x050B0039 /* SPACE */ + + 0x06010002 /* 1 */ + 0x06020004 /* 3 */ + 0x06030005 /* 4 */ + 0x06040003 /* 2 */ + 0x06050009 /* 8 */ + 0x06060008 /* 7 */ + 0x0608000b /* 0 */ + 0x0609000a /* 9 */ + 0x060a0038 /* L_ALT */ + 0x060b006c /* DOWN */ + 0x060c006a /* RIGHT */ + + 0x07010010 /* Q */ + 0x07020012 /* E */ + 0x07030013 /* R */ + 0x07040011 /* W */ + 0x07050017 /* I */ + 0x07060016 /* U */ + 0x07070036 /* R_SHIFT */ + 0x07080019 /* P */ + 0x07090018 /* O */ + 0x070b0067 /* UP */ + 0x070c0069>; /* LEFT */ + }; + }; + }; + }; + /* * On Snow we've got SIP WiFi and so can keep drive strengths low to * reduce EMI. */ dwmmc3@12230000 { slot@0 { - gpios = <&gpc4 0 2 0 0>, <&gpc4 1 2 3 0>, - <&gpc4 3 2 3 0>, <&gpc4 4 2 3 0>, - <&gpc4 5 2 3 0>, <&gpc4 6 2 3 0>; + pinctrl-names = "default"; + pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_bus4>; }; }; usb@12110000 { - samsung,vbus-gpio = <&gpx1 1 1 3 3>; + samsung,vbus-gpio = <&gpx1 1 0>; }; fixed-rate-clocks { diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 28758e5dd15c..98dfc3ea5c0b 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -18,6 +18,7 @@ */ /include/ "skeleton.dtsi" +/include/ "exynos5250-pinctrl.dtsi" / { compatible = "samsung,exynos5250"; @@ -44,6 +45,15 @@ i2c6 = &i2c_6; i2c7 = &i2c_7; i2c8 = &i2c_8; + pinctrl0 = &pinctrl_0; + pinctrl1 = &pinctrl_1; + pinctrl2 = &pinctrl_2; + pinctrl3 = &pinctrl_3; + }; + + chipid@10000000 { + compatible = "samsung,exynos4210-chipid"; + reg = <0x10000000 0x100>; }; pd_gsc: gsc-power-domain@0x10044000 { @@ -63,10 +73,22 @@ }; gic:interrupt-controller@10481000 { - compatible = "arm,cortex-a9-gic"; + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; #interrupt-cells = <3>; interrupt-controller; - reg = <0x10481000 0x1000>, <0x10482000 0x2000>; + reg = <0x10481000 0x1000>, + <0x10482000 0x1000>, + <0x10484000 0x2000>, + <0x10486000 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; }; combiner:interrupt-controller@10440000 { @@ -115,6 +137,36 @@ interrupts = <1 2>, <22 4>; }; + pinctrl_0: pinctrl@11400000 { + compatible = "samsung,exynos5250-pinctrl"; + reg = <0x11400000 0x1000>; + interrupts = <0 46 0>; + + wakup_eint: wakeup-interrupt-controller { + compatible = "samsung,exynos4210-wakeup-eint"; + interrupt-parent = <&gic>; + interrupts = <0 32 0>; + }; + }; + + pinctrl_1: pinctrl@13400000 { + compatible = "samsung,exynos5250-pinctrl"; + reg = <0x13400000 0x1000>; + interrupts = <0 45 0>; + }; + + pinctrl_2: pinctrl@10d10000 { + compatible = "samsung,exynos5250-pinctrl"; + reg = <0x10d10000 0x1000>; + interrupts = <0 50 0>; + }; + + pinctrl_3: pinctrl@03680000 { + compatible = "samsung,exynos5250-pinctrl"; + reg = <0x0368000 0x1000>; + interrupts = <0 47 0>; + }; + watchdog { compatible = "samsung,s3c2410-wdt"; reg = <0x101D0000 0x100>; @@ -200,6 +252,8 @@ #size-cells = <0>; clocks = <&clock 294>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_bus>; }; i2c_1: i2c@12C70000 { @@ -210,6 +264,8 @@ #size-cells = <0>; clocks = <&clock 295>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_bus>; }; i2c_2: i2c@12C80000 { @@ -220,6 +276,8 @@ #size-cells = <0>; clocks = <&clock 296>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_bus>; }; i2c_3: i2c@12C90000 { @@ -230,6 +288,8 @@ #size-cells = <0>; clocks = <&clock 297>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_bus>; }; i2c_4: i2c@12CA0000 { @@ -240,6 +300,8 @@ #size-cells = <0>; clocks = <&clock 298>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_bus>; }; i2c_5: i2c@12CB0000 { @@ -250,6 +312,8 @@ #size-cells = <0>; clocks = <&clock 299>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_bus>; }; i2c_6: i2c@12CC0000 { @@ -260,6 +324,8 @@ #size-cells = <0>; clocks = <&clock 300>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6_bus>; }; i2c_7: i2c@12CD0000 { @@ -270,6 +336,8 @@ #size-cells = <0>; clocks = <&clock 301>; clock-names = "i2c"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7_bus>; }; i2c_8: i2c@12CE0000 { @@ -302,6 +370,8 @@ #size-cells = <0>; clocks = <&clock 304>, <&clock 154>; clock-names = "spi", "spi_busclk0"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_bus>; }; spi_1: spi@12d30000 { @@ -315,6 +385,8 @@ #size-cells = <0>; clocks = <&clock 305>, <&clock 155>; clock-names = "spi", "spi_busclk0"; + pinctrl-names = "default"; + pinctrl-0 = <&spi1_bus>; }; spi_2: spi@12d40000 { @@ -328,6 +400,8 @@ #size-cells = <0>; clocks = <&clock 306>, <&clock 156>; clock-names = "spi", "spi_busclk0"; + pinctrl-names = "default"; + pinctrl-0 = <&spi2_bus>; }; dwmmc_0: dwmmc0@12200000 { @@ -381,6 +455,8 @@ samsung,supports-rstclr; samsung,supports-secdai; samsung,idma-addr = <0x03000000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2s0_bus>; }; i2s1: i2s@12D60000 { @@ -389,6 +465,8 @@ dmas = <&pdma1 12 &pdma1 11>; dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s1_bus>; }; i2s2: i2s@12D70000 { @@ -397,18 +475,26 @@ dmas = <&pdma0 12 &pdma0 11>; dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s2_bus>; }; usb@12110000 { compatible = "samsung,exynos4210-ehci"; reg = <0x12110000 0x100>; interrupts = <0 71 0>; + + clocks = <&clock 285>; + clock-names = "usbhost"; }; usb@12120000 { compatible = "samsung,exynos4210-ohci"; reg = <0x12120000 0x100>; interrupts = <0 71 0>; + + clocks = <&clock 285>; + clock-names = "usbhost"; }; amba { @@ -463,254 +549,6 @@ }; }; - gpio-controllers { - #address-cells = <1>; - #size-cells = <1>; - gpio-controller; - ranges; - - gpa0: gpio-controller@11400000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400000 0x20>; - #gpio-cells = <4>; - }; - - gpa1: gpio-controller@11400020 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400020 0x20>; - #gpio-cells = <4>; - }; - - gpa2: gpio-controller@11400040 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400040 0x20>; - #gpio-cells = <4>; - }; - - gpb0: gpio-controller@11400060 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400060 0x20>; - #gpio-cells = <4>; - }; - - gpb1: gpio-controller@11400080 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400080 0x20>; - #gpio-cells = <4>; - }; - - gpb2: gpio-controller@114000A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000A0 0x20>; - #gpio-cells = <4>; - }; - - gpb3: gpio-controller@114000C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000C0 0x20>; - #gpio-cells = <4>; - }; - - gpc0: gpio-controller@114000E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000E0 0x20>; - #gpio-cells = <4>; - }; - - gpc1: gpio-controller@11400100 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400100 0x20>; - #gpio-cells = <4>; - }; - - gpc2: gpio-controller@11400120 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400120 0x20>; - #gpio-cells = <4>; - }; - - gpc3: gpio-controller@11400140 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400140 0x20>; - #gpio-cells = <4>; - }; - - gpc4: gpio-controller@114002E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114002E0 0x20>; - #gpio-cells = <4>; - }; - - gpd0: gpio-controller@11400160 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400160 0x20>; - #gpio-cells = <4>; - }; - - gpd1: gpio-controller@11400180 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400180 0x20>; - #gpio-cells = <4>; - }; - - gpy0: gpio-controller@114001A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001A0 0x20>; - #gpio-cells = <4>; - }; - - gpy1: gpio-controller@114001C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001C0 0x20>; - #gpio-cells = <4>; - }; - - gpy2: gpio-controller@114001E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001E0 0x20>; - #gpio-cells = <4>; - }; - - gpy3: gpio-controller@11400200 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400200 0x20>; - #gpio-cells = <4>; - }; - - gpy4: gpio-controller@11400220 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400220 0x20>; - #gpio-cells = <4>; - }; - - gpy5: gpio-controller@11400240 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400240 0x20>; - #gpio-cells = <4>; - }; - - gpy6: gpio-controller@11400260 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400260 0x20>; - #gpio-cells = <4>; - }; - - gpx0: gpio-controller@11400C00 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400C00 0x20>; - #gpio-cells = <4>; - }; - - gpx1: gpio-controller@11400C20 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400C20 0x20>; - #gpio-cells = <4>; - }; - - gpx2: gpio-controller@11400C40 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400C40 0x20>; - #gpio-cells = <4>; - }; - - gpx3: gpio-controller@11400C60 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400C60 0x20>; - #gpio-cells = <4>; - }; - - gpe0: gpio-controller@13400000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x13400000 0x20>; - #gpio-cells = <4>; - }; - - gpe1: gpio-controller@13400020 { - compatible = "samsung,exynos4-gpio"; - reg = <0x13400020 0x20>; - #gpio-cells = <4>; - }; - - gpf0: gpio-controller@13400040 { - compatible = "samsung,exynos4-gpio"; - reg = <0x13400040 0x20>; - #gpio-cells = <4>; - }; - - gpf1: gpio-controller@13400060 { - compatible = "samsung,exynos4-gpio"; - reg = <0x13400060 0x20>; - #gpio-cells = <4>; - }; - - gpg0: gpio-controller@13400080 { - compatible = "samsung,exynos4-gpio"; - reg = <0x13400080 0x20>; - #gpio-cells = <4>; - }; - - gpg1: gpio-controller@134000A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x134000A0 0x20>; - #gpio-cells = <4>; - }; - - gpg2: gpio-controller@134000C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x134000C0 0x20>; - #gpio-cells = <4>; - }; - - gph0: gpio-controller@134000E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x134000E0 0x20>; - #gpio-cells = <4>; - }; - - gph1: gpio-controller@13400100 { - compatible = "samsung,exynos4-gpio"; - reg = <0x13400100 0x20>; - #gpio-cells = <4>; - }; - - gpv0: gpio-controller@10D10000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x10D10000 0x20>; - #gpio-cells = <4>; - }; - - gpv1: gpio-controller@10D10020 { - compatible = "samsung,exynos4-gpio"; - reg = <0x10D10020 0x20>; - #gpio-cells = <4>; - }; - - gpv2: gpio-controller@10D10040 { - compatible = "samsung,exynos4-gpio"; - reg = <0x10D10060 0x20>; - #gpio-cells = <4>; - }; - - gpv3: gpio-controller@10D10060 { - compatible = "samsung,exynos4-gpio"; - reg = <0x10D10080 0x20>; - #gpio-cells = <4>; - }; - - gpv4: gpio-controller@10D10080 { - compatible = "samsung,exynos4-gpio"; - reg = <0x10D100C0 0x20>; - #gpio-cells = <4>; - }; - - gpz: gpio-controller@03860000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x03860000 0x20>; - #gpio-cells = <4>; - }; - }; - - gsc_0: gsc@0x13e00000 { compatible = "samsung,exynos5-gsc"; reg = <0x13e00000 0x1000>; @@ -776,4 +614,14 @@ samsung,enable-mask = <1>; }; }; + + fimd { + compatible = "samsung,exynos5250-fimd"; + interrupt-parent = <&combiner>; + reg = <0x14400000 0x40000>; + interrupt-names = "fifo", "vsync", "lcd_sys"; + interrupts = <18 4>, <18 5>, <18 6>; + clocks = <&clock 133>, <&clock 339>; + clock-names = "sclk_fimd", "fimd"; + }; }; diff --git a/arch/arm/boot/dts/exynos5440-sd5v1.dts b/arch/arm/boot/dts/exynos5440-sd5v1.dts new file mode 100644 index 000000000000..ef747b52b674 --- /dev/null +++ b/arch/arm/boot/dts/exynos5440-sd5v1.dts @@ -0,0 +1,39 @@ +/* + * SAMSUNG SD5v1 board device tree source + * + * Copyright (c) 2013 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/ "exynos5440.dtsi" + +/ { + model = "SAMSUNG SD5v1 board based on EXYNOS5440"; + compatible = "samsung,sd5v1", "samsung,exynos5440"; + + chosen { + bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel early_printk no_console_suspend mem=2048M@0x80000000 console=ttySAC0,115200"; + }; + + fixed-rate-clocks { + xtal { + compatible = "samsung,clock-xtal"; + clock-frequency = <50000000>; + }; + }; + + gmac: ethernet@00230000 { + fixed_phy; + phy_addr = <1>; + }; + + spi { + status = "disabled"; + }; + +}; diff --git a/arch/arm/boot/dts/exynos5440-ssdk5440.dts b/arch/arm/boot/dts/exynos5440-ssdk5440.dts index a21eb4cbe893..d55042beb5c5 100644 --- a/arch/arm/boot/dts/exynos5440-ssdk5440.dts +++ b/arch/arm/boot/dts/exynos5440-ssdk5440.dts @@ -16,12 +16,8 @@ model = "SAMSUNG SSDK5440 board based on EXYNOS5440"; compatible = "samsung,ssdk5440", "samsung,exynos5440"; - memory { - reg = <0x80000000 0x80000000>; - }; - chosen { - bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x81000000,8M console=ttySAC0,115200 init=/linuxrc"; + bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel early_printk no_console_suspend mem=2048M@0x80000000 console=ttySAC0,115200"; }; spi { diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi index 48cc96aa0b5f..f6b1c8973845 100644 --- a/arch/arm/boot/dts/exynos5440.dtsi +++ b/arch/arm/boot/dts/exynos5440.dtsi @@ -26,7 +26,11 @@ compatible = "arm,cortex-a15-gic"; #interrupt-cells = <3>; interrupt-controller; - reg = <0x2E1000 0x1000>, <0x2E2000 0x1000>; + reg = <0x2E1000 0x1000>, + <0x2E2000 0x1000>, + <0x2E4000 0x2000>, + <0x2E6000 0x2000>; + interrupts = <1 9 0xf04>; }; cpus { @@ -51,6 +55,14 @@ }; }; + arm-pmu { + compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu"; + interrupts = <0 52 4>, + <0 53 4>, + <0 54 4>, + <0 55 4>; + }; + timer { compatible = "arm,cortex-a15-timer", "arm,armv7-timer"; @@ -61,6 +73,18 @@ clock-frequency = <50000000>; }; + cpufreq@160000 { + compatible = "samsung,exynos5440-cpufreq"; + reg = <0x160000 0x1000>; + interrupts = <0 57 0>; + operating-points = < + /* KHz uV */ + 1200000 1025000 + 1000000 975000 + 800000 925000 + >; + }; + serial@B0000 { compatible = "samsung,exynos4210-uart"; reg = <0xB0000 0x1000>; @@ -92,6 +116,8 @@ pinctrl { compatible = "samsung,exynos5440-pinctrl"; reg = <0xE0000 0x1000>; + interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, + <0 41 0>, <0 42 0>, <0 43 0>, <0 44 0>; interrupt-controller; #interrupt-cells = <2>; #gpio-cells = <2>; @@ -141,6 +167,17 @@ clock-names = "watchdog"; }; + gmac: ethernet@00230000 { + compatible = "snps,dwmac-3.70a"; + reg = <0x00230000 0x8000>; + interrupt-parent = <&gic>; + interrupts = <0 31 4>; + interrupt-names = "macirq"; + phy-mode = "sgmii"; + clocks = <&clock 25>; + clock-names = "stmmaceth"; + }; + amba { #address-cells = <1>; #size-cells = <1>; @@ -148,22 +185,22 @@ interrupt-parent = <&gic>; ranges; - pdma0: pdma@121A0000 { + pdma0: pdma@00121000 { compatible = "arm,pl330", "arm,primecell"; - reg = <0x120000 0x1000>; - interrupts = <0 34 0>; - clocks = <&clock 21>; + reg = <0x121000 0x1000>; + interrupts = <0 46 0>; + clocks = <&clock 8>; clock-names = "apb_pclk"; #dma-cells = <1>; #dma-channels = <8>; #dma-requests = <32>; }; - pdma1: pdma@121B0000 { + pdma1: pdma@00120000 { compatible = "arm,pl330", "arm,primecell"; - reg = <0x121000 0x1000>; - interrupts = <0 35 0>; - clocks = <&clock 21>; + reg = <0x120000 0x1000>; + interrupts = <0 47 0>; + clocks = <&clock 8>; clock-names = "apb_pclk"; #dma-cells = <1>; #dma-channels = <8>; diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts index 035c13f9d3c0..da0588a04131 100644 --- a/arch/arm/boot/dts/imx23-evk.dts +++ b/arch/arm/boot/dts/imx23-evk.dts @@ -59,8 +59,33 @@ lcdif@80030000 { pinctrl-names = "default"; pinctrl-0 = <&lcdif_24bit_pins_a>; - panel-enable-gpios = <&gpio1 18 0>; + lcd-supply = <®_lcd_3v3>; + display = <&display>; status = "okay"; + + display: display { + bits-per-pixel = <32>; + bus-width = <24>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <9200000>; + hactive = <480>; + vactive = <272>; + hback-porch = <15>; + hfront-porch = <8>; + vback-porch = <12>; + vfront-porch = <4>; + hsync-len = <1>; + vsync-len = <1>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; }; }; @@ -95,6 +120,15 @@ regulator-max-microvolt = <3300000>; gpio = <&gpio1 29 0>; }; + + reg_lcd_3v3: lcd-3v3 { + compatible = "regulator-fixed"; + regulator-name = "lcd-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio1 18 0>; + enable-active-high; + }; }; backlight { diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts index e7484e4ea659..d107c4af321f 100644 --- a/arch/arm/boot/dts/imx23-olinuxino.dts +++ b/arch/arm/boot/dts/imx23-olinuxino.dts @@ -29,6 +29,7 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>; bus-width = <4>; + broken-cd; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index ad2d79324cd3..73fd7d0887b5 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -49,9 +49,15 @@ reg = <0x80000000 0x2000>; }; - dma-apbh@80004000 { + dma_apbh: dma-apbh@80004000 { compatible = "fsl,imx23-dma-apbh"; reg = <0x80004000 0x2000>; + interrupts = <0 14 20 0 + 13 13 13 13>; + interrupt-names = "empty", "ssp0", "ssp1", "empty", + "gpmi0", "gpmi1", "gpmi2", "gpmi3"; + #dma-cells = <1>; + dma-channels = <8>; clocks = <&clks 15>; }; @@ -70,6 +76,8 @@ interrupt-names = "gpmi-dma", "bch"; clocks = <&clks 34>; clock-names = "gpmi_io"; + dmas = <&dma_apbh 4>; + dma-names = "rx-tx"; fsl,gpmi-dma-channel = <4>; status = "disabled"; }; @@ -78,6 +86,8 @@ reg = <0x80010000 0x2000>; interrupts = <15 14>; clocks = <&clks 33>; + dmas = <&dma_apbh 1>; + dma-names = "rx-tx"; fsl,ssp-dma-channel = <1>; status = "disabled"; }; @@ -305,9 +315,19 @@ status = "disabled"; }; - dma-apbx@80024000 { + dma_apbx: dma-apbx@80024000 { compatible = "fsl,imx23-dma-apbx"; reg = <0x80024000 0x2000>; + interrupts = <7 5 9 26 + 19 0 25 23 + 60 58 9 0 + 0 0 0 0>; + interrupt-names = "audio-adc", "audio-dac", "spdif-tx", "i2c", + "saif0", "empty", "auart0-rx", "auart0-tx", + "auart1-rx", "auart1-tx", "saif1", "empty", + "empty", "empty", "empty", "empty"; + #dma-cells = <1>; + dma-channels = <16>; clocks = <&clks 16>; }; @@ -344,6 +364,8 @@ reg = <0x80034000 0x2000>; interrupts = <2 20>; clocks = <&clks 33>; + dmas = <&dma_apbh 2>; + dma-names = "rx-tx"; fsl,ssp-dma-channel = <2>; status = "disabled"; }; @@ -369,6 +391,8 @@ saif0: saif@80042000 { reg = <0x80042000 0x2000>; + dmas = <&dma_apbx 4>; + dma-names = "rx-tx"; status = "disabled"; }; @@ -379,16 +403,22 @@ saif1: saif@80046000 { reg = <0x80046000 0x2000>; + dmas = <&dma_apbx 10>; + dma-names = "rx-tx"; status = "disabled"; }; audio-out@80048000 { reg = <0x80048000 0x2000>; + dmas = <&dma_apbx 1>; + dma-names = "tx"; status = "disabled"; }; audio-in@8004c000 { reg = <0x8004c000 0x2000>; + dmas = <&dma_apbx 0>; + dma-names = "rx"; status = "disabled"; }; @@ -401,11 +431,15 @@ spdif@80054000 { reg = <0x80054000 2000>; + dmas = <&dma_apbx 2>; + dma-names = "tx"; status = "disabled"; }; i2c@80058000 { reg = <0x80058000 0x2000>; + dmas = <&dma_apbx 3>; + dma-names = "rx-tx"; status = "disabled"; }; @@ -436,6 +470,8 @@ reg = <0x8006c000 0x2000>; interrupts = <24 25 23>; clocks = <&clks 32>; + dmas = <&dma_apbx 6>, <&dma_apbx 7>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -444,6 +480,8 @@ reg = <0x8006e000 0x2000>; interrupts = <59 60 58>; clocks = <&clks 32>; + dmas = <&dma_apbx 8>, <&dma_apbx 9>; + dma-names = "rx", "tx"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts index 6d8865bfb4b7..3d905d16cbec 100644 --- a/arch/arm/boot/dts/imx28-apf28dev.dts +++ b/arch/arm/boot/dts/imx28-apf28dev.dts @@ -72,7 +72,32 @@ pinctrl-names = "default"; pinctrl-0 = <&lcdif_16bit_pins_a &lcdif_pins_apf28dev>; + display = <&display>; status = "okay"; + + display: display { + bits-per-pixel = <16>; + bus-width = <16>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <33000033>; + hactive = <800>; + vactive = <480>; + hback-porch = <96>; + hfront-porch = <96>; + vback-porch = <20>; + vfront-porch = <21>; + hsync-len = <64>; + vsync-len = <4>; + hsync-active = <1>; + vsync-active = <1>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; }; }; diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts index 5171667a7763..43bf3c796cba 100644 --- a/arch/arm/boot/dts/imx28-apx4devkit.dts +++ b/arch/arm/boot/dts/imx28-apx4devkit.dts @@ -94,7 +94,32 @@ pinctrl-names = "default"; pinctrl-0 = <&lcdif_24bit_pins_a &lcdif_pins_apx4>; + display = <&display>; status = "okay"; + + display: display { + bits-per-pixel = <32>; + bus-width = <24>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <30000000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hfront-porch = <40>; + vback-porch = <32>; + vfront-porch = <13>; + hsync-len = <48>; + vsync-len = <3>; + hsync-active = <1>; + vsync-active = <1>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; }; }; diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts index a0d3e9f1738e..063e62059890 100644 --- a/arch/arm/boot/dts/imx28-cfa10049.dts +++ b/arch/arm/boot/dts/imx28-cfa10049.dts @@ -30,7 +30,6 @@ reg = <0>; fsl,pinmux-ids = < 0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */ - 0x1153 /* MX28_PAD_LCD_D22__GPIO_1_21 */ 0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */ 0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */ 0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */ @@ -120,13 +119,48 @@ fsl,voltage = <1>; fsl,pull-up = <0>; }; + + w1_gpio_pins: w1-gpio@0 { + reg = <0>; + fsl,pinmux-ids = < + 0x1153 /* MX28_PAD_LCD_D21__GPIO_1_21 */ + >; + fsl,drive-strength = <1>; + fsl,voltage = <1>; + fsl,pull-up = <0>; /* 0 will enable the keeper */ + }; }; lcdif@80030000 { pinctrl-names = "default"; pinctrl-0 = <&lcdif_18bit_pins_cfa10049 &lcdif_pins_cfa10049>; + display = <&display>; status = "okay"; + + display: display { + bits-per-pixel = <32>; + bus-width = <18>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <9216000>; + hactive = <320>; + vactive = <480>; + hback-porch = <2>; + hfront-porch = <2>; + vback-porch = <2>; + vfront-porch = <2>; + hsync-len = <15>; + vsync-len = <15>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; }; }; @@ -183,6 +217,11 @@ usbphy1: usbphy@8007e000 { status = "okay"; }; + + lradc@80050000 { + status = "okay"; + fsl,lradc-touchscreen-wires = <4>; + }; }; }; @@ -304,5 +343,14 @@ pwms = <&pwm 3 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; default-brightness-level = <6>; + + }; + + onewire@0 { + compatible = "w1-gpio"; + pinctrl-names = "default"; + pinctrl-0 = <&w1_gpio_pins>; + status = "okay"; + gpios = <&gpio1 21 0>; }; }; diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts index 2da316e04409..3637bf3b1d59 100644 --- a/arch/arm/boot/dts/imx28-evk.dts +++ b/arch/arm/boot/dts/imx28-evk.dts @@ -123,8 +123,33 @@ pinctrl-names = "default"; pinctrl-0 = <&lcdif_24bit_pins_a &lcdif_pins_evk>; - panel-enable-gpios = <&gpio3 30 0>; + lcd-supply = <®_lcd_3v3>; + display = <&display>; status = "okay"; + + display: display { + bits-per-pixel = <32>; + bus-width = <24>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <33500000>; + hactive = <800>; + vactive = <480>; + hback-porch = <89>; + hfront-porch = <164>; + vback-porch = <23>; + vfront-porch = <10>; + hsync-len = <10>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; }; can0: can@80032000 { @@ -285,6 +310,15 @@ gpio = <&gpio3 8 0>; enable-active-high; }; + + reg_lcd_3v3: lcd-3v3 { + compatible = "regulator-fixed"; + regulator-name = "lcd-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio3 30 0>; + enable-active-high; + }; }; sound { diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts index fd36e1cca104..5aa44e05c9f5 100644 --- a/arch/arm/boot/dts/imx28-m28evk.dts +++ b/arch/arm/boot/dts/imx28-m28evk.dts @@ -119,7 +119,32 @@ pinctrl-names = "default"; pinctrl-0 = <&lcdif_24bit_pins_a &lcdif_pins_m28>; + display = <&display>; status = "okay"; + + display: display { + bits-per-pixel = <16>; + bus-width = <18>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <33260000>; + hactive = <800>; + vactive = <480>; + hback-porch = <0>; + hfront-porch = <256>; + vback-porch = <0>; + vfront-porch = <45>; + hsync-len = <1>; + vsync-len = <1>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; }; can0: can@80032000 { @@ -220,6 +245,8 @@ phy-mode = "rmii"; pinctrl-names = "default"; pinctrl-0 = <&mac0_pins_a>; + clocks = <&clks 57>, <&clks 57>; + clock-names = "ipg", "ahb"; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 64af2381c1b0..600f7cb51f3e 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -61,12 +61,24 @@ hsadc@80002000 { reg = <0x80002000 0x2000>; interrupts = <13 87>; + dmas = <&dma_apbh 12>; + dma-names = "rx"; status = "disabled"; }; - dma-apbh@80004000 { + dma_apbh: dma-apbh@80004000 { compatible = "fsl,imx28-dma-apbh"; reg = <0x80004000 0x2000>; + interrupts = <82 83 84 85 + 88 88 88 88 + 88 88 88 88 + 87 86 0 0>; + interrupt-names = "ssp0", "ssp1", "ssp2", "ssp3", + "gpmi0", "gmpi1", "gpmi2", "gmpi3", + "gpmi4", "gmpi5", "gpmi6", "gmpi7", + "hsadc", "lcdif", "empty", "empty"; + #dma-cells = <1>; + dma-channels = <16>; clocks = <&clks 25>; }; @@ -86,6 +98,8 @@ interrupt-names = "gpmi-dma", "bch"; clocks = <&clks 50>; clock-names = "gpmi_io"; + dmas = <&dma_apbh 4>; + dma-names = "rx-tx"; fsl,gpmi-dma-channel = <4>; status = "disabled"; }; @@ -96,6 +110,8 @@ reg = <0x80010000 0x2000>; interrupts = <96 82>; clocks = <&clks 46>; + dmas = <&dma_apbh 0>; + dma-names = "rx-tx"; fsl,ssp-dma-channel = <0>; status = "disabled"; }; @@ -106,6 +122,8 @@ reg = <0x80012000 0x2000>; interrupts = <97 83>; clocks = <&clks 47>; + dmas = <&dma_apbh 1>; + dma-names = "rx-tx"; fsl,ssp-dma-channel = <1>; status = "disabled"; }; @@ -116,6 +134,8 @@ reg = <0x80014000 0x2000>; interrupts = <98 84>; clocks = <&clks 48>; + dmas = <&dma_apbh 2>; + dma-names = "rx-tx"; fsl,ssp-dma-channel = <2>; status = "disabled"; }; @@ -126,6 +146,8 @@ reg = <0x80016000 0x2000>; interrupts = <99 85>; clocks = <&clks 49>; + dmas = <&dma_apbh 3>; + dma-names = "rx-tx"; fsl,ssp-dma-channel = <3>; status = "disabled"; }; @@ -658,9 +680,19 @@ status = "disabled"; }; - dma-apbx@80024000 { + dma_apbx: dma-apbx@80024000 { compatible = "fsl,imx28-dma-apbx"; reg = <0x80024000 0x2000>; + interrupts = <78 79 66 0 + 80 81 68 69 + 70 71 72 73 + 74 75 76 77>; + interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty", + "saif0", "saif1", "i2c0", "i2c1", + "auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx", + "auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx"; + #dma-cells = <1>; + dma-channels = <16>; clocks = <&clks 26>; }; @@ -692,6 +724,8 @@ reg = <0x80030000 0x2000>; interrupts = <38 86>; clocks = <&clks 55>; + dmas = <&dma_apbh 13>; + dma-names = "rx"; status = "disabled"; }; @@ -767,6 +801,8 @@ reg = <0x80042000 0x2000>; interrupts = <59 80>; clocks = <&clks 53>; + dmas = <&dma_apbx 4>; + dma-names = "rx-tx"; fsl,saif-dma-channel = <4>; status = "disabled"; }; @@ -781,6 +817,8 @@ reg = <0x80046000 0x2000>; interrupts = <58 81>; clocks = <&clks 54>; + dmas = <&dma_apbx 5>; + dma-names = "rx-tx"; fsl,saif-dma-channel = <5>; status = "disabled"; }; @@ -796,6 +834,8 @@ spdif@80054000 { reg = <0x80054000 0x2000>; interrupts = <45 66>; + dmas = <&dma_apbx 2>; + dma-names = "tx"; status = "disabled"; }; @@ -812,6 +852,8 @@ reg = <0x80058000 0x2000>; interrupts = <111 68>; clock-frequency = <100000>; + dmas = <&dma_apbx 6>; + dma-names = "rx-tx"; fsl,i2c-dma-channel = <6>; status = "disabled"; }; @@ -823,6 +865,8 @@ reg = <0x8005a000 0x2000>; interrupts = <110 69>; clock-frequency = <100000>; + dmas = <&dma_apbx 7>; + dma-names = "rx-tx"; fsl,i2c-dma-channel = <7>; status = "disabled"; }; @@ -847,6 +891,8 @@ compatible = "fsl,imx28-auart", "fsl,imx23-auart"; reg = <0x8006a000 0x2000>; interrupts = <112 70 71>; + dmas = <&dma_apbx 8>, <&dma_apbx 9>; + dma-names = "rx", "tx"; fsl,auart-dma-channel = <8 9>; clocks = <&clks 45>; status = "disabled"; @@ -856,6 +902,8 @@ compatible = "fsl,imx28-auart", "fsl,imx23-auart"; reg = <0x8006c000 0x2000>; interrupts = <113 72 73>; + dmas = <&dma_apbx 10>, <&dma_apbx 11>; + dma-names = "rx", "tx"; clocks = <&clks 45>; status = "disabled"; }; @@ -864,6 +912,8 @@ compatible = "fsl,imx28-auart", "fsl,imx23-auart"; reg = <0x8006e000 0x2000>; interrupts = <114 74 75>; + dmas = <&dma_apbx 12>, <&dma_apbx 13>; + dma-names = "rx", "tx"; clocks = <&clks 45>; status = "disabled"; }; @@ -872,6 +922,8 @@ compatible = "fsl,imx28-auart", "fsl,imx23-auart"; reg = <0x80070000 0x2000>; interrupts = <115 76 77>; + dmas = <&dma_apbx 14>, <&dma_apbx 15>; + dma-names = "rx", "tx"; clocks = <&clks 45>; status = "disabled"; }; @@ -880,6 +932,8 @@ compatible = "fsl,imx28-auart", "fsl,imx23-auart"; reg = <0x80072000 0x2000>; interrupts = <116 78 79>; + dmas = <&dma_apbx 0>, <&dma_apbx 1>; + dma-names = "rx", "tx"; clocks = <&clks 45>; status = "disabled"; }; @@ -943,8 +997,8 @@ compatible = "fsl,imx28-fec"; reg = <0x800f0000 0x4000>; interrupts = <101>; - clocks = <&clks 57>, <&clks 57>; - clock-names = "ipg", "ahb"; + clocks = <&clks 57>, <&clks 57>, <&clks 64>; + clock-names = "ipg", "ahb", "enet_out"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 3cca7d39529d..9e8296e4c343 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -65,9 +65,13 @@ interrupt-parent = <&intc>; ranges; - dma-apbh@00110000 { + dma_apbh: dma-apbh@00110000 { compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; reg = <0x00110000 0x2000>; + interrupts = <0 13 0x04>, <0 13 0x04>, <0 13 0x04>, <0 13 0x04>; + interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3"; + #dma-cells = <1>; + dma-channels = <4>; clocks = <&clks 106>; }; @@ -83,6 +87,8 @@ <&clks 150>, <&clks 149>; clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch"; + dmas = <&dma_apbh 0>; + dma-names = "rx-tx"; fsl,gpmi-dma-channel = <0>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts index 8b119399025a..ff1aea0ee043 100644 --- a/arch/arm/boot/dts/integratorcp.dts +++ b/arch/arm/boot/dts/integratorcp.dts @@ -24,15 +24,15 @@ }; timer0: timer@13000000 { - compatible = "arm,sp804", "arm,primecell"; + compatible = "arm,integrator-cp-timer"; }; timer1: timer@13000100 { - compatible = "arm,sp804", "arm,primecell"; + compatible = "arm,integrator-cp-timer"; }; timer2: timer@13000200 { - compatible = "arm,sp804", "arm,primecell"; + compatible = "arm,integrator-cp-timer"; }; pic: pic@14000000 { diff --git a/arch/arm/boot/dts/omap2.dtsi b/arch/arm/boot/dts/omap2.dtsi index 761c4b69b25b..37aa7487d4d8 100644 --- a/arch/arm/boot/dts/omap2.dtsi +++ b/arch/arm/boot/dts/omap2.dtsi @@ -26,6 +26,11 @@ }; }; + pmu { + compatible = "arm,arm1136-pmu"; + interrupts = <3>; + }; + soc { compatible = "ti,omap-infra"; mpu { @@ -49,6 +54,18 @@ reg = <0x480FE000 0x1000>; }; + sdma: dma-controller@48056000 { + compatible = "ti,omap2430-sdma", "ti,omap2420-sdma"; + reg = <0x48056000 0x1000>; + interrupts = <12>, + <13>, + <14>, + <15>; + #dma-cells = <1>; + #dma-channels = <32>; + #dma-requests = <64>; + }; + uart1: serial@4806a000 { compatible = "ti,omap2-uart"; ti,hwmods = "uart1"; @@ -68,28 +85,28 @@ }; timer2: timer@4802a000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x4802a000 0x400>; interrupts = <38>; ti,hwmods = "timer2"; }; timer3: timer@48078000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x48078000 0x400>; interrupts = <39>; ti,hwmods = "timer3"; }; timer4: timer@4807a000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x4807a000 0x400>; interrupts = <40>; ti,hwmods = "timer4"; }; timer5: timer@4807c000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x4807c000 0x400>; interrupts = <41>; ti,hwmods = "timer5"; @@ -97,7 +114,7 @@ }; timer6: timer@4807e000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x4807e000 0x400>; interrupts = <42>; ti,hwmods = "timer6"; @@ -105,7 +122,7 @@ }; timer7: timer@48080000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x48080000 0x400>; interrupts = <43>; ti,hwmods = "timer7"; @@ -113,7 +130,7 @@ }; timer8: timer@48082000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x48082000 0x400>; interrupts = <44>; ti,hwmods = "timer8"; @@ -121,7 +138,7 @@ }; timer9: timer@48084000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x48084000 0x400>; interrupts = <45>; ti,hwmods = "timer9"; @@ -129,7 +146,7 @@ }; timer10: timer@48086000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x48086000 0x400>; interrupts = <46>; ti,hwmods = "timer10"; @@ -137,7 +154,7 @@ }; timer11: timer@48088000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x48088000 0x400>; interrupts = <47>; ti,hwmods = "timer11"; @@ -145,7 +162,7 @@ }; timer12: timer@4808a000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x4808a000 0x400>; interrupts = <48>; ti,hwmods = "timer12"; diff --git a/arch/arm/boot/dts/omap2420-h4.dts b/arch/arm/boot/dts/omap2420-h4.dts index 9b0d07746cba..68282ee13e26 100644 --- a/arch/arm/boot/dts/omap2420-h4.dts +++ b/arch/arm/boot/dts/omap2420-h4.dts @@ -18,3 +18,49 @@ reg = <0x80000000 0x4000000>; /* 64 MB */ }; }; + +&gpmc { + ranges = <0 0 0x08000000 0x04000000>; + + nor@0,0 { + compatible = "cfi-flash"; + linux,mtd-name= "intel,ge28f256l18b85"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0 0 0x04000000>; + bank-width = <2>; + + gpmc,mux-add-data = <2>; + gpmc,cs-on-ns = <10>; + gpmc,cs-rd-off-ns = <160>; + gpmc,cs-wr-off-ns = <160>; + gpmc,adv-on-ns = <20>; + gpmc,adv-rd-off-ns = <50>; + gpmc,adv-wr-off-ns = <50>; + gpmc,oe-on-ns = <60>; + gpmc,oe-off-ns = <120>; + gpmc,we-on-ns = <60>; + gpmc,we-off-ns = <120>; + gpmc,rd-cycle-ns = <170>; + gpmc,wr-cycle-ns = <170>; + gpmc,access-ns = <150>; + gpmc,page-burst-access-ns = <10>; + + partition@0 { + label = "bootloader"; + reg = <0 0x20000>; + }; + partition@0x20000 { + label = "params"; + reg = <0x20000 0x20000>; + }; + partition@0x40000 { + label = "kernel"; + reg = <0x40000 0x200000>; + }; + partition@0x240000 { + label = "file-system"; + reg = <0x240000 0x3dc0000>; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi index af6560908905..da5b285b73be 100644 --- a/arch/arm/boot/dts/omap2420.dtsi +++ b/arch/arm/boot/dts/omap2420.dtsi @@ -29,6 +29,65 @@ pinctrl-single,function-mask = <0x3f>; }; + gpio1: gpio@48018000 { + compatible = "ti,omap2-gpio"; + reg = <0x48018000 0x200>; + interrupts = <29>; + ti,hwmods = "gpio1"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpio2: gpio@4801a000 { + compatible = "ti,omap2-gpio"; + reg = <0x4801a000 0x200>; + interrupts = <30>; + ti,hwmods = "gpio2"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpio3: gpio@4801c000 { + compatible = "ti,omap2-gpio"; + reg = <0x4801c000 0x200>; + interrupts = <31>; + ti,hwmods = "gpio3"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpio4: gpio@4801e000 { + compatible = "ti,omap2-gpio"; + reg = <0x4801e000 0x200>; + interrupts = <32>; + ti,hwmods = "gpio4"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpmc: gpmc@6800a000 { + compatible = "ti,omap2420-gpmc"; + reg = <0x6800a000 0x1000>; + #address-cells = <2>; + #size-cells = <1>; + interrupts = <20>; + gpmc,num-cs = <8>; + gpmc,num-waitpins = <4>; + ti,hwmods = "gpmc"; + }; + mcbsp1: mcbsp@48074000 { compatible = "ti,omap2420-mcbsp"; reg = <0x48074000 0xff>; @@ -37,6 +96,9 @@ <60>; /* RX interrupt */ interrupt-names = "tx", "rx"; ti,hwmods = "mcbsp1"; + dmas = <&sdma 31>, + <&sdma 32>; + dma-names = "tx", "rx"; }; mcbsp2: mcbsp@48076000 { @@ -47,10 +109,13 @@ <63>; /* RX interrupt */ interrupt-names = "tx", "rx"; ti,hwmods = "mcbsp2"; + dmas = <&sdma 33>, + <&sdma 34>; + dma-names = "tx", "rx"; }; timer1: timer@48028000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x48028000 0x400>; interrupts = <37>; ti,hwmods = "timer1"; diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi index c3924457c9b6..054bc4439568 100644 --- a/arch/arm/boot/dts/omap2430.dtsi +++ b/arch/arm/boot/dts/omap2430.dtsi @@ -29,6 +29,76 @@ pinctrl-single,function-mask = <0x3f>; }; + gpio1: gpio@4900c000 { + compatible = "ti,omap2-gpio"; + reg = <0x4900c000 0x200>; + interrupts = <29>; + ti,hwmods = "gpio1"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpio2: gpio@4900e000 { + compatible = "ti,omap2-gpio"; + reg = <0x4900e000 0x200>; + interrupts = <30>; + ti,hwmods = "gpio2"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpio3: gpio@49010000 { + compatible = "ti,omap2-gpio"; + reg = <0x49010000 0x200>; + interrupts = <31>; + ti,hwmods = "gpio3"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpio4: gpio@49012000 { + compatible = "ti,omap2-gpio"; + reg = <0x49012000 0x200>; + interrupts = <32>; + ti,hwmods = "gpio4"; + ti,gpio-always-on; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpio5: gpio@480b6000 { + compatible = "ti,omap2-gpio"; + reg = <0x480b6000 0x200>; + interrupts = <33>; + ti,hwmods = "gpio5"; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + + gpmc: gpmc@6e000000 { + compatible = "ti,omap2430-gpmc"; + reg = <0x6e000000 0x1000>; + #address-cells = <2>; + #size-cells = <1>; + interrupts = <20>; + gpmc,num-cs = <8>; + gpmc,num-waitpins = <4>; + ti,hwmods = "gpmc"; + }; + mcbsp1: mcbsp@48074000 { compatible = "ti,omap2430-mcbsp"; reg = <0x48074000 0xff>; @@ -40,6 +110,9 @@ interrupt-names = "common", "tx", "rx", "rx_overflow"; ti,buffer-size = <128>; ti,hwmods = "mcbsp1"; + dmas = <&sdma 31>, + <&sdma 32>; + dma-names = "tx", "rx"; }; mcbsp2: mcbsp@48076000 { @@ -52,6 +125,9 @@ interrupt-names = "common", "tx", "rx"; ti,buffer-size = <128>; ti,hwmods = "mcbsp2"; + dmas = <&sdma 33>, + <&sdma 34>; + dma-names = "tx", "rx"; }; mcbsp3: mcbsp@4808c000 { @@ -64,6 +140,9 @@ interrupt-names = "common", "tx", "rx"; ti,buffer-size = <128>; ti,hwmods = "mcbsp3"; + dmas = <&sdma 17>, + <&sdma 18>; + dma-names = "tx", "rx"; }; mcbsp4: mcbsp@4808e000 { @@ -76,6 +155,9 @@ interrupt-names = "common", "tx", "rx"; ti,buffer-size = <128>; ti,hwmods = "mcbsp4"; + dmas = <&sdma 19>, + <&sdma 20>; + dma-names = "tx", "rx"; }; mcbsp5: mcbsp@48096000 { @@ -88,10 +170,13 @@ interrupt-names = "common", "tx", "rx"; ti,buffer-size = <128>; ti,hwmods = "mcbsp5"; + dmas = <&sdma 21>, + <&sdma 22>; + dma-names = "tx", "rx"; }; timer1: timer@49018000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap2420-timer"; reg = <0x49018000 0x400>; interrupts = <37>; ti,hwmods = "timer1"; diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts index 3705a81c1fc2..3046d1f81be0 100644 --- a/arch/arm/boot/dts/omap3-beagle-xm.dts +++ b/arch/arm/boot/dts/omap3-beagle-xm.dts @@ -13,6 +13,12 @@ model = "TI OMAP3 BeagleBoard xM"; compatible = "ti,omap3-beagle-xm, ti,omap3-beagle", "ti,omap3"; + cpus { + cpu@0 { + cpu0-supply = <&vcc>; + }; + }; + memory { device_type = "memory"; reg = <0x80000000 0x20000000>; /* 512 MB */ @@ -20,10 +26,6 @@ leds { compatible = "gpio-leds"; - pmu_stat { - label = "beagleboard::pmu_stat"; - gpios = <&twl_gpio 19 0>; /* LEDB */ - }; heartbeat { label = "beagleboard::usr0"; @@ -38,6 +40,16 @@ }; }; + pwmleds { + compatible = "pwm-leds"; + + pmu_stat { + label = "beagleboard::pmu_stat"; + pwms = <&twl_pwmled 1 7812500>; + max-brightness = <127>; + }; + }; + sound { compatible = "ti,omap-twl4030"; ti,model = "omap3beagle"; @@ -107,3 +119,10 @@ */ ti,pulldowns = <0x03a1c4>; }; + +&usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; + mode = <3>; + power = <50>; +}; diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts index 02d23f15fd86..6eec69997607 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -7,12 +7,18 @@ */ /dts-v1/; -/include/ "omap3.dtsi" +/include/ "omap34xx.dtsi" / { model = "TI OMAP3 BeagleBoard"; compatible = "ti,omap3-beagle", "ti,omap3"; + cpus { + cpu@0 { + cpu0-supply = <&vcc>; + }; + }; + memory { device_type = "memory"; reg = <0x80000000 0x10000000>; /* 256 MB */ diff --git a/arch/arm/boot/dts/omap3-devkit8000.dts b/arch/arm/boot/dts/omap3-devkit8000.dts new file mode 100644 index 000000000000..8a5cdcc6debd --- /dev/null +++ b/arch/arm/boot/dts/omap3-devkit8000.dts @@ -0,0 +1,169 @@ +/* + * Author: Anil Kumar <anilk4.v@gmail.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/ "omap34xx.dtsi" +/ { + model = "TimLL OMAP3 Devkit8000"; + compatible = "timll,omap3-devkit8000", "ti,omap3"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + leds { + compatible = "gpio-leds"; + + heartbeat { + label = "devkit8000::led1"; + gpios = <&gpio6 26 0>; /* 186 -> LED1 */ + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + + mmc { + label = "devkit8000::led2"; + gpios = <&gpio6 3 0>; /* 163 -> LED2 */ + default-state = "on"; + linux,default-trigger = "none"; + }; + + usr { + label = "devkit8000::led3"; + gpios = <&gpio6 4 0>; /* 164 -> LED3 */ + default-state = "on"; + linux,default-trigger = "usr"; + }; + + }; + + sound { + compatible = "ti,omap-twl4030"; + ti,model = "devkit8000"; + + ti,mcbsp = <&mcbsp2>; + ti,codec = <&twl_audio>; + ti,audio-routing = + "Ext Spk", "PREDRIVEL", + "Ext Spk", "PREDRIVER", + "MAINMIC", "Main Mic", + "Main Mic", "Mic Bias 1"; + }; +}; + +&i2c1 { + clock-frequency = <2600000>; + + twl: twl@48 { + reg = <0x48>; + interrupts = <7>; /* SYS_NIRQ cascaded to intc */ + + twl_audio: audio { + compatible = "ti,twl4030-audio"; + codec { + }; + }; + }; +}; + +&i2c2 { + status = "disabled"; +}; + +&i2c3 { + status = "disabled"; +}; + +/include/ "twl4030.dtsi" + +&mmc1 { + vmmc-supply = <&vmmc1>; + vmmc_aux-supply = <&vsim>; + bus-width = <8>; +}; + +&mmc2 { + status = "disabled"; +}; + +&mmc3 { + status = "disabled"; +}; + +&wdt2 { + status = "disabled"; +}; + +&mcbsp1 { + status = "disabled"; +}; + +&mcbsp3 { + status = "disabled"; +}; + +&mcbsp4 { + status = "disabled"; +}; + +&mcbsp5 { + status = "disabled"; +}; + +&gpmc { + ranges = <0 0 0x30000000 0x04>; /* CS0: NAND */ + + nand@0,0 { + reg = <0 0 0>; /* CS0, offset 0 */ + nand-bus-width = <16>; + + gpmc,sync-clk = <0>; + gpmc,cs-on = <0>; + gpmc,cs-rd-off = <44>; + gpmc,cs-wr-off = <44>; + gpmc,adv-on = <6>; + gpmc,adv-rd-off = <34>; + gpmc,adv-wr-off = <44>; + gpmc,we-off = <40>; + gpmc,oe-off = <54>; + gpmc,access = <64>; + gpmc,rd-cycle = <82>; + gpmc,wr-cycle = <82>; + gpmc,wr-access = <40>; + gpmc,wr-data-mux-bus = <0>; + + #address-cells = <1>; + #size-cells = <1>; + + x-loader@0 { + label = "X-Loader"; + reg = <0 0x80000>; + }; + + bootloaders@80000 { + label = "U-Boot"; + reg = <0x80000 0x1e0000>; + }; + + bootloaders_env@260000 { + label = "U-Boot Env"; + reg = <0x260000 0x20000>; + }; + + kernel@280000 { + label = "Kernel"; + reg = <0x280000 0x400000>; + }; + + filesystem@680000 { + label = "File System"; + reg = <0x680000 0xf980000>; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap3-evm.dts b/arch/arm/boot/dts/omap3-evm.dts index e8ba1c247a39..96d1c206a57b 100644 --- a/arch/arm/boot/dts/omap3-evm.dts +++ b/arch/arm/boot/dts/omap3-evm.dts @@ -7,12 +7,18 @@ */ /dts-v1/; -/include/ "omap3.dtsi" +/include/ "omap34xx.dtsi" / { model = "TI OMAP3 EVM (OMAP3530, AM/DM37x)"; compatible = "ti,omap3-evm", "ti,omap3"; + cpus { + cpu@0 { + cpu0-supply = <&vcc>; + }; + }; + memory { device_type = "memory"; reg = <0x80000000 0x10000000>; /* 256 MB */ @@ -59,3 +65,10 @@ &twl_gpio { ti,use-leds; }; + +&usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; + mode = <3>; + power = <50>; +}; diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/omap3-igep.dtsi new file mode 100644 index 000000000000..f8fe3b748c3e --- /dev/null +++ b/arch/arm/boot/dts/omap3-igep.dtsi @@ -0,0 +1,122 @@ +/* + * Device Tree Source for IGEP Technology devices + * + * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk> + * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.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/ "omap34xx.dtsi" + +/ { + memory { + device_type = "memory"; + reg = <0x80000000 0x20000000>; /* 512 MB */ + }; + + sound { + compatible = "ti,omap-twl4030"; + ti,model = "igep2"; + ti,mcbsp = <&mcbsp2>; + ti,codec = <&twl_audio>; + }; +}; + +&omap3_pmx_core { + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + 0x152 0x100 /* uart1_rx.uart1_rx INPUT | MODE0 */ + 0x14c 0 /* uart1_tx.uart1_tx OUTPUT | MODE0 */ + >; + }; + + uart2_pins: pinmux_uart2_pins { + pinctrl-single,pins = < + 0x14a 0x100 /* uart2_rx.uart2_rx INPUT | MODE0 */ + 0x148 0 /* uart2_tx.uart2_tx OUTPUT | MODE0 */ + >; + }; + + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + 0x16e 0x100 /* uart3_rx.uart3_rx INPUT | MODE0 */ + 0x170 0 /* uart3_tx.uart3_tx OUTPUT | MODE0 */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + 0x114 0x0118 /* sdmmc1_clk.sdmmc1_clk INPUT PULLUP | MODE 0 */ + 0x116 0x0118 /* sdmmc1_cmd.sdmmc1_cmd INPUT PULLUP | MODE 0 */ + 0x118 0x0118 /* sdmmc1_dat0.sdmmc1_dat0 INPUT PULLUP | MODE 0 */ + 0x11a 0x0118 /* sdmmc1_dat1.sdmmc1_dat1 INPUT PULLUP | MODE 0 */ + 0x11c 0x0118 /* sdmmc1_dat2.sdmmc1_dat2 INPUT PULLUP | MODE 0 */ + 0x11e 0x0118 /* sdmmc1_dat3.sdmmc1_dat3 INPUT PULLUP | MODE 0 */ + 0x120 0x0100 /* sdmmc1_dat4.sdmmc1_dat4 INPUT | MODE 0 */ + 0x122 0x0100 /* sdmmc1_dat5.sdmmc1_dat5 INPUT | MODE 0 */ + 0x124 0x0100 /* sdmmc1_dat6.sdmmc1_dat6 INPUT | MODE 0 */ + 0x126 0x0100 /* sdmmc1_dat7.sdmmc1_dat7 INPUT | MODE 0 */ + >; + }; +}; + +&i2c1 { + clock-frequency = <2600000>; + + twl: twl@48 { + reg = <0x48>; + interrupts = <7>; /* SYS_NIRQ cascaded to intc */ + interrupt-parent = <&intc>; + + twl_audio: audio { + compatible = "ti,twl4030-audio"; + codec { + }; + }; + }; +}; + +/include/ "twl4030.dtsi" + +&i2c2 { + clock-frequency = <400000>; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <&vmmc1>; + vmmc_aux-supply = <&vsim>; + bus-width = <8>; +}; + +&mmc2 { + status = "disabled"; +}; + +&mmc3 { + status = "disabled"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; +}; + +&twl_gpio { + ti,use-leds; +}; diff --git a/arch/arm/boot/dts/omap3-igep0020.dts b/arch/arm/boot/dts/omap3-igep0020.dts new file mode 100644 index 000000000000..e2b98490cc9a --- /dev/null +++ b/arch/arm/boot/dts/omap3-igep0020.dts @@ -0,0 +1,56 @@ +/* + * Device Tree Source for IGEPv2 board + * + * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk> + * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/include/ "omap3-igep.dtsi" + +/ { + model = "IGEPv2"; + compatible = "isee,omap3-igep0020", "ti,omap3"; + + leds { + compatible = "gpio-leds"; + boot { + label = "omap3:green:boot"; + gpios = <&gpio1 26 0>; + default-state = "on"; + }; + + user0 { + label = "omap3:red:user0"; + gpios = <&gpio1 27 0>; + default-state = "off"; + }; + + user1 { + label = "omap3:red:user1"; + gpios = <&gpio1 28 0>; + default-state = "off"; + }; + + user2 { + label = "omap3:green:user1"; + gpios = <&twl_gpio 19 1>; + }; + }; +}; + +&i2c3 { + clock-frequency = <100000>; + + /* + * Display monitor features are burnt in the EEPROM + * as EDID data. + */ + eeprom@50 { + compatible = "ti,eeprom"; + reg = <0x50>; + }; +}; diff --git a/arch/arm/boot/dts/omap3-igep0030.dts b/arch/arm/boot/dts/omap3-igep0030.dts new file mode 100644 index 000000000000..9dc48d262ffb --- /dev/null +++ b/arch/arm/boot/dts/omap3-igep0030.dts @@ -0,0 +1,44 @@ +/* + * Device Tree Source for IGEP COM Module + * + * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk> + * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/include/ "omap3-igep.dtsi" + +/ { + model = "IGEP COM Module"; + compatible = "isee,omap3-igep0030", "ti,omap3"; + + leds { + compatible = "gpio-leds"; + boot { + label = "omap3:green:boot"; + gpios = <&twl_gpio 13 1>; + default-state = "on"; + }; + + user0 { + label = "omap3:red:user0"; + gpios = <&twl_gpio 18 1>; /* LEDA */ + default-state = "off"; + }; + + user1 { + label = "omap3:green:user1"; + gpios = <&twl_gpio 19 1>; /* LEDB */ + default-state = "off"; + }; + + user2 { + label = "omap3:red:user1"; + gpios = <&gpio1 16 1>; + default-state = "off"; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi index 89808ce01673..a626c50041f6 100644 --- a/arch/arm/boot/dts/omap3-overo.dtsi +++ b/arch/arm/boot/dts/omap3-overo.dtsi @@ -11,17 +11,26 @@ */ /dts-v1/; -/include/ "omap3.dtsi" +/include/ "omap34xx.dtsi" / { - leds { - compatible = "gpio-leds"; + pwmleds { + compatible = "pwm-leds"; + overo { label = "overo:blue:COM"; - gpios = <&twl_gpio 19 0>; - linux,default-trigger = "mmc0"; + pwms = <&twl_pwmled 1 7812500>; + max-brightness = <127>; }; }; + + sound { + compatible = "ti,omap-twl4030"; + ti,model = "overo"; + + ti,mcbsp = <&mcbsp2>; + ti,codec = <&twl_audio>; + }; }; &i2c1 { @@ -31,6 +40,12 @@ reg = <0x48>; interrupts = <7>; /* SYS_NIRQ cascaded to intc */ interrupt-parent = <&intc>; + + twl_audio: audio { + compatible = "ti,twl4030-audio"; + codec { + }; + }; }; }; @@ -55,3 +70,10 @@ &twl_gpio { ti,use-leds; }; + +&usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; + mode = <3>; + power = <50>; +}; diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index a14f74bbce7c..82a404da1c0d 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -26,8 +26,14 @@ }; }; + pmu { + compatible = "arm,cortex-a8-pmu"; + interrupts = <3>; + ti,hwmods = "debugss"; + }; + /* - * The soc node represents the soc top level view. It is uses for IPs + * The soc node represents the soc top level view. It is used for IPs * that are not memory mapped in the MPU view or for the MPU itself. */ soc { @@ -75,76 +81,101 @@ reg = <0x48200000 0x1000>; }; + sdma: dma-controller@48056000 { + compatible = "ti,omap3630-sdma", "ti,omap3430-sdma"; + reg = <0x48056000 0x1000>; + interrupts = <12>, + <13>, + <14>, + <15>; + #dma-cells = <1>; + #dma-channels = <32>; + #dma-requests = <96>; + }; + omap3_pmx_core: pinmux@48002030 { compatible = "ti,omap3-padconf", "pinctrl-single"; reg = <0x48002030 0x05cc>; #address-cells = <1>; #size-cells = <0>; pinctrl-single,register-width = <16>; - pinctrl-single,function-mask = <0x7fff>; + pinctrl-single,function-mask = <0x7f1f>; }; - omap3_pmx_wkup: pinmux@0x48002a58 { + omap3_pmx_wkup: pinmux@0x48002a00 { compatible = "ti,omap3-padconf", "pinctrl-single"; - reg = <0x48002a58 0x5c>; + reg = <0x48002a00 0x5c>; #address-cells = <1>; #size-cells = <0>; pinctrl-single,register-width = <16>; - pinctrl-single,function-mask = <0x7fff>; + pinctrl-single,function-mask = <0x7f1f>; }; gpio1: gpio@48310000 { compatible = "ti,omap3-gpio"; + reg = <0x48310000 0x200>; + interrupts = <29>; ti,hwmods = "gpio1"; + ti,gpio-always-on; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio2: gpio@49050000 { compatible = "ti,omap3-gpio"; + reg = <0x49050000 0x200>; + interrupts = <30>; ti,hwmods = "gpio2"; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio3: gpio@49052000 { compatible = "ti,omap3-gpio"; + reg = <0x49052000 0x200>; + interrupts = <31>; ti,hwmods = "gpio3"; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio4: gpio@49054000 { compatible = "ti,omap3-gpio"; + reg = <0x49054000 0x200>; + interrupts = <32>; ti,hwmods = "gpio4"; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio5: gpio@49056000 { compatible = "ti,omap3-gpio"; + reg = <0x49056000 0x200>; + interrupts = <33>; ti,hwmods = "gpio5"; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio6: gpio@49058000 { compatible = "ti,omap3-gpio"; + reg = <0x49058000 0x200>; + interrupts = <34>; ti,hwmods = "gpio6"; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; uart1: serial@4806a000 { @@ -192,6 +223,16 @@ #size-cells = <0>; ti,hwmods = "mcspi1"; ti,spi-num-cs = <4>; + dmas = <&sdma 35>, + <&sdma 36>, + <&sdma 37>, + <&sdma 38>, + <&sdma 39>, + <&sdma 40>, + <&sdma 41>, + <&sdma 42>; + dma-names = "tx0", "rx0", "tx1", "rx1", + "tx2", "rx2", "tx3", "rx3"; }; mcspi2: spi@4809a000 { @@ -200,6 +241,11 @@ #size-cells = <0>; ti,hwmods = "mcspi2"; ti,spi-num-cs = <2>; + dmas = <&sdma 43>, + <&sdma 44>, + <&sdma 45>, + <&sdma 46>; + dma-names = "tx0", "rx0", "tx1", "rx1"; }; mcspi3: spi@480b8000 { @@ -208,6 +254,11 @@ #size-cells = <0>; ti,hwmods = "mcspi3"; ti,spi-num-cs = <2>; + dmas = <&sdma 15>, + <&sdma 16>, + <&sdma 23>, + <&sdma 24>; + dma-names = "tx0", "rx0", "tx1", "rx1"; }; mcspi4: spi@480ba000 { @@ -216,22 +267,30 @@ #size-cells = <0>; ti,hwmods = "mcspi4"; ti,spi-num-cs = <1>; + dmas = <&sdma 70>, <&sdma 71>; + dma-names = "tx0", "rx0"; }; mmc1: mmc@4809c000 { compatible = "ti,omap3-hsmmc"; ti,hwmods = "mmc1"; ti,dual-volt; + dmas = <&sdma 61>, <&sdma 62>; + dma-names = "tx", "rx"; }; mmc2: mmc@480b4000 { compatible = "ti,omap3-hsmmc"; ti,hwmods = "mmc2"; + dmas = <&sdma 47>, <&sdma 48>; + dma-names = "tx", "rx"; }; mmc3: mmc@480ad000 { compatible = "ti,omap3-hsmmc"; ti,hwmods = "mmc3"; + dmas = <&sdma 77>, <&sdma 78>; + dma-names = "tx", "rx"; }; wdt2: wdt@48314000 { @@ -249,6 +308,9 @@ interrupt-names = "common", "tx", "rx"; ti,buffer-size = <128>; ti,hwmods = "mcbsp1"; + dmas = <&sdma 31>, + <&sdma 32>; + dma-names = "tx", "rx"; }; mcbsp2: mcbsp@49022000 { @@ -263,6 +325,9 @@ interrupt-names = "common", "tx", "rx", "sidetone"; ti,buffer-size = <1280>; ti,hwmods = "mcbsp2", "mcbsp2_sidetone"; + dmas = <&sdma 33>, + <&sdma 34>; + dma-names = "tx", "rx"; }; mcbsp3: mcbsp@49024000 { @@ -277,6 +342,9 @@ interrupt-names = "common", "tx", "rx", "sidetone"; ti,buffer-size = <128>; ti,hwmods = "mcbsp3", "mcbsp3_sidetone"; + dmas = <&sdma 17>, + <&sdma 18>; + dma-names = "tx", "rx"; }; mcbsp4: mcbsp@49026000 { @@ -289,6 +357,9 @@ interrupt-names = "common", "tx", "rx"; ti,buffer-size = <128>; ti,hwmods = "mcbsp4"; + dmas = <&sdma 19>, + <&sdma 20>; + dma-names = "tx", "rx"; }; mcbsp5: mcbsp@48096000 { @@ -301,10 +372,13 @@ interrupt-names = "common", "tx", "rx"; ti,buffer-size = <128>; ti,hwmods = "mcbsp5"; + dmas = <&sdma 21>, + <&sdma 22>; + dma-names = "tx", "rx"; }; timer1: timer@48318000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x48318000 0x400>; interrupts = <37>; ti,hwmods = "timer1"; @@ -312,28 +386,28 @@ }; timer2: timer@49032000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x49032000 0x400>; interrupts = <38>; ti,hwmods = "timer2"; }; timer3: timer@49034000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x49034000 0x400>; interrupts = <39>; ti,hwmods = "timer3"; }; timer4: timer@49036000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x49036000 0x400>; interrupts = <40>; ti,hwmods = "timer4"; }; timer5: timer@49038000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x49038000 0x400>; interrupts = <41>; ti,hwmods = "timer5"; @@ -341,7 +415,7 @@ }; timer6: timer@4903a000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x4903a000 0x400>; interrupts = <42>; ti,hwmods = "timer6"; @@ -349,7 +423,7 @@ }; timer7: timer@4903c000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x4903c000 0x400>; interrupts = <43>; ti,hwmods = "timer7"; @@ -357,7 +431,7 @@ }; timer8: timer@4903e000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x4903e000 0x400>; interrupts = <44>; ti,hwmods = "timer8"; @@ -366,7 +440,7 @@ }; timer9: timer@49040000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x49040000 0x400>; interrupts = <45>; ti,hwmods = "timer9"; @@ -374,7 +448,7 @@ }; timer10: timer@48086000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x48086000 0x400>; interrupts = <46>; ti,hwmods = "timer10"; @@ -382,7 +456,7 @@ }; timer11: timer@48088000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x48088000 0x400>; interrupts = <47>; ti,hwmods = "timer11"; @@ -390,7 +464,7 @@ }; timer12: timer@48304000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x48304000 0x400>; interrupts = <95>; ti,hwmods = "timer12"; @@ -428,5 +502,26 @@ }; }; + gpmc: gpmc@6e000000 { + compatible = "ti,omap3430-gpmc"; + ti,hwmods = "gpmc"; + reg = <0x6e000000 0x02d0>; + interrupts = <20>; + gpmc,num-cs = <8>; + gpmc,num-waitpins = <4>; + #address-cells = <2>; + #size-cells = <1>; + }; + + usb_otg_hs: usb_otg_hs@480ab000 { + compatible = "ti,omap3-musb"; + reg = <0x480ab000 0x1000>; + interrupts = <0 92 0x4>, <0 93 0x4>; + interrupt-names = "mc", "dma"; + ti,hwmods = "usb_otg_hs"; + multipoint = <1>; + num-eps = <16>; + ram-bits = <12>; + }; }; }; diff --git a/arch/arm/boot/dts/omap3430-sdp.dts b/arch/arm/boot/dts/omap3430-sdp.dts new file mode 100644 index 000000000000..144ae43453c4 --- /dev/null +++ b/arch/arm/boot/dts/omap3430-sdp.dts @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.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/ "omap34xx.dtsi" + +/ { + model = "TI OMAP3430 SDP"; + compatible = "ti,omap3430-sdp", "ti,omap3"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; +}; + +&i2c1 { + clock-frequency = <2600000>; + + twl: twl@48 { + reg = <0x48>; + interrupts = <7>; /* SYS_NIRQ cascaded to intc */ + }; +}; + +/include/ "twl4030.dtsi" + +&mmc1 { + vmmc-supply = <&vmmc1>; + vmmc_aux-supply = <&vsim>; + bus-width = <8>; +}; + +&mmc2 { + status = "disabled"; +}; + +&mmc3 { + status = "disabled"; +}; + +&gpmc { + ranges = <0 0 0x10000000 0x08000000>, + <1 0 0x28000000 0x08000000>, + <2 0 0x20000000 0x10000000>; + + nor@0,0 { + compatible = "cfi-flash"; + linux,mtd-name= "intel,pf48f6000m0y1be"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0 0 0x08000000>; + bank-width = <2>; + + gpmc,mux-add-data = <2>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <186>; + gpmc,cs-wr-off-ns = <186>; + gpmc,adv-on-ns = <12>; + gpmc,adv-rd-off-ns = <48>; + gpmc,adv-wr-off-ns = <48>; + gpmc,oe-on-ns = <54>; + gpmc,oe-off-ns = <168>; + gpmc,we-on-ns = <54>; + gpmc,we-off-ns = <168>; + gpmc,rd-cycle-ns = <186>; + gpmc,wr-cycle-ns = <186>; + gpmc,access-ns = <114>; + gpmc,page-burst-access-ns = <6>; + gpmc,bus-turnaround-ns = <12>; + gpmc,cycle2cycle-delay-ns = <18>; + gpmc,wr-data-mux-bus-ns = <90>; + gpmc,wr-access-ns = <186>; + gpmc,cycle2cycle-samecsen; + gpmc,cycle2cycle-diffcsen; + + partition@0 { + label = "bootloader-nor"; + reg = <0 0x40000>; + }; + partition@0x40000 { + label = "params-nor"; + reg = <0x40000 0x40000>; + }; + partition@0x80000 { + label = "kernel-nor"; + reg = <0x80000 0x200000>; + }; + partition@0x280000 { + label = "filesystem-nor"; + reg = <0x240000 0x7d80000>; + }; + }; + + nand@1,0 { + linux,mtd-name= "micron,mt29f1g08abb"; + #address-cells = <1>; + #size-cells = <1>; + reg = <1 0 0x08000000>; + nand-bus-width = <8>; + + ti,nand-ecc-opt = "sw"; + gpmc,device-nand; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <36>; + gpmc,cs-wr-off-ns = <36>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <24>; + gpmc,adv-wr-off-ns = <36>; + gpmc,oe-on-ns = <6>; + gpmc,oe-off-ns = <48>; + gpmc,we-on-ns = <6>; + gpmc,we-off-ns = <30>; + gpmc,rd-cycle-ns = <72>; + gpmc,wr-cycle-ns = <72>; + gpmc,access-ns = <54>; + gpmc,wr-access-ns = <30>; + + partition@0 { + label = "xloader-nand"; + reg = <0 0x80000>; + }; + partition@0x80000 { + label = "bootloader-nand"; + reg = <0x80000 0x140000>; + }; + partition@0x1c0000 { + label = "params-nand"; + reg = <0x1c0000 0xc0000>; + }; + partition@0x280000 { + label = "kernel-nand"; + reg = <0x280000 0x500000>; + }; + partition@0x780000 { + label = "filesystem-nand"; + reg = <0x780000 0x7880000>; + }; + }; + + onenand@2,0 { + linux,mtd-name= "samsung,kfm2g16q2m-deb8"; + #address-cells = <1>; + #size-cells = <1>; + reg = <2 0 0x10000000>; + + gpmc,device-width = <2>; + gpmc,mux-add-data = <2>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <84>; + gpmc,cs-wr-off-ns = <72>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <18>; + gpmc,adv-wr-off-ns = <18>; + gpmc,oe-on-ns = <30>; + gpmc,oe-off-ns = <84>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <42>; + gpmc,rd-cycle-ns = <108>; + gpmc,wr-cycle-ns = <96>; + gpmc,access-ns = <78>; + gpmc,wr-data-mux-bus-ns = <30>; + + partition@0 { + label = "xloader-onenand"; + reg = <0 0x80000>; + }; + partition@0x80000 { + label = "bootloader-onenand"; + reg = <0x80000 0x40000>; + }; + partition@0xc0000 { + label = "params-onenand"; + reg = <0xc0000 0x20000>; + }; + partition@0xe0000 { + label = "kernel-onenand"; + reg = <0xe0000 0x200000>; + }; + partition@0x2e0000 { + label = "filesystem-onenand"; + reg = <0x2e0000 0xfd20000>; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap34xx.dtsi b/arch/arm/boot/dts/omap34xx.dtsi new file mode 100644 index 000000000000..75ed4ae2e631 --- /dev/null +++ b/arch/arm/boot/dts/omap34xx.dtsi @@ -0,0 +1,28 @@ +/* + * Device Tree Source for OMAP34xx/OMAP35xx SoC + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "omap3.dtsi" + +/ { + cpus { + cpu@0 { + /* OMAP343x/OMAP35xx variants OPP1-5 */ + operating-points = < + /* kHz uV */ + 125000 975000 + 250000 1075000 + 500000 1200000 + 550000 1270000 + 600000 1350000 + >; + clock-latency = <300000>; /* From legacy driver */ + }; + }; +}; diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi index 96bf0287cb9f..f3447bc1b032 100644 --- a/arch/arm/boot/dts/omap36xx.dtsi +++ b/arch/arm/boot/dts/omap36xx.dtsi @@ -15,6 +15,19 @@ serial3 = &uart4; }; + cpus { + /* OMAP3630/OMAP37xx 'standard device' variants OPP50 to OPP130 */ + cpu@0 { + operating-points = < + /* kHz uV */ + 300000 1012500 + 600000 1200000 + 800000 1325000 + >; + clock-latency = <300000>; /* From legacy driver */ + }; + }; + ocp { uart4: serial@49042000 { compatible = "ti,omap3-uart"; diff --git a/arch/arm/boot/dts/omap4-panda-a4.dts b/arch/arm/boot/dts/omap4-panda-a4.dts index 75466d2abfb5..e30cdf0f5ac1 100644 --- a/arch/arm/boot/dts/omap4-panda-a4.dts +++ b/arch/arm/boot/dts/omap4-panda-a4.dts @@ -5,7 +5,10 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -/include/ "omap4-panda.dts" +/dts-v1/; + +/include/ "omap443x.dtsi" +/include/ "omap4-panda-common.dtsi" /* Pandaboard Rev A4+ have external pullups on SCL & SDA */ &dss_hdmi_pins { diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi new file mode 100644 index 000000000000..03bd60deb52b --- /dev/null +++ b/arch/arm/boot/dts/omap4-panda-common.dtsi @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2011-2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +/include/ "elpida_ecb240abacn.dtsi" + +/ { + model = "TI OMAP4 PandaBoard"; + compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4"; + + memory { + device_type = "memory"; + reg = <0x80000000 0x40000000>; /* 1 GB */ + }; + + leds { + compatible = "gpio-leds"; + heartbeat { + label = "pandaboard::status1"; + gpios = <&gpio1 7 0>; + linux,default-trigger = "heartbeat"; + }; + + mmc { + label = "pandaboard::status2"; + gpios = <&gpio1 8 0>; + linux,default-trigger = "mmc0"; + }; + }; + + sound: sound { + compatible = "ti,abe-twl6040"; + ti,model = "PandaBoard"; + + ti,mclk-freq = <38400000>; + + ti,mcpdm = <&mcpdm>; + + ti,twl6040 = <&twl6040>; + + /* Audio routing */ + ti,audio-routing = + "Headset Stereophone", "HSOL", + "Headset Stereophone", "HSOR", + "Ext Spk", "HFL", + "Ext Spk", "HFR", + "Line Out", "AUXL", + "Line Out", "AUXR", + "HSMIC", "Headset Mic", + "Headset Mic", "Headset Mic Bias", + "AFML", "Line In", + "AFMR", "Line In"; + }; +}; + +&omap4_pmx_core { + pinctrl-names = "default"; + pinctrl-0 = < + &twl6040_pins + &mcpdm_pins + &mcbsp1_pins + &dss_hdmi_pins + &tpd12s015_pins + >; + + twl6040_pins: pinmux_twl6040_pins { + pinctrl-single,pins = < + 0xe0 0x3 /* hdq_sio.gpio_127 OUTPUT | MODE3 */ + 0x160 0x100 /* sys_nirq2.sys_nirq2 INPUT | MODE0 */ + >; + }; + + mcpdm_pins: pinmux_mcpdm_pins { + pinctrl-single,pins = < + 0xc6 0x108 /* abe_pdm_ul_data.abe_pdm_ul_data INPUT PULLDOWN | MODE0 */ + 0xc8 0x108 /* abe_pdm_dl_data.abe_pdm_dl_data INPUT PULLDOWN | MODE0 */ + 0xca 0x118 /* abe_pdm_frame.abe_pdm_frame INPUT PULLUP | MODE0 */ + 0xcc 0x108 /* abe_pdm_lb_clk.abe_pdm_lb_clk INPUT PULLDOWN | MODE0 */ + 0xce 0x108 /* abe_clks.abe_clks INPUT PULLDOWN | MODE0 */ + >; + }; + + mcbsp1_pins: pinmux_mcbsp1_pins { + pinctrl-single,pins = < + 0xbe 0x100 /* abe_mcbsp1_clkx.abe_mcbsp1_clkx INPUT | MODE0 */ + 0xc0 0x108 /* abe_mcbsp1_dr.abe_mcbsp1_dr INPUT PULLDOWN | MODE0 */ + 0xc2 0x8 /* abe_mcbsp1_dx.abe_mcbsp1_dx OUTPUT PULLDOWN | MODE0 */ + 0xc4 0x100 /* abe_mcbsp1_fsx.abe_mcbsp1_fsx INPUT | MODE0 */ + >; + }; + + dss_hdmi_pins: pinmux_dss_hdmi_pins { + pinctrl-single,pins = < + 0x5a 0x118 /* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */ + 0x5c 0x118 /* hdmi_scl.hdmi_scl INPUT PULLUP | MODE 0 */ + 0x5e 0x118 /* hdmi_sda.hdmi_sda INPUT PULLUP | MODE 0 */ + >; + }; + + tpd12s015_pins: pinmux_tpd12s015_pins { + pinctrl-single,pins = < + 0x22 0x3 /* gpmc_a17.gpio_41 OUTPUT | MODE3 */ + 0x48 0x3 /* gpmc_nbe1.gpio_60 OUTPUT | MODE3 */ + 0x58 0x10b /* hdmi_hpd.gpio_63 INPUT PULLDOWN | MODE3 */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0xe2 0x118 /* i2c1_scl PULLUP | INPUTENABLE | MODE0 */ + 0xe4 0x118 /* i2c1_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + 0xe6 0x118 /* i2c2_scl PULLUP | INPUTENABLE | MODE0 */ + 0xe8 0x118 /* i2c2_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; + + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + 0xea 0x118 /* i2c3_scl PULLUP | INPUTENABLE | MODE0 */ + 0xec 0x118 /* i2c3_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; + + i2c4_pins: pinmux_i2c4_pins { + pinctrl-single,pins = < + 0xee 0x118 /* i2c4_scl PULLUP | INPUTENABLE | MODE0 */ + 0xf0 0x118 /* i2c4_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + clock-frequency = <400000>; + + twl: twl@48 { + reg = <0x48>; + /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */ + interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */ + interrupt-parent = <&gic>; + }; + + twl6040: twl@4b { + compatible = "ti,twl6040"; + reg = <0x4b>; + /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */ + interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */ + interrupt-parent = <&gic>; + ti,audpwron-gpio = <&gpio4 31 0>; /* gpio line 127 */ + + vio-supply = <&v1v8>; + v2v1-supply = <&v2v1>; + enable-active-high; + }; +}; + +/include/ "twl6030.dtsi" + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + + clock-frequency = <400000>; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + + clock-frequency = <100000>; + + /* + * Display monitor features are burnt in their EEPROM as EDID data. + * The EEPROM is connected as I2C slave device. + */ + eeprom@50 { + compatible = "ti,eeprom"; + reg = <0x50>; + }; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins>; + + clock-frequency = <400000>; +}; + +&mmc1 { + vmmc-supply = <&vmmc>; + bus-width = <8>; +}; + +&mmc2 { + status = "disabled"; +}; + +&mmc3 { + status = "disabled"; +}; + +&mmc4 { + status = "disabled"; +}; + +&mmc5 { + ti,non-removable; + bus-width = <4>; +}; + +&emif1 { + cs1-used; + device-handle = <&elpida_ECB240ABACN>; +}; + +&emif2 { + cs1-used; + device-handle = <&elpida_ECB240ABACN>; +}; + +&mcbsp2 { + status = "disabled"; +}; + +&mcbsp3 { + status = "disabled"; +}; + +&dmic { + status = "disabled"; +}; + +&twl_usb_comparator { + usb-supply = <&vusb>; +}; + +&usb_otg_hs { + interface-type = <1>; + mode = <3>; + power = <50>; +}; diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts index 73bc1a67e444..f1d8c217ce12 100644 --- a/arch/arm/boot/dts/omap4-panda-es.dts +++ b/arch/arm/boot/dts/omap4-panda-es.dts @@ -5,7 +5,10 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -/include/ "omap4-panda.dts" +/dts-v1/; + +/include/ "omap4460.dtsi" +/include/ "omap4-panda-common.dtsi" /* Audio routing is differnet between PandaBoard4430 and PandaBoardES */ &sound { diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index 4122efe31cfd..f8b221f0168e 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -7,202 +7,5 @@ */ /dts-v1/; -/include/ "omap4.dtsi" -/include/ "elpida_ecb240abacn.dtsi" - -/ { - model = "TI OMAP4 PandaBoard"; - compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4"; - - memory { - device_type = "memory"; - reg = <0x80000000 0x40000000>; /* 1 GB */ - }; - - leds { - compatible = "gpio-leds"; - heartbeat { - label = "pandaboard::status1"; - gpios = <&gpio1 7 0>; - linux,default-trigger = "heartbeat"; - }; - - mmc { - label = "pandaboard::status2"; - gpios = <&gpio1 8 0>; - linux,default-trigger = "mmc0"; - }; - }; - - sound: sound { - compatible = "ti,abe-twl6040"; - ti,model = "PandaBoard"; - - ti,mclk-freq = <38400000>; - - ti,mcpdm = <&mcpdm>; - - ti,twl6040 = <&twl6040>; - - /* Audio routing */ - ti,audio-routing = - "Headset Stereophone", "HSOL", - "Headset Stereophone", "HSOR", - "Ext Spk", "HFL", - "Ext Spk", "HFR", - "Line Out", "AUXL", - "Line Out", "AUXR", - "HSMIC", "Headset Mic", - "Headset Mic", "Headset Mic Bias", - "AFML", "Line In", - "AFMR", "Line In"; - }; -}; - -&omap4_pmx_core { - pinctrl-names = "default"; - pinctrl-0 = < - &twl6040_pins - &mcpdm_pins - &mcbsp1_pins - &dss_hdmi_pins - &tpd12s015_pins - >; - - twl6040_pins: pinmux_twl6040_pins { - pinctrl-single,pins = < - 0xe0 0x3 /* hdq_sio.gpio_127 OUTPUT | MODE3 */ - 0x160 0x100 /* sys_nirq2.sys_nirq2 INPUT | MODE0 */ - >; - }; - - mcpdm_pins: pinmux_mcpdm_pins { - pinctrl-single,pins = < - 0xc6 0x108 /* abe_pdm_ul_data.abe_pdm_ul_data INPUT PULLDOWN | MODE0 */ - 0xc8 0x108 /* abe_pdm_dl_data.abe_pdm_dl_data INPUT PULLDOWN | MODE0 */ - 0xca 0x118 /* abe_pdm_frame.abe_pdm_frame INPUT PULLUP | MODE0 */ - 0xcc 0x108 /* abe_pdm_lb_clk.abe_pdm_lb_clk INPUT PULLDOWN | MODE0 */ - 0xce 0x108 /* abe_clks.abe_clks INPUT PULLDOWN | MODE0 */ - >; - }; - - mcbsp1_pins: pinmux_mcbsp1_pins { - pinctrl-single,pins = < - 0xbe 0x100 /* abe_mcbsp1_clkx.abe_mcbsp1_clkx INPUT | MODE0 */ - 0xc0 0x108 /* abe_mcbsp1_dr.abe_mcbsp1_dr INPUT PULLDOWN | MODE0 */ - 0xc2 0x8 /* abe_mcbsp1_dx.abe_mcbsp1_dx OUTPUT PULLDOWN | MODE0 */ - 0xc4 0x100 /* abe_mcbsp1_fsx.abe_mcbsp1_fsx INPUT | MODE0 */ - >; - }; - - dss_hdmi_pins: pinmux_dss_hdmi_pins { - pinctrl-single,pins = < - 0x5a 0x118 /* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */ - 0x5c 0x118 /* hdmi_scl.hdmi_scl INPUT PULLUP | MODE 0 */ - 0x5e 0x118 /* hdmi_sda.hdmi_sda INPUT PULLUP | MODE 0 */ - >; - }; - - tpd12s015_pins: pinmux_tpd12s015_pins { - pinctrl-single,pins = < - 0x22 0x3 /* gpmc_a17.gpio_41 OUTPUT | MODE3 */ - 0x48 0x3 /* gpmc_nbe1.gpio_60 OUTPUT | MODE3 */ - 0x58 0x10b /* hdmi_hpd.gpio_63 INPUT PULLDOWN | MODE3 */ - >; - }; -}; - -&i2c1 { - clock-frequency = <400000>; - - twl: twl@48 { - reg = <0x48>; - /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */ - interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */ - interrupt-parent = <&gic>; - }; - - twl6040: twl@4b { - compatible = "ti,twl6040"; - reg = <0x4b>; - /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */ - interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */ - interrupt-parent = <&gic>; - ti,audpwron-gpio = <&gpio4 31 0>; /* gpio line 127 */ - - vio-supply = <&v1v8>; - v2v1-supply = <&v2v1>; - enable-active-high; - }; -}; - -/include/ "twl6030.dtsi" - -&i2c2 { - clock-frequency = <400000>; -}; - -&i2c3 { - clock-frequency = <100000>; - - /* - * Display monitor features are burnt in their EEPROM as EDID data. - * The EEPROM is connected as I2C slave device. - */ - eeprom@50 { - compatible = "ti,eeprom"; - reg = <0x50>; - }; -}; - -&i2c4 { - clock-frequency = <400000>; -}; - -&mmc1 { - vmmc-supply = <&vmmc>; - bus-width = <8>; -}; - -&mmc2 { - status = "disabled"; -}; - -&mmc3 { - status = "disabled"; -}; - -&mmc4 { - status = "disabled"; -}; - -&mmc5 { - ti,non-removable; - bus-width = <4>; -}; - -&emif1 { - cs1-used; - device-handle = <&elpida_ECB240ABACN>; -}; - -&emif2 { - cs1-used; - device-handle = <&elpida_ECB240ABACN>; -}; - -&mcbsp2 { - status = "disabled"; -}; - -&mcbsp3 { - status = "disabled"; -}; - -&dmic { - status = "disabled"; -}; - -&twl_usb_comparator { - usb-supply = <&vusb>; -}; +/include/ "omap443x.dtsi" +/include/ "omap4-panda-common.dtsi" diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 43e5258a9372..a35d9cd58063 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -7,7 +7,7 @@ */ /dts-v1/; -/include/ "omap4.dtsi" +/include/ "omap443x.dtsi" /include/ "elpida_ecb240abacn.dtsi" / { @@ -80,6 +80,32 @@ }; }; + pwmleds { + compatible = "pwm-leds"; + kpad { + label = "omap4::keypad"; + pwms = <&twl_pwm 0 7812500>; + max-brightness = <127>; + }; + + charging { + label = "omap4:green:chrg"; + pwms = <&twl_pwmled 0 7812500>; + max-brightness = <255>; + }; + }; + + backlight { + compatible = "pwm-backlight"; + pwms = <&twl_pwm 1 7812500>; + brightness-levels = < + 0 10 20 30 40 + 50 60 70 80 90 + 100 110 120 127 + >; + default-brightness-level = <13>; + }; + sound { compatible = "ti,abe-twl6040"; ti,model = "SDP4430"; @@ -197,6 +223,15 @@ >; }; + mcspi1_pins: pinmux_mcspi1_pins { + pinctrl-single,pins = < + 0xf2 0x100 /* mcspi1_clk.mcspi1_clk INPUT | MODE0 */ + 0xf4 0x100 /* mcspi1_somi.mcspi1_somi INPUT | MODE0 */ + 0xf6 0x100 /* mcspi1_simo.mcspi1_simo INPUT | MODE0 */ + 0xf8 0x100 /* mcspi1_cs0.mcspi1_cs0 INPUT | MODE0*/ + >; + }; + dss_hdmi_pins: pinmux_dss_hdmi_pins { pinctrl-single,pins = < 0x5a 0x118 /* hdmi_cec.hdmi_cec INPUT PULLUP | MODE 0 */ @@ -212,9 +247,40 @@ 0x58 0x10b /* hdmi_hpd.gpio_63 INPUT PULLDOWN | MODE3 */ >; }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0xe2 0x118 /* i2c1_scl PULLUP | INPUTENABLE | MODE0 */ + 0xe4 0x118 /* i2c1_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + 0xe6 0x118 /* i2c2_scl PULLUP | INPUTENABLE | MODE0 */ + 0xe8 0x118 /* i2c2_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; + + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + 0xea 0x118 /* i2c3_scl PULLUP | INPUTENABLE | MODE0 */ + 0xec 0x118 /* i2c3_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; + + i2c4_pins: pinmux_i2c4_pins { + pinctrl-single,pins = < + 0xee 0x118 /* i2c4_scl PULLUP | INPUTENABLE | MODE0 */ + 0xf0 0x118 /* i2c4_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; }; &i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <400000>; twl: twl@48 { @@ -253,10 +319,16 @@ /include/ "twl6030.dtsi" &i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + clock-frequency = <400000>; }; &i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + clock-frequency = <400000>; /* @@ -279,6 +351,9 @@ }; &i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins>; + clock-frequency = <400000>; /* @@ -292,12 +367,15 @@ }; &mcspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&mcspi1_pins>; + eth@0 { compatible = "ks8851"; spi-max-frequency = <24000000>; reg = <0>; interrupt-parent = <&gpio2>; - interrupts = <2>; /* gpio line 34 */ + interrupts = <2 8>; /* gpio line 34, low triggered */ vdd-supply = <&vdd_eth>; }; }; @@ -428,3 +506,9 @@ &twl_usb_comparator { usb-supply = <&vusb>; }; + +&usb_otg_hs { + interface-type = <1>; + mode = <3>; + power = <50>; +}; diff --git a/arch/arm/boot/dts/omap4-var-som.dts b/arch/arm/boot/dts/omap4-var-som.dts index 6601e6af6092..7e04103779c4 100644 --- a/arch/arm/boot/dts/omap4-var-som.dts +++ b/arch/arm/boot/dts/omap4-var-som.dts @@ -7,7 +7,7 @@ */ /dts-v1/; -/include/ "omap4.dtsi" +/include/ "omap443x.dtsi" / { model = "Variscite OMAP4 SOM"; @@ -68,7 +68,7 @@ spi-max-frequency = <24000000>; reg = <0>; interrupt-parent = <&gpio6>; - interrupts = <11>; /* gpio line 171 */ + interrupts = <11 8>; /* gpio line 171, low triggered */ vdd-supply = <&vdd_eth>; }; }; diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index b7db1a2b6ca7..2a5642882c8a 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -94,6 +94,11 @@ #size-cells = <1>; ranges; ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3"; + reg = <0x44000000 0x1000>, + <0x44800000 0x2000>, + <0x45000000 0x1000>; + interrupts = <0 9 0x4>, + <0 10 0x4>; counter32k: counter@4a304000 { compatible = "ti,omap-counter32k"; @@ -118,15 +123,28 @@ pinctrl-single,function-mask = <0x7fff>; }; + sdma: dma-controller@4a056000 { + compatible = "ti,omap4430-sdma"; + reg = <0x4a056000 0x1000>; + interrupts = <0 12 0x4>, + <0 13 0x4>, + <0 14 0x4>, + <0 15 0x4>; + #dma-cells = <1>; + #dma-channels = <32>; + #dma-requests = <127>; + }; + gpio1: gpio@4a310000 { compatible = "ti,omap4-gpio"; reg = <0x4a310000 0x200>; interrupts = <0 29 0x4>; ti,hwmods = "gpio1"; + ti,gpio-always-on; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio2: gpio@48055000 { @@ -137,7 +155,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio3: gpio@48057000 { @@ -148,7 +166,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio4: gpio@48059000 { @@ -159,7 +177,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio5: gpio@4805b000 { @@ -170,7 +188,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio6: gpio@4805d000 { @@ -181,7 +199,18 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; + }; + + gpmc: gpmc@50000000 { + compatible = "ti,omap4430-gpmc"; + reg = <0x50000000 0x1000>; + #address-cells = <2>; + #size-cells = <1>; + interrupts = <0 20 0x4>; + gpmc,num-cs = <8>; + gpmc,num-waitpins = <4>; + ti,hwmods = "gpmc"; }; uart1: serial@4806a000 { @@ -260,6 +289,16 @@ #size-cells = <0>; ti,hwmods = "mcspi1"; ti,spi-num-cs = <4>; + dmas = <&sdma 35>, + <&sdma 36>, + <&sdma 37>, + <&sdma 38>, + <&sdma 39>, + <&sdma 40>, + <&sdma 41>, + <&sdma 42>; + dma-names = "tx0", "rx0", "tx1", "rx1", + "tx2", "rx2", "tx3", "rx3"; }; mcspi2: spi@4809a000 { @@ -270,6 +309,11 @@ #size-cells = <0>; ti,hwmods = "mcspi2"; ti,spi-num-cs = <2>; + dmas = <&sdma 43>, + <&sdma 44>, + <&sdma 45>, + <&sdma 46>; + dma-names = "tx0", "rx0", "tx1", "rx1"; }; mcspi3: spi@480b8000 { @@ -280,6 +324,8 @@ #size-cells = <0>; ti,hwmods = "mcspi3"; ti,spi-num-cs = <2>; + dmas = <&sdma 15>, <&sdma 16>; + dma-names = "tx0", "rx0"; }; mcspi4: spi@480ba000 { @@ -290,6 +336,8 @@ #size-cells = <0>; ti,hwmods = "mcspi4"; ti,spi-num-cs = <1>; + dmas = <&sdma 70>, <&sdma 71>; + dma-names = "tx0", "rx0"; }; mmc1: mmc@4809c000 { @@ -299,6 +347,8 @@ ti,hwmods = "mmc1"; ti,dual-volt; ti,needs-special-reset; + dmas = <&sdma 61>, <&sdma 62>; + dma-names = "tx", "rx"; }; mmc2: mmc@480b4000 { @@ -307,6 +357,8 @@ interrupts = <0 86 0x4>; ti,hwmods = "mmc2"; ti,needs-special-reset; + dmas = <&sdma 47>, <&sdma 48>; + dma-names = "tx", "rx"; }; mmc3: mmc@480ad000 { @@ -315,6 +367,8 @@ interrupts = <0 94 0x4>; ti,hwmods = "mmc3"; ti,needs-special-reset; + dmas = <&sdma 77>, <&sdma 78>; + dma-names = "tx", "rx"; }; mmc4: mmc@480d1000 { @@ -323,6 +377,8 @@ interrupts = <0 96 0x4>; ti,hwmods = "mmc4"; ti,needs-special-reset; + dmas = <&sdma 57>, <&sdma 58>; + dma-names = "tx", "rx"; }; mmc5: mmc@480d5000 { @@ -331,6 +387,8 @@ interrupts = <0 59 0x4>; ti,hwmods = "mmc5"; ti,needs-special-reset; + dmas = <&sdma 59>, <&sdma 60>; + dma-names = "tx", "rx"; }; wdt2: wdt@4a314000 { @@ -347,6 +405,9 @@ reg-names = "mpu", "dma"; interrupts = <0 112 0x4>; ti,hwmods = "mcpdm"; + dmas = <&sdma 65>, + <&sdma 66>; + dma-names = "up_link", "dn_link"; }; dmic: dmic@4012e000 { @@ -356,6 +417,8 @@ reg-names = "mpu", "dma"; interrupts = <0 114 0x4>; ti,hwmods = "dmic"; + dmas = <&sdma 67>; + dma-names = "up_link"; }; mcbsp1: mcbsp@40122000 { @@ -367,6 +430,9 @@ interrupt-names = "common"; ti,buffer-size = <128>; ti,hwmods = "mcbsp1"; + dmas = <&sdma 33>, + <&sdma 34>; + dma-names = "tx", "rx"; }; mcbsp2: mcbsp@40124000 { @@ -378,6 +444,9 @@ interrupt-names = "common"; ti,buffer-size = <128>; ti,hwmods = "mcbsp2"; + dmas = <&sdma 17>, + <&sdma 18>; + dma-names = "tx", "rx"; }; mcbsp3: mcbsp@40126000 { @@ -389,6 +458,9 @@ interrupt-names = "common"; ti,buffer-size = <128>; ti,hwmods = "mcbsp3"; + dmas = <&sdma 19>, + <&sdma 20>; + dma-names = "tx", "rx"; }; mcbsp4: mcbsp@48096000 { @@ -399,6 +471,9 @@ interrupt-names = "common"; ti,buffer-size = <128>; ti,hwmods = "mcbsp4"; + dmas = <&sdma 31>, + <&sdma 32>; + dma-names = "tx", "rx"; }; keypad: keypad@4a31c000 { @@ -438,10 +513,15 @@ #size-cells = <1>; ranges; ti,hwmods = "ocp2scp_usb_phy"; + usb2_phy: usb2phy@4a0ad080 { + compatible = "ti,omap-usb2"; + reg = <0x4a0ad080 0x58>; + ctrl-module = <&omap_control_usb>; + }; }; timer1: timer@4a318000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x4a318000 0x80>; interrupts = <0 37 0x4>; ti,hwmods = "timer1"; @@ -449,28 +529,28 @@ }; timer2: timer@48032000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x48032000 0x80>; interrupts = <0 38 0x4>; ti,hwmods = "timer2"; }; timer3: timer@48034000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x48034000 0x80>; interrupts = <0 39 0x4>; ti,hwmods = "timer3"; }; timer4: timer@48036000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x48036000 0x80>; interrupts = <0 40 0x4>; ti,hwmods = "timer4"; }; timer5: timer@40138000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x40138000 0x80>, <0x49038000 0x80>; interrupts = <0 41 0x4>; @@ -479,7 +559,7 @@ }; timer6: timer@4013a000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x4013a000 0x80>, <0x4903a000 0x80>; interrupts = <0 42 0x4>; @@ -488,7 +568,7 @@ }; timer7: timer@4013c000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x4013c000 0x80>, <0x4903c000 0x80>; interrupts = <0 43 0x4>; @@ -497,7 +577,7 @@ }; timer8: timer@4013e000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x4013e000 0x80>, <0x4903e000 0x80>; interrupts = <0 44 0x4>; @@ -507,7 +587,7 @@ }; timer9: timer@4803e000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x4803e000 0x80>; interrupts = <0 45 0x4>; ti,hwmods = "timer9"; @@ -515,7 +595,7 @@ }; timer10: timer@48086000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap3430-timer"; reg = <0x48086000 0x80>; interrupts = <0 46 0x4>; ti,hwmods = "timer10"; @@ -523,7 +603,7 @@ }; timer11: timer@48088000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap4430-timer"; reg = <0x48088000 0x80>; interrupts = <0 47 0x4>; ti,hwmods = "timer11"; @@ -559,5 +639,26 @@ interrupts = <0 77 0x4>; }; }; + + omap_control_usb: omap-control-usb@4a002300 { + compatible = "ti,omap-control-usb"; + reg = <0x4a002300 0x4>, + <0x4a00233c 0x4>; + reg-names = "control_dev_conf", "otghs_control"; + ti,type = <1>; + }; + + usb_otg_hs: usb_otg_hs@4a0ab000 { + compatible = "ti,omap4-musb"; + reg = <0x4a0ab000 0x7ff>; + interrupts = <0 92 0x4>, <0 93 0x4>; + interrupt-names = "mc", "dma"; + ti,hwmods = "usb_otg_hs"; + usb-phy = <&usb2_phy>; + multipoint = <1>; + num-eps = <16>; + ram-bits = <12>; + ti,has-mailbox; + }; }; }; diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi new file mode 100644 index 000000000000..cccf39af4925 --- /dev/null +++ b/arch/arm/boot/dts/omap443x.dtsi @@ -0,0 +1,27 @@ +/* + * Device Tree Source for OMAP443x SoC + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "omap4.dtsi" + +/ { + cpus { + cpu@0 { + /* OMAP443x variants OPP50-OPPNT */ + operating-points = < + /* kHz uV */ + 300000 1025000 + 600000 1200000 + 800000 1313000 + 1008000 1375000 + >; + clock-latency = <300000>; /* From legacy driver */ + }; + }; +}; diff --git a/arch/arm/boot/dts/omap4460.dtsi b/arch/arm/boot/dts/omap4460.dtsi new file mode 100644 index 000000000000..2cf227c86099 --- /dev/null +++ b/arch/arm/boot/dts/omap4460.dtsi @@ -0,0 +1,32 @@ +/* + * Device Tree Source for OMAP4460 SoC + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ +/include/ "omap4.dtsi" + +/ { + cpus { + /* OMAP446x 'standard device' variants OPP50 to OPPTurbo */ + cpu@0 { + operating-points = < + /* kHz uV */ + 350000 1025000 + 700000 1200000 + 920000 1313000 + >; + clock-latency = <300000>; /* From legacy driver */ + }; + }; + + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts = <0 54 0x4>, + <0 55 0x4>; + ti,hwmods = "debugss"; + }; +}; diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts index 8722c15bbba2..982acd19477d 100644 --- a/arch/arm/boot/dts/omap5-evm.dts +++ b/arch/arm/boot/dts/omap5-evm.dts @@ -16,7 +16,7 @@ memory { device_type = "memory"; - reg = <0x80000000 0x80000000>; /* 2 GB */ + reg = <0x80000000 0x7F000000>; /* 2032 MB */ }; vmmcsd_fixed: fixedregulator-mmcsd { @@ -80,6 +80,68 @@ 0x15a 0x100 /* abemcbsp2_clkx.abemcbsp2_clkx INPUT | MODE0 */ >; }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + 0x1b2 0x118 /* i2c1_scl PULLUP | INPUTENABLE | MODE0 */ + 0x1b4 0x118 /* i2c1_sda PULLUP | INPUTENABLE | MODE0 */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + 0x178 0x100 /* i2c2_scl INPUTENABLE | MODE0 */ + 0x17a 0x100 /* i2c2_sda INPUTENABLE | MODE0 */ + >; + }; + + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + 0x13a 0x100 /* i2c3_scl INPUTENABLE | MODE0 */ + 0x13c 0x100 /* i2c3_sda INPUTENABLE | MODE0 */ + >; + }; + + i2c4_pins: pinmux_i2c4_pins { + pinctrl-single,pins = < + 0xb8 0x100 /* i2c4_scl INPUTENABLE | MODE0 */ + 0xba 0x100 /* i2c4_sda INPUTENABLE | MODE0 */ + >; + }; + + i2c5_pins: pinmux_i2c5_pins { + pinctrl-single,pins = < + 0x184 0x100 /* i2c5_scl INPUTENABLE | MODE0 */ + 0x186 0x100 /* i2c5_sda INPUTENABLE | MODE0 */ + >; + }; + + mcspi2_pins: pinmux_mcspi2_pins { + pinctrl-single,pins = < + 0xbc 0x100 /* MCSPI2_CLK INPUTENABLE | MODE0 */ + 0xbe 0x100 /* MCSPI2_SIMO INPUTENABLE | MODE0 */ + 0xc0 0x118 /* MCSPI2_SOMI PULLUP | INPUTENABLE | MODE0*/ + 0xc2 0x0 /* MCSPI2_CS MODE0*/ + >; + }; + + mcspi3_pins: pinmux_mcspi3_pins { + pinctrl-single,pins = < + 0x78 0x101 /* MCSPI2_SOMI INPUTENABLE | MODE1 */ + 0x7a 0x101 /* MCSPI2_CS INPUTENABLE | MODE1 */ + 0x7c 0x101 /* MCSPI2_SIMO INPUTENABLE | MODE1 */ + 0x7e 0x101 /* MCSPI2_CLK INPUTENABLE | MODE1 */ + >; + }; + + mcspi4_pins: pinmux_mcspi4_pins { + pinctrl-single,pins = < + 0x164 0x101 /* MCSPI2_CLK INPUTENABLE | MODE1 */ + 0x168 0x101 /* MCSPI2_SIMO INPUTENABLE | MODE1 */ + 0x16a 0x101 /* MCSPI2_SOMI INPUTENABLE | MODE1 */ + 0x16c 0x101 /* MCSPI2_CS INPUTENABLE | MODE1 */ + >; + }; }; &mmc1 { @@ -106,7 +168,17 @@ status = "disabled"; }; +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + clock-frequency = <400000>; +}; + &i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + clock-frequency = <400000>; /* Pressure Sensor */ @@ -116,7 +188,17 @@ }; }; +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; + + clock-frequency = <400000>; +}; + &i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins>; + clock-frequency = <400000>; /* Temperature Sensor */ @@ -126,6 +208,13 @@ }; }; +&i2c5 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_pins>; + + clock-frequency = <400000>; +}; + &keypad { keypad,num-rows = <8>; keypad,num-columns = <8>; @@ -151,3 +240,22 @@ cs1-used; device-handle = <&samsung_K3PE0E000B>; }; + +&mcspi1 { + +}; + +&mcspi2 { + pinctrl-names = "default"; + pinctrl-0 = <&mcspi2_pins>; +}; + +&mcspi3 { + pinctrl-names = "default"; + pinctrl-0 = <&mcspi3_pins>; +}; + +&mcspi4 { + pinctrl-names = "default"; + pinctrl-0 = <&mcspi4_pins>; +}; diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 790bb2a4b343..3dd7ff825828 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -18,6 +18,9 @@ /include/ "skeleton.dtsi" / { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ti,omap5"; interrupt-parent = <&gic>; @@ -33,24 +36,32 @@ cpus { cpu@0 { compatible = "arm,cortex-a15"; - timer { - compatible = "arm,armv7-timer"; - /* 14th PPI IRQ, active low level-sensitive */ - interrupts = <1 14 0x308>; - clock-frequency = <6144000>; - }; }; cpu@1 { compatible = "arm,cortex-a15"; - timer { - compatible = "arm,armv7-timer"; - /* 14th PPI IRQ, active low level-sensitive */ - interrupts = <1 14 0x308>; - clock-frequency = <6144000>; - }; }; }; + timer { + compatible = "arm,armv7-timer"; + /* PPI secure/nonsecure IRQ, active low level-sensitive */ + interrupts = <1 13 0x308>, + <1 14 0x308>, + <1 11 0x308>, + <1 10 0x308>; + clock-frequency = <6144000>; + }; + + gic: interrupt-controller@48211000 { + compatible = "arm,cortex-a15-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x48211000 0x1000>, + <0x48212000 0x1000>, + <0x48214000 0x2000>, + <0x48216000 0x2000>; + }; + /* * The soc node represents the soc top level view. It is uses for IPs * that are not memory mapped in the MPU view or for the MPU itself. @@ -76,6 +87,11 @@ #size-cells = <1>; ranges; ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3"; + reg = <0x44000000 0x2000>, + <0x44800000 0x3000>, + <0x45000000 0x4000>; + interrupts = <0 9 0x4>, + <0 10 0x4>; counter32k: counter@4ae04000 { compatible = "ti,omap-counter32k"; @@ -100,12 +116,16 @@ pinctrl-single,function-mask = <0x7fff>; }; - gic: interrupt-controller@48211000 { - compatible = "arm,cortex-a15-gic"; - interrupt-controller; - #interrupt-cells = <3>; - reg = <0x48211000 0x1000>, - <0x48212000 0x1000>; + sdma: dma-controller@4a056000 { + compatible = "ti,omap4430-sdma"; + reg = <0x4a056000 0x1000>; + interrupts = <0 12 0x4>, + <0 13 0x4>, + <0 14 0x4>, + <0 15 0x4>; + #dma-cells = <1>; + #dma-channels = <32>; + #dma-requests = <127>; }; gpio1: gpio@4ae10000 { @@ -113,10 +133,11 @@ reg = <0x4ae10000 0x200>; interrupts = <0 29 0x4>; ti,hwmods = "gpio1"; + ti,gpio-always-on; gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio2: gpio@48055000 { @@ -127,7 +148,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio3: gpio@48057000 { @@ -138,7 +159,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio4: gpio@48059000 { @@ -149,7 +170,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio5: gpio@4805b000 { @@ -160,7 +181,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio6: gpio@4805d000 { @@ -171,7 +192,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio7: gpio@48051000 { @@ -182,7 +203,7 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; }; gpio8: gpio@48053000 { @@ -193,7 +214,18 @@ gpio-controller; #gpio-cells = <2>; interrupt-controller; - #interrupt-cells = <1>; + #interrupt-cells = <2>; + }; + + gpmc: gpmc@50000000 { + compatible = "ti,omap4430-gpmc"; + reg = <0x50000000 0x1000>; + #address-cells = <2>; + #size-cells = <1>; + interrupts = <0 20 0x4>; + gpmc,num-cs = <8>; + gpmc,num-waitpins = <4>; + ti,hwmods = "gpmc"; }; i2c1: i2c@48070000 { @@ -241,6 +273,65 @@ ti,hwmods = "i2c5"; }; + mcspi1: spi@48098000 { + compatible = "ti,omap4-mcspi"; + reg = <0x48098000 0x200>; + interrupts = <0 65 0x4>; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi1"; + ti,spi-num-cs = <4>; + dmas = <&sdma 35>, + <&sdma 36>, + <&sdma 37>, + <&sdma 38>, + <&sdma 39>, + <&sdma 40>, + <&sdma 41>, + <&sdma 42>; + dma-names = "tx0", "rx0", "tx1", "rx1", + "tx2", "rx2", "tx3", "rx3"; + }; + + mcspi2: spi@4809a000 { + compatible = "ti,omap4-mcspi"; + reg = <0x4809a000 0x200>; + interrupts = <0 66 0x4>; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi2"; + ti,spi-num-cs = <2>; + dmas = <&sdma 43>, + <&sdma 44>, + <&sdma 45>, + <&sdma 46>; + dma-names = "tx0", "rx0", "tx1", "rx1"; + }; + + mcspi3: spi@480b8000 { + compatible = "ti,omap4-mcspi"; + reg = <0x480b8000 0x200>; + interrupts = <0 91 0x4>; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi3"; + ti,spi-num-cs = <2>; + dmas = <&sdma 15>, <&sdma 16>; + dma-names = "tx0", "rx0"; + }; + + mcspi4: spi@480ba000 { + compatible = "ti,omap4-mcspi"; + reg = <0x480ba000 0x200>; + interrupts = <0 48 0x4>; + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi4"; + ti,spi-num-cs = <1>; + dmas = <&sdma 70>, <&sdma 71>; + dma-names = "tx0", "rx0"; + }; + uart1: serial@4806a000 { compatible = "ti,omap4-uart"; reg = <0x4806a000 0x100>; @@ -296,6 +387,8 @@ ti,hwmods = "mmc1"; ti,dual-volt; ti,needs-special-reset; + dmas = <&sdma 61>, <&sdma 62>; + dma-names = "tx", "rx"; }; mmc2: mmc@480b4000 { @@ -304,6 +397,8 @@ interrupts = <0 86 0x4>; ti,hwmods = "mmc2"; ti,needs-special-reset; + dmas = <&sdma 47>, <&sdma 48>; + dma-names = "tx", "rx"; }; mmc3: mmc@480ad000 { @@ -312,6 +407,8 @@ interrupts = <0 94 0x4>; ti,hwmods = "mmc3"; ti,needs-special-reset; + dmas = <&sdma 77>, <&sdma 78>; + dma-names = "tx", "rx"; }; mmc4: mmc@480d1000 { @@ -320,6 +417,8 @@ interrupts = <0 96 0x4>; ti,hwmods = "mmc4"; ti,needs-special-reset; + dmas = <&sdma 57>, <&sdma 58>; + dma-names = "tx", "rx"; }; mmc5: mmc@480d5000 { @@ -328,10 +427,13 @@ interrupts = <0 59 0x4>; ti,hwmods = "mmc5"; ti,needs-special-reset; + dmas = <&sdma 59>, <&sdma 60>; + dma-names = "tx", "rx"; }; keypad: keypad@4ae1c000 { compatible = "ti,omap4-keypad"; + reg = <0x4ae1c000 0x400>; ti,hwmods = "kbd"; }; @@ -342,6 +444,9 @@ reg-names = "mpu", "dma"; interrupts = <0 112 0x4>; ti,hwmods = "mcpdm"; + dmas = <&sdma 65>, + <&sdma 66>; + dma-names = "up_link", "dn_link"; }; dmic: dmic@4012e000 { @@ -351,6 +456,8 @@ reg-names = "mpu", "dma"; interrupts = <0 114 0x4>; ti,hwmods = "dmic"; + dmas = <&sdma 67>; + dma-names = "up_link"; }; mcbsp1: mcbsp@40122000 { @@ -362,6 +469,9 @@ interrupt-names = "common"; ti,buffer-size = <128>; ti,hwmods = "mcbsp1"; + dmas = <&sdma 33>, + <&sdma 34>; + dma-names = "tx", "rx"; }; mcbsp2: mcbsp@40124000 { @@ -373,6 +483,9 @@ interrupt-names = "common"; ti,buffer-size = <128>; ti,hwmods = "mcbsp2"; + dmas = <&sdma 17>, + <&sdma 18>; + dma-names = "tx", "rx"; }; mcbsp3: mcbsp@40126000 { @@ -384,10 +497,13 @@ interrupt-names = "common"; ti,buffer-size = <128>; ti,hwmods = "mcbsp3"; + dmas = <&sdma 19>, + <&sdma 20>; + dma-names = "tx", "rx"; }; timer1: timer@4ae18000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x4ae18000 0x80>; interrupts = <0 37 0x4>; ti,hwmods = "timer1"; @@ -395,28 +511,28 @@ }; timer2: timer@48032000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x48032000 0x80>; interrupts = <0 38 0x4>; ti,hwmods = "timer2"; }; timer3: timer@48034000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x48034000 0x80>; interrupts = <0 39 0x4>; ti,hwmods = "timer3"; }; timer4: timer@48036000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x48036000 0x80>; interrupts = <0 40 0x4>; ti,hwmods = "timer4"; }; timer5: timer@40138000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x40138000 0x80>, <0x49038000 0x80>; interrupts = <0 41 0x4>; @@ -425,7 +541,7 @@ }; timer6: timer@4013a000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x4013a000 0x80>, <0x4903a000 0x80>; interrupts = <0 42 0x4>; @@ -435,7 +551,7 @@ }; timer7: timer@4013c000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x4013c000 0x80>, <0x4903c000 0x80>; interrupts = <0 43 0x4>; @@ -444,7 +560,7 @@ }; timer8: timer@4013e000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x4013e000 0x80>, <0x4903e000 0x80>; interrupts = <0 44 0x4>; @@ -454,27 +570,34 @@ }; timer9: timer@4803e000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x4803e000 0x80>; interrupts = <0 45 0x4>; ti,hwmods = "timer9"; }; timer10: timer@48086000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x48086000 0x80>; interrupts = <0 46 0x4>; ti,hwmods = "timer10"; }; timer11: timer@48088000 { - compatible = "ti,omap2-timer"; + compatible = "ti,omap5430-timer"; reg = <0x48088000 0x80>; interrupts = <0 47 0x4>; ti,hwmods = "timer11"; ti,timer-pwm; }; + wdt2: wdt@4ae14000 { + compatible = "ti,omap5-wdt", "ti,omap3-wdt"; + reg = <0x4ae14000 0x80>; + interrupts = <0 80 0x4>; + ti,hwmods = "wd_timer2"; + }; + emif1: emif@0x4c000000 { compatible = "ti,emif-4d5"; ti,hwmods = "emif1"; @@ -496,5 +619,53 @@ hw-caps-ll-interface; hw-caps-temp-alert; }; + + omap_control_usb: omap-control-usb@4a002300 { + compatible = "ti,omap-control-usb"; + reg = <0x4a002300 0x4>, + <0x4a002370 0x4>; + reg-names = "control_dev_conf", "phy_power_usb"; + ti,type = <2>; + }; + + omap_dwc3@4a020000 { + compatible = "ti,dwc3"; + ti,hwmods = "usb_otg_ss"; + reg = <0x4a020000 0x1000>; + interrupts = <0 93 4>; + #address-cells = <1>; + #size-cells = <1>; + utmi-mode = <2>; + ranges; + dwc3@4a030000 { + compatible = "synopsys,dwc3"; + reg = <0x4a030000 0x1000>; + interrupts = <0 92 4>; + usb-phy = <&usb2_phy>, <&usb3_phy>; + tx-fifo-resize; + }; + }; + + ocp2scp { + compatible = "ti,omap-ocp2scp"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + ti,hwmods = "ocp2scp1"; + usb2_phy: usb2phy@4a084000 { + compatible = "ti,omap-usb2"; + reg = <0x4a084000 0x7c>; + ctrl-module = <&omap_control_usb>; + }; + + usb3_phy: usb3phy@4a084400 { + compatible = "ti,omap-usb3"; + reg = <0x4a084400 0x80>, + <0x4a084800 0x64>, + <0x4a084c00 0x40>; + reg-names = "phy_rx", "phy_tx", "pll_ctrl"; + ctrl-module = <&omap_control_usb>; + }; + }; }; }; diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts new file mode 100644 index 000000000000..f603c6946c29 --- /dev/null +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -0,0 +1,52 @@ +/* + * Device Tree Source for the APE6EVM board + * + * Copyright (C) 2013 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/dts-v1/; +/include/ "r8a73a4.dtsi" + +/ { + model = "APE6EVM"; + compatible = "renesas,ape6evm", "renesas,r8a73a4"; + + chosen { + bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x40000000>; + }; + + ape6evm_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + lbsc { + #address-cells = <1>; + #size-cells = <1>; + + ethernet@8000000 { + compatible = "smsc,lan9118", "smsc,lan9115"; + reg = <0x08000000 0x1000>; + interrupt-parent = <&irqc1>; + interrupts = <8 0x4>; + phy-mode = "mii"; + reg-io-width = <4>; + smsc,irq-active-high; + smsc,irq-push-pull; + vdd33a-supply = <&ape6evm_fixed_3v3>; + vddvario-supply = <&ape6evm_fixed_3v3>; + }; + }; +}; diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi new file mode 100644 index 000000000000..fde2a337d1ff --- /dev/null +++ b/arch/arm/boot/dts/r8a73a4.dtsi @@ -0,0 +1,94 @@ +/* + * Device Tree Source for the r8a73a4 SoC + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Magnus Damm + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/ { + compatible = "renesas,r8a73a4"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0>; + clock-frequency = <1500000000>; + }; + }; + + gic: interrupt-controller@f1001000 { + compatible = "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0xf1001000 0 0x1000>, + <0 0xf1002000 0 0x1000>, + <0 0xf1004000 0 0x2000>, + <0 0xf1006000 0 0x2000>; + interrupts = <1 9 0xf04>; + + gic-cpuif@4 { + compatible = "arm,gic-cpuif"; + cpuif-id = <4>; + cpu = <&cpu0>; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + }; + + irqc0: interrupt-controller@e61c0000 { + compatible = "renesas,irqc"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0 0xe61c0000 0 0x200>; + interrupt-parent = <&gic>; + interrupts = <0 0 4>, <0 1 4>, <0 2 4>, <0 3 4>, + <0 4 4>, <0 5 4>, <0 6 4>, <0 7 4>, + <0 8 4>, <0 9 4>, <0 10 4>, <0 11 4>, + <0 12 4>, <0 13 4>, <0 14 4>, <0 15 4>, + <0 16 4>, <0 17 4>, <0 18 4>, <0 19 4>, + <0 20 4>, <0 21 4>, <0 22 4>, <0 23 4>, + <0 24 4>, <0 25 4>, <0 26 4>, <0 27 4>, + <0 28 4>, <0 29 4>, <0 30 4>, <0 31 4>; + }; + + irqc1: interrupt-controller@e61c0200 { + compatible = "renesas,irqc"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0 0xe61c0200 0 0x200>; + interrupt-parent = <&gic>; + interrupts = <0 32 4>, <0 33 4>, <0 34 4>, <0 35 4>, + <0 36 4>, <0 37 4>, <0 38 4>, <0 39 4>, + <0 40 4>, <0 41 4>, <0 42 4>, <0 43 4>, + <0 44 4>, <0 45 4>, <0 46 4>, <0 47 4>, + <0 48 4>, <0 49 4>, <0 50 4>, <0 51 4>, + <0 52 4>, <0 53 4>, <0 54 4>, <0 55 4>, + <0 56 4>, <0 57 4>; + }; + + thermal@e61f0000 { + compatible = "renesas,rcar-thermal"; + reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>, + <0 0xe61f0200 0 0x38>, <0 0xe61f0300 0 0x38>; + interrupt-parent = <&gic>; + interrupts = <0 69 4>; + }; +}; diff --git a/arch/arm/boot/dts/r8a7778-bockw.dts b/arch/arm/boot/dts/r8a7778-bockw.dts new file mode 100644 index 000000000000..0076b1e8a0fb --- /dev/null +++ b/arch/arm/boot/dts/r8a7778-bockw.dts @@ -0,0 +1,32 @@ +/* + * Reference Device Tree Source for the Bock-W board + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * based on r8a7779 + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Simon Horman + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/dts-v1/; +/include/ "r8a7778.dtsi" + +/ { + model = "bockw"; + compatible = "renesas,bockw", "renesas,r8a7778"; + + chosen { + bootargs = "console=ttySC0,115200 ignore_loglevel ip=dhcp root=/dev/nfs"; + }; + + memory { + device_type = "memory"; + reg = <0x60000000 0x10000000>; + }; +}; diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi new file mode 100644 index 000000000000..474373559bdc --- /dev/null +++ b/arch/arm/boot/dts/r8a7778.dtsi @@ -0,0 +1,35 @@ +/* + * Device Tree Source for Renesas r8a7778 + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * based on r8a7779 + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Simon Horman + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "renesas,r8a7778"; + + cpus { + cpu@0 { + compatible = "arm,cortex-a9"; + }; + }; + + gic: interrupt-controller@fe438000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xfe438000 0x1000>, + <0xfe430000 0x100>; + }; +}; diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts new file mode 100644 index 000000000000..09a84fce89d6 --- /dev/null +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -0,0 +1,31 @@ +/* + * Device Tree Source for the Lager board + * + * Copyright (C) 2013 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/dts-v1/; +/include/ "r8a7790.dtsi" + +/ { + model = "Lager"; + compatible = "renesas,lager", "renesas,r8a7790"; + + chosen { + bootargs = "console=ttySC6,115200 ignore_loglevel"; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0 0x40000000 0 0x80000000>; + }; + + lbsc { + #address-cells = <1>; + #size-cells = <1>; + }; +}; diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi new file mode 100644 index 000000000000..7a1711027e41 --- /dev/null +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -0,0 +1,63 @@ +/* + * Device Tree Source for the r8a7790 SoC + * + * Copyright (C) 2013 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/ { + compatible = "renesas,r8a7790"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0>; + clock-frequency = <1300000000>; + }; + }; + + gic: interrupt-controller@f1001000 { + compatible = "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0xf1001000 0 0x1000>, + <0 0xf1002000 0 0x1000>, + <0 0xf1004000 0 0x2000>, + <0 0xf1006000 0 0x2000>; + interrupts = <1 9 0xf04>; + + gic-cpuif@4 { + compatible = "arm,gic-cpuif"; + cpuif-id = <4>; + cpu = <&cpu0>; + }; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + }; + + irqc0: interrupt-controller@e61c0000 { + compatible = "renesas,irqc"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0 0xe61c0000 0 0x200>; + interrupt-parent = <&gic>; + interrupts = <0 0 4>, <0 1 4>, <0 2 4>, <0 3 4>; + }; +}; diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi index 39b0458d365a..2e643ea51cce 100644 --- a/arch/arm/boot/dts/sama5d3.dtsi +++ b/arch/arm/boot/dts/sama5d3.dtsi @@ -60,6 +60,8 @@ compatible = "atmel,hsmci"; reg = <0xf0000000 0x600>; interrupts = <21 4 0>; + dmas = <&dma0 2 0>; + dma-names = "rxtx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_dat4_7>; status = "disabled"; @@ -111,6 +113,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf0014000 0x4000>; interrupts = <18 4 6>; + dmas = <&dma0 2 7>, + <&dma0 2 8>; + dma-names = "tx", "rx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c0>; #address-cells = <1>; @@ -122,6 +127,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf0018000 0x4000>; interrupts = <19 4 6>; + dmas = <&dma0 2 9>, + <&dma0 2 10>; + dma-names = "tx", "rx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; #address-cells = <1>; @@ -167,6 +175,8 @@ compatible = "atmel,hsmci"; reg = <0xf8000000 0x600>; interrupts = <22 4 0>; + dmas = <&dma1 2 0>; + dma-names = "rxtx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3>; status = "disabled"; @@ -178,6 +188,8 @@ compatible = "atmel,hsmci"; reg = <0xf8004000 0x600>; interrupts = <23 4 0>; + dmas = <&dma1 2 1>; + dma-names = "rxtx"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mmc2_clk_cmd_dat0 &pinctrl_mmc2_dat1_3>; status = "disabled"; @@ -294,6 +306,9 @@ compatible = "atmel,at91sam9x5-i2c"; reg = <0xf801c000 0x4000>; interrupts = <20 4 6>; + dmas = <&dma1 2 11>, + <&dma1 2 12>; + dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; @@ -348,14 +363,14 @@ compatible = "atmel,at91sam9g45-dma"; reg = <0xffffe600 0x200>; interrupts = <30 4 0>; - #dma-cells = <1>; + #dma-cells = <2>; }; dma1: dma-controller@ffffe800 { compatible = "atmel,at91sam9g45-dma"; reg = <0xffffe800 0x200>; interrupts = <31 4 0>; - #dma-cells = <1>; + #dma-cells = <2>; }; ramc0: ramc@ffffea00 { diff --git a/arch/arm/boot/dts/sama5d34ek.dts b/arch/arm/boot/dts/sama5d34ek.dts index d2739f8d7ae9..6bebfcdcb1d1 100644 --- a/arch/arm/boot/dts/sama5d34ek.dts +++ b/arch/arm/boot/dts/sama5d34ek.dts @@ -12,7 +12,7 @@ / { model = "Atmel SAMA5D34-EK"; - compatible = "atmel,sama5d34ek", "atmel,sama5ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5"; + compatible = "atmel,sama5d34ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5"; ahb { apb { diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts index f33b5ccb7446..5972abb55f9c 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts @@ -44,6 +44,19 @@ regulator-always-on; regulator-boot-on; }; + + lan9220@10000000 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0x10000000 0x100>; + phy-mode = "mii"; + interrupt-parent = <&irqpin0>; + interrupts = <3 0>; /* active low */ + reg-io-width = <4>; + smsc,irq-push-pull; + smsc,save-mac-address; + vddvario-supply = <®_1p8v>; + vdd33a-supply = <®_3p3v>; + }; }; &mmcif { diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index 3e4d383ac6d9..ec40bf78289e 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -38,6 +38,87 @@ <0xf0000100 0x100>; }; + irqpin0: irqpin@e6900000 { + compatible = "renesas,intc-irqpin"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0xe6900000 4>, + <0xe6900010 4>, + <0xe6900020 1>, + <0xe6900040 1>, + <0xe6900060 1>; + interrupt-parent = <&gic>; + interrupts = <0 1 0x4 + 0 2 0x4 + 0 3 0x4 + 0 4 0x4 + 0 5 0x4 + 0 6 0x4 + 0 7 0x4 + 0 8 0x4>; + }; + + irqpin1: irqpin@e6900004 { + compatible = "renesas,intc-irqpin"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0xe6900004 4>, + <0xe6900014 4>, + <0xe6900024 1>, + <0xe6900044 1>, + <0xe6900064 1>; + interrupt-parent = <&gic>; + interrupts = <0 9 0x4 + 0 10 0x4 + 0 11 0x4 + 0 12 0x4 + 0 13 0x4 + 0 14 0x4 + 0 15 0x4 + 0 16 0x4>; + control-parent; + }; + + irqpin2: irqpin@e6900008 { + compatible = "renesas,intc-irqpin"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0xe6900008 4>, + <0xe6900018 4>, + <0xe6900028 1>, + <0xe6900048 1>, + <0xe6900068 1>; + interrupt-parent = <&gic>; + interrupts = <0 17 0x4 + 0 18 0x4 + 0 19 0x4 + 0 20 0x4 + 0 21 0x4 + 0 22 0x4 + 0 23 0x4 + 0 24 0x4>; + }; + + irqpin3: irqpin@e690000c { + compatible = "renesas,intc-irqpin"; + #interrupt-cells = <2>; + interrupt-controller; + reg = <0xe690000c 4>, + <0xe690001c 4>, + <0xe690002c 1>, + <0xe690004c 1>, + <0xe690006c 1>; + interrupt-parent = <&gic>; + interrupts = <0 25 0x4 + 0 26 0x4 + 0 27 0x4 + 0 28 0x4 + 0 29 0x4 + 0 30 0x4 + 0 31 0x4 + 0 32 0x4>; + }; + i2c0: i2c@0xe6820000 { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi index c511c4772efd..54d128d35681 100644 --- a/arch/arm/boot/dts/spear1340.dtsi +++ b/arch/arm/boot/dts/spear1340.dtsi @@ -113,6 +113,9 @@ reg = <0xb4100000 0x1000>; interrupts = <0 105 0x4>; status = "disabled"; + dmas = <&dwdma0 0x600 0 0 1>, /* 0xC << 11 */ + <&dwdma0 0x680 0 1 0>; /* 0xD << 7 */ + dma-names = "tx", "rx"; }; thermal@e07008c4 { diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi index b4ca60f4eb42..45597fd91050 100644 --- a/arch/arm/boot/dts/spear13xx.dtsi +++ b/arch/arm/boot/dts/spear13xx.dtsi @@ -98,13 +98,24 @@ reg = <0xb2800000 0x1000>; interrupts = <0 29 0x4>; status = "disabled"; + dmas = <&dwdma0 0 0 0 0>; + dma-names = "data"; }; - dma@ea800000 { + dwdma0: dma@ea800000 { compatible = "snps,dma-spear1340"; reg = <0xea800000 0x1000>; interrupts = <0 19 0x4>; status = "disabled"; + + dma-channels = <8>; + #dma-cells = <3>; + dma-requests = <32>; + chan_allocation_order = <1>; + chan_priority = <1>; + block_size = <0xfff>; + dma-masters = <2>; + data_width = <3 3 0 0>; }; dma@eb000000 { @@ -112,6 +123,15 @@ reg = <0xeb000000 0x1000>; interrupts = <0 59 0x4>; status = "disabled"; + + dma-requests = <32>; + dma-channels = <8>; + dma-masters = <2>; + #dma-cells = <3>; + chan_allocation_order = <1>; + chan_priority = <1>; + block_size = <0xfff>; + data_width = <3 3 0 0>; }; fsmc: flash@b0000000 { @@ -261,6 +281,9 @@ #size-cells = <0>; interrupts = <0 31 0x4>; status = "disabled"; + dmas = <&dwdma0 0x2000 0 0 0>, /* 0x4 << 11 */ + <&dwdma0 0x0280 0 0 0>; /* 0x5 << 7 */ + dma-names = "tx", "rx"; }; rtc@e0580000 { diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts index 616990dc92db..72c1f27af7f3 100644 --- a/arch/arm/boot/dts/tegra114-dalmore.dts +++ b/arch/arm/boot/dts/tegra114-dalmore.dts @@ -10,14 +10,835 @@ reg = <0x80000000 0x40000000>; }; + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + clk1_out_pw4 { + nvidia,pins = "clk1_out_pw4"; + nvidia,function = "extperiph1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + dap1_din_pn1 { + nvidia,pins = "dap1_din_pn1"; + nvidia,function = "i2s0"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + dap1_dout_pn2 { + nvidia,pins = "dap1_dout_pn2", + "dap1_fs_pn0", + "dap1_sclk_pn3"; + nvidia,function = "i2s0"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + dap2_din_pa4 { + nvidia,pins = "dap2_din_pa4"; + nvidia,function = "i2s1"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + dap2_dout_pa5 { + nvidia,pins = "dap2_dout_pa5", + "dap2_fs_pa2", + "dap2_sclk_pa3"; + nvidia,function = "i2s1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + dap4_din_pp5 { + nvidia,pins = "dap4_din_pp5", + "dap4_dout_pp6", + "dap4_fs_pp4", + "dap4_sclk_pp7"; + nvidia,function = "i2s3"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + dvfs_pwm_px0 { + nvidia,pins = "dvfs_pwm_px0", + "dvfs_clk_px2"; + nvidia,function = "cldvfs"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + ulpi_clk_py0 { + nvidia,pins = "ulpi_clk_py0", + "ulpi_data0_po1", + "ulpi_data1_po2", + "ulpi_data2_po3", + "ulpi_data3_po4", + "ulpi_data4_po5", + "ulpi_data5_po6", + "ulpi_data6_po7", + "ulpi_data7_po0"; + nvidia,function = "ulpi"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + ulpi_dir_py1 { + nvidia,pins = "ulpi_dir_py1", + "ulpi_nxt_py2"; + nvidia,function = "ulpi"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + ulpi_stp_py3 { + nvidia,pins = "ulpi_stp_py3"; + nvidia,function = "ulpi"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + cam_i2c_scl_pbb1 { + nvidia,pins = "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2"; + nvidia,function = "i2c3"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + nvidia,open-drain = <0>; + }; + cam_mclk_pcc0 { + nvidia,pins = "cam_mclk_pcc0", + "pbb0"; + nvidia,function = "vi_alt3"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + nvidia,lock = <0>; + }; + gen2_i2c_scl_pt5 { + nvidia,pins = "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6"; + nvidia,function = "i2c2"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + nvidia,open-drain = <0>; + }; + gmi_a16_pj7 { + nvidia,pins = "gmi_a16_pj7"; + nvidia,function = "uartd"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gmi_a17_pb0 { + nvidia,pins = "gmi_a17_pb0", + "gmi_a18_pb1"; + nvidia,function = "uartd"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + gmi_a19_pk7 { + nvidia,pins = "gmi_a19_pk7"; + nvidia,function = "uartd"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gmi_ad5_pg5 { + nvidia,pins = "gmi_ad5_pg5", + "gmi_cs6_n_pi3", + "gmi_wr_n_pi0"; + nvidia,function = "spi4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gmi_ad6_pg6 { + nvidia,pins = "gmi_ad6_pg6", + "gmi_ad7_pg7"; + nvidia,function = "spi4"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gmi_ad12_ph4 { + nvidia,pins = "gmi_ad12_ph4"; + nvidia,function = "rsvd4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gmi_ad9_ph1 { + nvidia,pins = "gmi_ad9_ph1"; + nvidia,function = "pwm1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gmi_cs1_n_pj2 { + nvidia,pins = "gmi_cs1_n_pj2", + "gmi_oe_n_pi1"; + nvidia,function = "soc"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + clk2_out_pw5 { + nvidia,pins = "clk2_out_pw5"; + nvidia,function = "extperiph2"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + sdmmc1_clk_pz0 { + nvidia,pins = "sdmmc1_clk_pz0"; + nvidia,function = "sdmmc1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + sdmmc1_cmd_pz1 { + nvidia,pins = "sdmmc1_cmd_pz1", + "sdmmc1_dat0_py7", + "sdmmc1_dat1_py6", + "sdmmc1_dat2_py5", + "sdmmc1_dat3_py4"; + nvidia,function = "sdmmc1"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + sdmmc1_wp_n_pv3 { + nvidia,pins = "sdmmc1_wp_n_pv3"; + nvidia,function = "spi4"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + sdmmc3_clk_pa6 { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "sdmmc3"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + sdmmc3_cmd_pa7 { + nvidia,pins = "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", + "kb_col4_pq4", + "sdmmc3_clk_lb_out_pee4", + "sdmmc3_clk_lb_in_pee5"; + nvidia,function = "sdmmc3"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + sdmmc4_clk_pcc4 { + nvidia,pins = "sdmmc4_clk_pcc4"; + nvidia,function = "sdmmc4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + sdmmc4_cmd_pt7 { + nvidia,pins = "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; + nvidia,function = "sdmmc4"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + clk_32k_out_pa0 { + nvidia,pins = "clk_32k_out_pa0"; + nvidia,function = "blink"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + kb_col0_pq0 { + nvidia,pins = "kb_col0_pq0", + "kb_col1_pq1", + "kb_col2_pq2", + "kb_row0_pr0", + "kb_row1_pr1", + "kb_row2_pr2"; + nvidia,function = "kbc"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + dap3_din_pp1 { + nvidia,pins = "dap3_din_pp1", + "dap3_sclk_pp3"; + nvidia,function = "displayb"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <0>; + }; + pv0 { + nvidia,pins = "pv0"; + nvidia,function = "rsvd4"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <0>; + }; + kb_row7_pr7 { + nvidia,pins = "kb_row7_pr7"; + nvidia,function = "rsvd2"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + kb_row10_ps2 { + nvidia,pins = "kb_row10_ps2"; + nvidia,function = "uarta"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + kb_row9_ps1 { + nvidia,pins = "kb_row9_ps1"; + nvidia,function = "uarta"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + pwr_i2c_scl_pz6 { + nvidia,pins = "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7"; + nvidia,function = "i2cpwr"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + nvidia,open-drain = <0>; + }; + sys_clk_req_pz5 { + nvidia,pins = "sys_clk_req_pz5"; + nvidia,function = "sysclk"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + core_pwr_req { + nvidia,pins = "core_pwr_req"; + nvidia,function = "pwron"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + cpu_pwr_req { + nvidia,pins = "cpu_pwr_req"; + nvidia,function = "cpu"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + pwr_int_n { + nvidia,pins = "pwr_int_n"; + nvidia,function = "pmi"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + reset_out_n { + nvidia,pins = "reset_out_n"; + nvidia,function = "reset_out_n"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + clk3_out_pee0 { + nvidia,pins = "clk3_out_pee0"; + nvidia,function = "extperiph3"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gen1_i2c_scl_pc4 { + nvidia,pins = "gen1_i2c_scl_pc4", + "gen1_i2c_sda_pc5"; + nvidia,function = "i2c1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + nvidia,open-drain = <0>; + }; + uart2_cts_n_pj5 { + nvidia,pins = "uart2_cts_n_pj5"; + nvidia,function = "uartb"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + uart2_rts_n_pj6 { + nvidia,pins = "uart2_rts_n_pj6"; + nvidia,function = "uartb"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + uart2_rxd_pc3 { + nvidia,pins = "uart2_rxd_pc3"; + nvidia,function = "irda"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + uart2_txd_pc2 { + nvidia,pins = "uart2_txd_pc2"; + nvidia,function = "irda"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + uart3_cts_n_pa1 { + nvidia,pins = "uart3_cts_n_pa1", + "uart3_rxd_pw7"; + nvidia,function = "uartc"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + uart3_rts_n_pc0 { + nvidia,pins = "uart3_rts_n_pc0", + "uart3_txd_pw6"; + nvidia,function = "uartc"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + owr { + nvidia,pins = "owr"; + nvidia,function = "owr"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + hdmi_cec_pee3 { + nvidia,pins = "hdmi_cec_pee3"; + nvidia,function = "cec"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + nvidia,open-drain = <0>; + }; + ddc_scl_pv4 { + nvidia,pins = "ddc_scl_pv4", + "ddc_sda_pv5"; + nvidia,function = "i2c4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + nvidia,rcv-sel = <1>; + }; + spdif_in_pk6 { + nvidia,pins = "spdif_in_pk6"; + nvidia,function = "usb"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + }; + usb_vbus_en0_pn4 { + nvidia,pins = "usb_vbus_en0_pn4"; + nvidia,function = "usb"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + nvidia,lock = <0>; + nvidia,open-drain = <1>; + }; + gpio_x6_aud_px6 { + nvidia,pins = "gpio_x6_aud_px6"; + nvidia,function = "spi6"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + nvidia,enable-input = <1>; + }; + gpio_x4_aud_px4 { + nvidia,pins = "gpio_x4_aud_px4", + "gpio_x7_aud_px7"; + nvidia,function = "rsvd1"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gpio_x5_aud_px5 { + nvidia,pins = "gpio_x5_aud_px5"; + nvidia,function = "rsvd1"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gpio_w2_aud_pw2 { + nvidia,pins = "gpio_w2_aud_pw2"; + nvidia,function = "rsvd2"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gpio_w3_aud_pw3 { + nvidia,pins = "gpio_w3_aud_pw3"; + nvidia,function = "spi6"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gpio_x1_aud_px1 { + nvidia,pins = "gpio_x1_aud_px1"; + nvidia,function = "rsvd4"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gpio_x3_aud_px3 { + nvidia,pins = "gpio_x3_aud_px3"; + nvidia,function = "rsvd4"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + dap3_fs_pp0 { + nvidia,pins = "dap3_fs_pp0"; + nvidia,function = "i2s2"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + dap3_dout_pp2 { + nvidia,pins = "dap3_dout_pp2"; + nvidia,function = "i2s2"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + pv1 { + nvidia,pins = "pv1"; + nvidia,function = "rsvd1"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + pbb3 { + nvidia,pins = "pbb3", + "pbb5", + "pbb6", + "pbb7"; + nvidia,function = "rsvd4"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + pcc1 { + nvidia,pins = "pcc1", + "pcc2"; + nvidia,function = "rsvd4"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gmi_ad0_pg0 { + nvidia,pins = "gmi_ad0_pg0", + "gmi_ad1_pg1"; + nvidia,function = "gmi"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gmi_ad10_ph2 { + nvidia,pins = "gmi_ad10_ph2", + "gmi_ad11_ph3", + "gmi_ad13_ph5", + "gmi_ad8_ph0", + "gmi_clk_pk1"; + nvidia,function = "gmi"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + gmi_ad2_pg2 { + nvidia,pins = "gmi_ad2_pg2", + "gmi_ad3_pg3"; + nvidia,function = "gmi"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gmi_adv_n_pk0 { + nvidia,pins = "gmi_adv_n_pk0", + "gmi_cs0_n_pj0", + "gmi_cs2_n_pk3", + "gmi_cs4_n_pk2", + "gmi_cs7_n_pi6", + "gmi_dqs_p_pj3", + "gmi_iordy_pi5", + "gmi_wp_n_pc7"; + nvidia,function = "gmi"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + gmi_cs3_n_pk4 { + nvidia,pins = "gmi_cs3_n_pk4"; + nvidia,function = "gmi"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + clk2_req_pcc5 { + nvidia,pins = "clk2_req_pcc5"; + nvidia,function = "rsvd4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + kb_col3_pq3 { + nvidia,pins = "kb_col3_pq3", + "kb_col6_pq6", + "kb_col7_pq7"; + nvidia,function = "kbc"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + kb_col5_pq5 { + nvidia,pins = "kb_col5_pq5"; + nvidia,function = "kbc"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + kb_row3_pr3 { + nvidia,pins = "kb_row3_pr3", + "kb_row4_pr4", + "kb_row6_pr6", + "kb_row8_ps0"; + nvidia,function = "kbc"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + clk3_req_pee1 { + nvidia,pins = "clk3_req_pee1"; + nvidia,function = "rsvd4"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + pu4 { + nvidia,pins = "pu4"; + nvidia,function = "displayb"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <0>; + }; + pu5 { + nvidia,pins = "pu5", + "pu6"; + nvidia,function = "displayb"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + hdmi_int_pn7 { + nvidia,pins = "hdmi_int_pn7"; + nvidia,function = "rsvd1"; + nvidia,pull = <1>; + nvidia,tristate = <0>; + nvidia,enable-input = <1>; + }; + clk1_req_pee2 { + nvidia,pins = "clk1_req_pee2", + "usb_vbus_en1_pn5"; + nvidia,function = "rsvd4"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + nvidia,enable-input = <0>; + }; + + drive_sdio1 { + nvidia,pins = "drive_sdio1"; + nvidia,high-speed-mode = <1>; + nvidia,schmitt = <0>; + nvidia,low-power-mode = <3>; + nvidia,pull-down-strength = <36>; + nvidia,pull-up-strength = <20>; + nvidia,slew-rate-rising = <2>; + nvidia,slew-rate-falling = <2>; + }; + drive_sdio3 { + nvidia,pins = "drive_sdio3"; + nvidia,high-speed-mode = <1>; + nvidia,schmitt = <0>; + nvidia,low-power-mode = <3>; + nvidia,pull-down-strength = <22>; + nvidia,pull-up-strength = <36>; + nvidia,slew-rate-rising = <0>; + nvidia,slew-rate-falling = <0>; + }; + drive_gma { + nvidia,pins = "drive_gma"; + nvidia,high-speed-mode = <1>; + nvidia,schmitt = <0>; + nvidia,low-power-mode = <3>; + nvidia,pull-down-strength = <2>; + nvidia,pull-up-strength = <1>; + nvidia,slew-rate-rising = <0>; + nvidia,slew-rate-falling = <0>; + nvidia,drive-type = <1>; + }; + }; + }; + serial@70006300 { status = "okay"; }; + i2c@7000c000 { + status = "okay"; + clock-frequency = <100000>; + + battery: smart-battery { + compatible = "ti,bq20z45", "sbs,sbs-battery"; + reg = <0xb>; + battery-name = "battery"; + sbs,i2c-retry-count = <2>; + sbs,poll-retry-count = <100>; + }; + }; + + i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + tps51632 { + compatible = "ti,tps51632"; + reg = <0x43>; + regulator-name = "vdd-cpu"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1520000>; + regulator-boot-on; + regulator-always-on; + }; + + tps65090 { + compatible = "ti,tps65090"; + reg = <0x48>; + interrupt-parent = <&gpio>; + interrupts = <72 0x04>; /* gpio PJ0 */ + + vsys1-supply = <&vdd_ac_bat_reg>; + vsys2-supply = <&vdd_ac_bat_reg>; + vsys3-supply = <&vdd_ac_bat_reg>; + infet1-supply = <&vdd_ac_bat_reg>; + infet2-supply = <&vdd_ac_bat_reg>; + infet3-supply = <&tps65090_dcdc2_reg>; + infet4-supply = <&tps65090_dcdc2_reg>; + infet5-supply = <&tps65090_dcdc2_reg>; + infet6-supply = <&tps65090_dcdc2_reg>; + infet7-supply = <&tps65090_dcdc2_reg>; + vsys-l1-supply = <&vdd_ac_bat_reg>; + vsys-l2-supply = <&vdd_ac_bat_reg>; + + regulators { + tps65090_dcdc1_reg: dcdc1 { + regulator-name = "vdd-sys-5v0"; + regulator-always-on; + regulator-boot-on; + }; + + tps65090_dcdc2_reg: dcdc2 { + regulator-name = "vdd-sys-3v3"; + regulator-always-on; + regulator-boot-on; + }; + + dcdc3 { + regulator-name = "vdd-ao"; + regulator-always-on; + regulator-boot-on; + }; + + fet1 { + regulator-name = "vdd-lcd-bl"; + }; + + fet3 { + regulator-name = "vdd-modem-3v3"; + }; + + fet4 { + regulator-name = "avdd-lcd"; + }; + + fet5 { + regulator-name = "vdd-lvds"; + }; + + fet6 { + regulator-name = "vdd-sd-slot"; + regulator-always-on; + regulator-boot-on; + }; + + fet7 { + regulator-name = "vdd-com-3v3"; + }; + + ldo1 { + regulator-name = "vdd-sby-5v0"; + regulator-always-on; + regulator-boot-on; + }; + + ldo2 { + regulator-name = "vdd-sby-3v3"; + regulator-always-on; + regulator-boot-on; + }; + }; + }; + }; + pmc { nvidia,invert-interrupt; }; + sdhci@78000400 { + cd-gpios = <&gpio 170 1>; /* gpio PV2 */ + bus-width = <4>; + status = "okay"; + }; + + sdhci@78000600 { + bus-width = <8>; + status = "okay"; + non-removable; + }; + clocks { compatible = "simple-bus"; #address-cells = <1>; @@ -30,4 +851,74 @@ clock-frequency = <32768>; }; }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + vdd_ac_bat_reg: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "vdd_ac_bat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + dvdd_ts_reg: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "dvdd_ts"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&gpio 61 0>; /* GPIO PH5 */ + }; + + lcd_bl_en_reg: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "lcd_bl_en"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio 58 0>; /* GPIO PH2 */ + }; + + usb1_vbus_reg: regulator@3 { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "usb1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio 108 0>; /* GPIO PN4 */ + gpio-open-drain; + vin-supply = <&tps65090_dcdc1_reg>; + }; + + usb3_vbus_reg: regulator@4 { + compatible = "regulator-fixed"; + reg = <4>; + regulator-name = "usb2_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio 86 0>; /* GPIO PK6 */ + gpio-open-drain; + vin-supply = <&tps65090_dcdc1_reg>; + }; + + vdd_hdmi_reg: regulator@5 { + compatible = "regulator-fixed"; + reg = <5>; + regulator-name = "vdd_hdmi_5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio 81 0>; /* GPIO PK1 */ + vin-supply = <&tps65090_dcdc1_reg>; + }; + }; }; diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index c1110a9b2a91..629415ffd8dc 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi @@ -4,6 +4,13 @@ compatible = "nvidia,tegra114"; interrupt-parent = <&gic>; + aliases { + serial0 = &uarta; + serial1 = &uartb; + serial2 = &uartc; + serial3 = &uartd; + }; + gic: interrupt-controller { compatible = "arm,cortex-a15-gic"; #interrupt-cells = <3>; @@ -33,6 +40,44 @@ #clock-cells = <1>; }; + apbdma: dma { + compatible = "nvidia,tegra114-apbdma"; + reg = <0x6000a000 0x1400>; + interrupts = <0 104 0x04 + 0 105 0x04 + 0 106 0x04 + 0 107 0x04 + 0 108 0x04 + 0 109 0x04 + 0 110 0x04 + 0 111 0x04 + 0 112 0x04 + 0 113 0x04 + 0 114 0x04 + 0 115 0x04 + 0 116 0x04 + 0 117 0x04 + 0 118 0x04 + 0 119 0x04 + 0 128 0x04 + 0 129 0x04 + 0 130 0x04 + 0 131 0x04 + 0 132 0x04 + 0 133 0x04 + 0 134 0x04 + 0 135 0x04 + 0 136 0x04 + 0 137 0x04 + 0 138 0x04 + 0 139 0x04 + 0 140 0x04 + 0 141 0x04 + 0 142 0x04 + 0 143 0x04>; + clocks = <&tegra_car 34>; + }; + ahb: ahb { compatible = "nvidia,tegra114-ahb", "nvidia,tegra30-ahb"; reg = <0x6000c004 0x14c>; @@ -61,42 +106,189 @@ 0x70003000 0x40c>; /* Mux registers */ }; - serial@70006000 { + /* + * There are two serial driver i.e. 8250 based simple serial + * driver and APB DMA based serial driver for higher baudrate + * and performace. To enable the 8250 based driver, the compatible + * is "nvidia,tegra114-uart", "nvidia,tegra20-uart" and to enable + * the APB DMA based serial driver, the comptible is + * "nvidia,tegra114-hsuart", "nvidia,tegra30-hsuart". + */ + uarta: serial@70006000 { compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; reg = <0x70006000 0x40>; reg-shift = <2>; interrupts = <0 36 0x04>; + nvidia,dma-request-selector = <&apbdma 8>; status = "disabled"; clocks = <&tegra_car 6>; }; - serial@70006040 { + uartb: serial@70006040 { compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; reg = <0x70006040 0x40>; reg-shift = <2>; interrupts = <0 37 0x04>; + nvidia,dma-request-selector = <&apbdma 9>; status = "disabled"; clocks = <&tegra_car 192>; }; - serial@70006200 { + uartc: serial@70006200 { compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; reg = <0x70006200 0x100>; reg-shift = <2>; interrupts = <0 46 0x04>; + nvidia,dma-request-selector = <&apbdma 10>; status = "disabled"; clocks = <&tegra_car 55>; }; - serial@70006300 { + uartd: serial@70006300 { compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart"; reg = <0x70006300 0x100>; reg-shift = <2>; interrupts = <0 90 0x04>; + nvidia,dma-request-selector = <&apbdma 19>; status = "disabled"; clocks = <&tegra_car 65>; }; + pwm: pwm { + compatible = "nvidia,tegra114-pwm", "nvidia,tegra20-pwm"; + reg = <0x7000a000 0x100>; + #pwm-cells = <2>; + clocks = <&tegra_car 17>; + status = "disabled"; + }; + + i2c@7000c000 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c000 0x100>; + interrupts = <0 38 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 12>; + clock-names = "div-clk"; + status = "disabled"; + }; + + i2c@7000c400 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c400 0x100>; + interrupts = <0 84 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 54>; + clock-names = "div-clk"; + status = "disabled"; + }; + + i2c@7000c500 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c500 0x100>; + interrupts = <0 92 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 67>; + clock-names = "div-clk"; + status = "disabled"; + }; + + i2c@7000c700 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c700 0x100>; + interrupts = <0 120 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 103>; + clock-names = "div-clk"; + status = "disabled"; + }; + + i2c@7000d000 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000d000 0x100>; + interrupts = <0 53 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 47>; + clock-names = "div-clk"; + status = "disabled"; + }; + + spi@7000d400 { + compatible = "nvidia,tegra114-spi"; + reg = <0x7000d400 0x200>; + interrupts = <0 59 0x04>; + nvidia,dma-request-selector = <&apbdma 15>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 41>; + clock-names = "spi"; + status = "disabled"; + }; + + spi@7000d600 { + compatible = "nvidia,tegra114-spi"; + reg = <0x7000d600 0x200>; + interrupts = <0 82 0x04>; + nvidia,dma-request-selector = <&apbdma 16>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 44>; + clock-names = "spi"; + status = "disabled"; + }; + + spi@7000d800 { + compatible = "nvidia,tegra114-spi"; + reg = <0x7000d800 0x200>; + interrupts = <0 83 0x04>; + nvidia,dma-request-selector = <&apbdma 17>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 46>; + clock-names = "spi"; + status = "disabled"; + }; + + spi@7000da00 { + compatible = "nvidia,tegra114-spi"; + reg = <0x7000da00 0x200>; + interrupts = <0 93 0x04>; + nvidia,dma-request-selector = <&apbdma 18>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 68>; + clock-names = "spi"; + status = "disabled"; + }; + + spi@7000dc00 { + compatible = "nvidia,tegra114-spi"; + reg = <0x7000dc00 0x200>; + interrupts = <0 94 0x04>; + nvidia,dma-request-selector = <&apbdma 27>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 104>; + clock-names = "spi"; + status = "disabled"; + }; + + spi@7000de00 { + compatible = "nvidia,tegra114-spi"; + reg = <0x7000de00 0x200>; + interrupts = <0 79 0x04>; + nvidia,dma-request-selector = <&apbdma 28>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 105>; + clock-names = "spi"; + status = "disabled"; + }; + rtc { compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc"; reg = <0x7000e000 0x100>; @@ -104,6 +296,14 @@ clocks = <&tegra_car 4>; }; + kbc { + compatible = "nvidia,tegra114-kbc"; + reg = <0x7000e200 0x100>; + interrupts = <0 85 0x04>; + clocks = <&tegra_car 36>; + status = "disabled"; + }; + pmc { compatible = "nvidia,tegra114-pmc"; reg = <0x7000e400 0x400>; @@ -122,6 +322,38 @@ nvidia,ahb = <&ahb>; }; + sdhci@78000000 { + compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci"; + reg = <0x78000000 0x200>; + interrupts = <0 14 0x04>; + clocks = <&tegra_car 14>; + status = "disable"; + }; + + sdhci@78000200 { + compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci"; + reg = <0x78000200 0x200>; + interrupts = <0 15 0x04>; + clocks = <&tegra_car 9>; + status = "disable"; + }; + + sdhci@78000400 { + compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci"; + reg = <0x78000400 0x200>; + interrupts = <0 19 0x04>; + clocks = <&tegra_car 69>; + status = "disable"; + }; + + sdhci@78000600 { + compatible = "nvidia,tegra114-sdhci", "nvidia,tegra30-sdhci"; + reg = <0x78000600 0x200>; + interrupts = <0 31 0x04>; + clocks = <&tegra_car 15>; + status = "disable"; + }; + cpus { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi index 4e3afdef28a8..a573b94b7c93 100644 --- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi +++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi @@ -361,6 +361,15 @@ }; }; + pmc { + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <5000>; + nvidia,cpu-pwr-off-time = <5000>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <3875>; + nvidia,sys-clock-req-active-high; + }; + memory-controller@7000f400 { emc-table@83250 { reg = <83250>; @@ -473,6 +482,9 @@ "Mic", "MIC1"; nvidia,ac97-controller = <&ac97>; + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; regulators { diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts index ae9d5a20834e..e7d5de4e00b9 100644 --- a/arch/arm/boot/dts/tegra20-harmony.dts +++ b/arch/arm/boot/dts/tegra20-harmony.dts @@ -416,6 +416,12 @@ pmc { nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <5000>; + nvidia,cpu-pwr-off-time = <5000>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <3875>; + nvidia,sys-clock-req-active-high; }; usb@c5000000 { @@ -464,6 +470,17 @@ }; }; + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio 170 1>; /* gpio PV2, active low */ + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + }; + kbc { status = "okay"; nvidia,debounce-delay-ms = <2>; @@ -669,5 +686,8 @@ nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */ nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */ + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-medcom-wide.dts b/arch/arm/boot/dts/tegra20-medcom-wide.dts index a2d6d6541f83..ace23437da89 100644 --- a/arch/arm/boot/dts/tegra20-medcom-wide.dts +++ b/arch/arm/boot/dts/tegra20-medcom-wide.dts @@ -6,6 +6,10 @@ model = "Avionic Design Medcom-Wide board"; compatible = "ad,medcom-wide", "ad,tamonten", "nvidia,tegra20"; + pwm { + status = "okay"; + }; + i2c@7000c000 { wm8903: wm8903@1a { compatible = "wlf,wm8903"; @@ -54,5 +58,8 @@ nvidia,spkr-en-gpios = <&wm8903 2 0>; nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index fd60940e4063..e3e0c9977df4 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts @@ -415,6 +415,12 @@ pmc { nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <2000>; + nvidia,cpu-pwr-off-time = <0>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <0>; + nvidia,sys-clock-req-active-high; }; usb@c5000000 { @@ -445,6 +451,7 @@ sdhci@c8000600 { status = "okay"; bus-width = <8>; + non-removable; }; clocks { @@ -514,5 +521,8 @@ nvidia,audio-codec = <&alc5632>; nvidia,i2s-controller = <&tegra_i2s1>; nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/tegra20-plutux.dts index 289480026fbf..1a17cc30bb9d 100644 --- a/arch/arm/boot/dts/tegra20-plutux.dts +++ b/arch/arm/boot/dts/tegra20-plutux.dts @@ -52,5 +52,8 @@ nvidia,spkr-en-gpios = <&wm8903 2 0>; nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index 4ee700a33ca5..cee4c34010fe 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -517,6 +517,12 @@ pmc { nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <5000>; + nvidia,cpu-pwr-off-time = <5000>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <3875>; + nvidia,sys-clock-req-active-high; }; memory-controller@7000f400 { @@ -580,6 +586,7 @@ status = "okay"; power-gpios = <&gpio 86 0>; /* gpio PK6 */ bus-width = <4>; + keep-power-in-suspend; }; sdhci@c8000400 { @@ -593,6 +600,7 @@ sdhci@c8000600 { status = "okay"; bus-width = <8>; + non-removable; }; clocks { @@ -821,5 +829,8 @@ nvidia,spkr-en-gpios = <&wm8903 2 0>; nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */ + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi index c19025725918..50b3ec16b93a 100644 --- a/arch/arm/boot/dts/tegra20-tamonten.dtsi +++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi @@ -458,6 +458,12 @@ pmc { nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <5000>; + nvidia,cpu-pwr-off-time = <5000>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <3875>; + nvidia,sys-clock-req-active-high; }; usb@c5008000 { diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/tegra20-tec.dts index 402b21004bef..742f0b38d21d 100644 --- a/arch/arm/boot/dts/tegra20-tec.dts +++ b/arch/arm/boot/dts/tegra20-tec.dts @@ -52,5 +52,8 @@ nvidia,spkr-en-gpios = <&wm8903 2 0>; nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index a9f3f06580f5..9cc78a15d739 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -300,6 +300,15 @@ }; }; + pmc { + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <5000>; + nvidia,cpu-pwr-off-time = <5000>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <3875>; + nvidia,sys-clock-req-active-high; + }; + usb@c5000000 { status = "okay"; nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */ @@ -343,6 +352,17 @@ }; }; + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio 190 1>; /* gpio PX6, active low */ + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + }; + poweroff { compatible = "gpio-poweroff"; gpios = <&gpio 191 1>; /* gpio PX7, active low */ @@ -376,5 +396,8 @@ compatible = "nvidia,tegra-audio-trimslice"; nvidia,i2s-controller = <&tegra_i2s1>; nvidia,audio-codec = <&codec>; + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts index f544806e9618..dd38f1f03834 100644 --- a/arch/arm/boot/dts/tegra20-ventana.dts +++ b/arch/arm/boot/dts/tegra20-ventana.dts @@ -493,6 +493,12 @@ pmc { nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <2000>; + nvidia,cpu-pwr-off-time = <100>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <458>; + nvidia,sys-clock-req-active-high; }; usb@c5000000 { @@ -516,6 +522,7 @@ status = "okay"; power-gpios = <&gpio 86 0>; /* gpio PK6 */ bus-width = <4>; + keep-power-in-suspend; }; sdhci@c8000400 { @@ -529,6 +536,7 @@ sdhci@c8000600 { status = "okay"; bus-width = <8>; + non-removable; }; clocks { @@ -544,6 +552,17 @@ }; }; + gpio-keys { + compatible = "gpio-keys"; + + power { + label = "Power"; + gpios = <&gpio 170 1>; /* gpio PV2, active low */ + linux,code = <116>; /* KEY_POWER */ + gpio-key,wakeup; + }; + }; + regulators { compatible = "simple-bus"; #address-cells = <1>; @@ -620,5 +639,8 @@ nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ nvidia,int-mic-en-gpios = <&gpio 184 0>; /* gpio PX0 */ nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */ + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts index 258cf945f515..d2567f83aaff 100644 --- a/arch/arm/boot/dts/tegra20-whistler.dts +++ b/arch/arm/boot/dts/tegra20-whistler.dts @@ -496,6 +496,14 @@ pmc { nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <2000>; + nvidia,cpu-pwr-off-time = <1000>; + nvidia,core-pwr-good-time = <0 3845>; + nvidia,core-pwr-off-time = <93727>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; + nvidia,combined-power-req; }; usb@c5000000 { @@ -518,6 +526,7 @@ sdhci@c8000600 { status = "okay"; bus-width = <8>; + non-removable; }; clocks { @@ -539,6 +548,7 @@ nvidia,repeat-delay-ms = <160>; nvidia,kbc-row-pins = <0 1 2>; nvidia,kbc-col-pins = <16 17>; + nvidia,wakeup-source; linux,keymap = <0x00000074 /* KEY_POWER */ 0x01000066 /* KEY_HOME */ 0x0101009E /* KEY_BACK */ @@ -573,5 +583,8 @@ nvidia,i2s-controller = <&tegra_i2s1>; nvidia,audio-codec = <&codec>; + + clocks = <&tegra_car 112>, <&tegra_car 113>, <&tegra_car 94>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index fc7febc2b386..56a91106041b 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -209,7 +209,7 @@ compatible = "nvidia,tegra20-das"; reg = <0x70000c00 0x80>; }; - + tegra_ac97: ac97 { compatible = "nvidia,tegra20-ac97"; reg = <0x70002000 0x200>; @@ -299,6 +299,7 @@ reg = <0x7000a000 0x100>; #pwm-cells = <2>; clocks = <&tegra_car 17>; + status = "disabled"; }; rtc { @@ -442,31 +443,6 @@ #size-cells = <0>; }; - phy1: usb-phy@c5000400 { - compatible = "nvidia,tegra20-usb-phy"; - reg = <0xc5000400 0x3c00>; - phy_type = "utmi"; - nvidia,has-legacy-mode; - clocks = <&tegra_car 22>, <&tegra_car 127>; - clock-names = "phy", "pll_u"; - }; - - phy2: usb-phy@c5004400 { - compatible = "nvidia,tegra20-usb-phy"; - reg = <0xc5004400 0x3c00>; - phy_type = "ulpi"; - clocks = <&tegra_car 94>, <&tegra_car 127>; - clock-names = "phy", "pll_u"; - }; - - phy3: usb-phy@c5008400 { - compatible = "nvidia,tegra20-usb-phy"; - reg = <0xc5008400 0x3C00>; - phy_type = "utmi"; - clocks = <&tegra_car 22>, <&tegra_car 127>; - clock-names = "phy", "pll_u"; - }; - usb@c5000000 { compatible = "nvidia,tegra20-ehci", "usb-ehci"; reg = <0xc5000000 0x4000>; @@ -479,6 +455,15 @@ status = "disabled"; }; + phy1: usb-phy@c5000400 { + compatible = "nvidia,tegra20-usb-phy"; + reg = <0xc5000400 0x3c00>; + phy_type = "utmi"; + nvidia,has-legacy-mode; + clocks = <&tegra_car 22>, <&tegra_car 127>; + clock-names = "phy", "pll_u"; + }; + usb@c5004000 { compatible = "nvidia,tegra20-ehci", "usb-ehci"; reg = <0xc5004000 0x4000>; @@ -489,6 +474,14 @@ status = "disabled"; }; + phy2: usb-phy@c5004400 { + compatible = "nvidia,tegra20-usb-phy"; + reg = <0xc5004400 0x3c00>; + phy_type = "ulpi"; + clocks = <&tegra_car 93>, <&tegra_car 127>; + clock-names = "phy", "pll_u"; + }; + usb@c5008000 { compatible = "nvidia,tegra20-ehci", "usb-ehci"; reg = <0xc5008000 0x4000>; @@ -499,6 +492,14 @@ status = "disabled"; }; + phy3: usb-phy@c5008400 { + compatible = "nvidia,tegra20-usb-phy"; + reg = <0xc5008400 0x3c00>; + phy_type = "utmi"; + clocks = <&tegra_car 22>, <&tegra_car 127>; + clock-names = "phy", "pll_u"; + }; + sdhci@c8000000 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000000 0x200>; diff --git a/arch/arm/boot/dts/tegra30-beaver.dts b/arch/arm/boot/dts/tegra30-beaver.dts index 6248b2445b32..b732f7c13a66 100644 --- a/arch/arm/boot/dts/tegra30-beaver.dts +++ b/arch/arm/boot/dts/tegra30-beaver.dts @@ -253,6 +253,13 @@ pmc { status = "okay"; nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <2000>; + nvidia,cpu-pwr-off-time = <200>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <0>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; }; sdhci@78000000 { @@ -266,6 +273,7 @@ sdhci@78000600 { status = "okay"; bus-width = <8>; + non-removable; }; clocks { diff --git a/arch/arm/boot/dts/tegra30-cardhu-a02.dts b/arch/arm/boot/dts/tegra30-cardhu-a02.dts index adc88aa50eb6..e392bd2dab9b 100644 --- a/arch/arm/boot/dts/tegra30-cardhu-a02.dts +++ b/arch/arm/boot/dts/tegra30-cardhu-a02.dts @@ -88,6 +88,7 @@ status = "okay"; power-gpios = <&gpio 28 0>; /* gpio PD4 */ bus-width = <4>; + keep-power-in-suspend; }; }; diff --git a/arch/arm/boot/dts/tegra30-cardhu-a04.dts b/arch/arm/boot/dts/tegra30-cardhu-a04.dts index 08163e145d57..d0db6c7e774f 100644 --- a/arch/arm/boot/dts/tegra30-cardhu-a04.dts +++ b/arch/arm/boot/dts/tegra30-cardhu-a04.dts @@ -100,5 +100,6 @@ status = "okay"; power-gpios = <&gpio 27 0>; /* gpio PD3 */ bus-width = <4>; + keep-power-in-suspend; }; }; diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index 65bf2b63174e..01b4c26fad96 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -307,6 +307,13 @@ pmc { status = "okay"; nvidia,invert-interrupt; + nvidia,suspend-mode = <2>; + nvidia,cpu-pwr-good-time = <2000>; + nvidia,cpu-pwr-off-time = <200>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <0>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; }; sdhci@78000000 { @@ -320,6 +327,7 @@ sdhci@78000600 { status = "okay"; bus-width = <8>; + non-removable; }; clocks { @@ -509,5 +517,8 @@ nvidia,spkr-en-gpios = <&wm8903 2 0>; nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */ + + clocks = <&tegra_car 184>, <&tegra_car 185>, <&tegra_car 120>; + clock-names = "pll_a", "pll_a_out0", "mclk"; }; }; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index 9fe7a92b4c85..15ded605142a 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -286,6 +286,7 @@ reg = <0x7000a000 0x100>; #pwm-cells = <2>; clocks = <&tegra_car 17>; + status = "disabled"; }; rtc { diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi index ed0bc9546837..b3034da00a37 100644 --- a/arch/arm/boot/dts/twl4030.dtsi +++ b/arch/arm/boot/dts/twl4030.dtsi @@ -23,6 +23,12 @@ compatible = "ti,twl4030-wdt"; }; + vcc: regulator-vdd1 { + compatible = "ti,twl4030-vdd1"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1450000>; + }; + vdac: regulator-vdac { compatible = "ti,twl4030-vdac"; regulator-min-microvolt = <1800000>; @@ -67,7 +73,7 @@ #interrupt-cells = <1>; }; - twl4030-usb { + usb2_phy: twl4030-usb { compatible = "ti,twl4030-usb"; interrupts = <10>, <4>; usb1v5-supply = <&vusb1v5>; @@ -75,4 +81,14 @@ usb3v1-supply = <&vusb3v1>; usb_mode = <1>; }; + + twl_pwm: pwm { + compatible = "ti,twl4030-pwm"; + #pwm-cells = <2>; + }; + + twl_pwmled: pwmled { + compatible = "ti,twl4030-pwmled"; + #pwm-cells = <2>; + }; }; diff --git a/arch/arm/boot/dts/twl6030.dtsi b/arch/arm/boot/dts/twl6030.dtsi index 9996cfc5ee80..2e3bd3172b23 100644 --- a/arch/arm/boot/dts/twl6030.dtsi +++ b/arch/arm/boot/dts/twl6030.dtsi @@ -91,4 +91,16 @@ compatible = "ti,twl6030-usb"; interrupts = <4>, <10>; }; + + twl_pwm: pwm { + /* provides two PWMs (id 0, 1 for PWM1 and PWM2) */ + compatible = "ti,twl6030-pwm"; + #pwm-cells = <2>; + }; + + twl_pwmled: pwmled { + /* provides one PWM (id 0 for Charging indicator LED) */ + compatible = "ti,twl6030-pwmled"; + #pwm-cells = <2>; + }; }; diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts index e2fe3195c0d1..dde75ae8b4b1 100644 --- a/arch/arm/boot/dts/versatile-ab.dts +++ b/arch/arm/boot/dts/versatile-ab.dts @@ -121,6 +121,18 @@ interrupts = <0>; }; + timer@101e2000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x101e2000 0x1000>; + interrupts = <4>; + }; + + timer@101e3000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x101e3000 0x1000>; + interrupts = <5>; + }; + gpio0: gpio@101e4000 { compatible = "arm,pl061", "arm,primecell"; reg = <0x101e4000 0x1000>; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts index 1420bb14d95c..62d9b225dcce 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts @@ -98,6 +98,7 @@ <0 49 4>; clocks = <&oscclk2>, <&oscclk2>; clock-names = "timclk", "apb_pclk"; + status = "disabled"; }; watchdog@100e5000 { diff --git a/arch/arm/boot/dts/xenvm-4.2.dts b/arch/arm/boot/dts/xenvm-4.2.dts index ec3f9528e180..336915151398 100644 --- a/arch/arm/boot/dts/xenvm-4.2.dts +++ b/arch/arm/boot/dts/xenvm-4.2.dts @@ -29,6 +29,19 @@ compatible = "arm,cortex-a15"; reg = <0>; }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <1>; + }; + }; + + psci { + compatible = "arm,psci"; + method = "hvc"; + cpu_off = <1>; + cpu_on = <2>; }; memory@80000000 { diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi index 748fc347ed18..14fb2e609bab 100644 --- a/arch/arm/boot/dts/zynq-7000.dtsi +++ b/arch/arm/boot/dts/zynq-7000.dtsi @@ -136,5 +136,12 @@ clock-names = "cpu_1x"; clock-ranges; }; + scutimer: scutimer@f8f00600 { + interrupt-parent = <&intc>; + interrupts = < 1 13 0x301 >; + compatible = "arm,cortex-a9-twd-timer"; + reg = < 0xf8f00600 0x20 >; + clocks = <&cpu_clk 1>; + } ; }; }; diff --git a/arch/arm/common/mcpm_platsmp.c b/arch/arm/common/mcpm_platsmp.c index 52b88d81b7bb..3caed0db6986 100644 --- a/arch/arm/common/mcpm_platsmp.c +++ b/arch/arm/common/mcpm_platsmp.c @@ -15,8 +15,6 @@ #include <linux/smp.h> #include <linux/spinlock.h> -#include <linux/irqchip/arm-gic.h> - #include <asm/mcpm.h> #include <asm/smp.h> #include <asm/smp_plat.h> @@ -49,7 +47,6 @@ static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *i static void __cpuinit mcpm_secondary_init(unsigned int cpu) { mcpm_cpu_powered_up(); - gic_secondary_init(0); } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 9d2d3ba339ff..ddc740769601 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -25,33 +25,29 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/sched_clock.h> #include <asm/hardware/arm_timer.h> +#include <asm/hardware/timer-sp.h> -static long __init sp804_get_clock_rate(const char *name) +static long __init sp804_get_clock_rate(struct clk *clk) { - struct clk *clk; long rate; int err; - clk = clk_get_sys("sp804", name); - if (IS_ERR(clk)) { - pr_err("sp804: %s clock not found: %d\n", name, - (int)PTR_ERR(clk)); - return PTR_ERR(clk); - } - err = clk_prepare(clk); if (err) { - pr_err("sp804: %s clock failed to prepare: %d\n", name, err); + pr_err("sp804: clock failed to prepare: %d\n", err); clk_put(clk); return err; } err = clk_enable(clk); if (err) { - pr_err("sp804: %s clock failed to enable: %d\n", name, err); + pr_err("sp804: clock failed to enable: %d\n", err); clk_unprepare(clk); clk_put(clk); return err; @@ -59,7 +55,7 @@ static long __init sp804_get_clock_rate(const char *name) rate = clk_get_rate(clk); if (rate < 0) { - pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate); + pr_err("sp804: clock failed to get rate: %ld\n", rate); clk_disable(clk); clk_unprepare(clk); clk_put(clk); @@ -77,9 +73,21 @@ static u32 sp804_read(void) void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base, const char *name, + struct clk *clk, int use_sched_clock) { - long rate = sp804_get_clock_rate(name); + long rate; + + if (!clk) { + clk = clk_get_sys("sp804", name); + if (IS_ERR(clk)) { + pr_err("sp804: clock not found: %d\n", + (int)PTR_ERR(clk)); + return; + } + } + + rate = sp804_get_clock_rate(clk); if (rate < 0) return; @@ -171,12 +179,20 @@ static struct irqaction sp804_timer_irq = { .dev_id = &sp804_clockevent, }; -void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, - const char *name) +void __init __sp804_clockevents_init(void __iomem *base, unsigned int irq, struct clk *clk, const char *name) { struct clock_event_device *evt = &sp804_clockevent; - long rate = sp804_get_clock_rate(name); + long rate; + if (!clk) + clk = clk_get_sys("sp804", name); + if (IS_ERR(clk)) { + pr_err("sp804: %s clock not found: %d\n", name, + (int)PTR_ERR(clk)); + return; + } + + rate = sp804_get_clock_rate(clk); if (rate < 0) return; @@ -186,6 +202,98 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, evt->irq = irq; evt->cpumask = cpu_possible_mask; + writel(0, base + TIMER_CTRL); + setup_irq(irq, &sp804_timer_irq); clockevents_config_and_register(evt, rate, 0xf, 0xffffffff); } + +static void __init sp804_of_init(struct device_node *np) +{ + static bool initialized = false; + void __iomem *base; + int irq; + u32 irq_num = 0; + struct clk *clk1, *clk2; + const char *name = of_get_property(np, "compatible", NULL); + + base = of_iomap(np, 0); + if (WARN_ON(!base)) + return; + + /* Ensure timers are disabled */ + writel(0, base + TIMER_CTRL); + writel(0, base + TIMER_2_BASE + TIMER_CTRL); + + if (initialized || !of_device_is_available(np)) + goto err; + + clk1 = of_clk_get(np, 0); + if (IS_ERR(clk1)) + clk1 = NULL; + + /* Get the 2nd clock if the timer has 2 timer clocks */ + if (of_count_phandle_with_args(np, "clocks", "#clock-cells") == 3) { + clk2 = of_clk_get(np, 1); + if (IS_ERR(clk2)) { + pr_err("sp804: %s clock not found: %d\n", np->name, + (int)PTR_ERR(clk2)); + goto err; + } + } else + clk2 = clk1; + + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) + goto err; + + of_property_read_u32(np, "arm,sp804-has-irq", &irq_num); + if (irq_num == 2) { + __sp804_clockevents_init(base + TIMER_2_BASE, irq, clk2, name); + __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1); + } else { + __sp804_clockevents_init(base, irq, clk1 , name); + __sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, + name, clk2, 1); + } + initialized = true; + + return; +err: + iounmap(base); +} +CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init); + +static void __init integrator_cp_of_init(struct device_node *np) +{ + static int init_count = 0; + void __iomem *base; + int irq; + const char *name = of_get_property(np, "compatible", NULL); + + base = of_iomap(np, 0); + if (WARN_ON(!base)) + return; + + /* Ensure timer is disabled */ + writel(0, base + TIMER_CTRL); + + if (init_count == 2 || !of_device_is_available(np)) + goto err; + + if (!init_count) + sp804_clocksource_init(base, name); + else { + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) + goto err; + + sp804_clockevents_init(base, irq, name); + } + + init_count++; + return; +err: + iounmap(base); +} +CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init); diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig new file mode 100644 index 000000000000..6524cdf3b08d --- /dev/null +++ b/arch/arm/configs/bockw_defconfig @@ -0,0 +1,94 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_KERNEL_LZMA=y +CONFIG_NO_HZ=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_R8A7778=y +CONFIG_MACH_BOCKW=y +CONFIG_MEMORY_START=0x60000000 +CONFIG_MEMORY_SIZE=0x10000000 +CONFIG_SHMOBILE_TIMER_HZ=1024 +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_EM_TIMER_STI is not set +CONFIG_ARM_ERRATA_430973=y +CONFIG_ARM_ERRATA_458693=y +CONFIG_ARM_ERRATA_460075=y +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_HIGHMEM=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ARM_APPENDED_DTB=y +CONFIG_CMDLINE="console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp" +CONFIG_CMDLINE_FORCE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_FW_LOADER is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=6 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_UIO=y +CONFIG_UIO_PDRV_GENIRQ=y +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +CONFIG_NFS_V4_1=y +CONFIG_ROOT_NFS=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_FTRACE is not set +# CONFIG_ARM_UNWIND is not set +CONFIG_AVERAGE=y diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index 02c657af4005..f07a847b00c9 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -109,6 +109,7 @@ CONFIG_I2C_IMX=y CONFIG_SPI=y CONFIG_SPI_IMX=y CONFIG_SPI_SPIDEV=y +CONFIG_GPIO_SYSFS=y CONFIG_W1=y CONFIG_W1_MASTER_MXC=y CONFIG_W1_SLAVE_THERM=y diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 088d6c11a0fa..6ec010f248b5 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -9,6 +9,7 @@ CONFIG_CGROUPS=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set CONFIG_MODULES=y diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 33903ca0d879..c1ef64bc5abd 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -137,6 +137,8 @@ CONFIG_SERIAL_8250_DETECT_IRQ=y CONFIG_SERIAL_8250_RSA=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y CONFIG_HW_RANDOM=y CONFIG_I2C_CHARDEV=y CONFIG_SPI=y @@ -153,6 +155,7 @@ CONFIG_OMAP_WATCHDOG=y CONFIG_TWL4030_WATCHDOG=y CONFIG_MFD_TPS65217=y CONFIG_MFD_TPS65910=y +CONFIG_TWL6040_CORE=y CONFIG_REGULATOR_TWL4030=y CONFIG_REGULATOR_TPS65023=y CONFIG_REGULATOR_TPS6507X=y @@ -195,6 +198,7 @@ CONFIG_SND_USB_AUDIO=m CONFIG_SND_SOC=m CONFIG_SND_OMAP_SOC=m CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m +CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m CONFIG_USB=y CONFIG_USB_DEBUG=y diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 7ade91d8cc6f..7c1bfc0aea0c 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -10,8 +10,7 @@ #include <clocksource/arm_arch_timer.h> #ifdef CONFIG_ARM_ARCH_TIMER -int arch_timer_of_register(void); -int arch_timer_sched_clock_init(void); +int arch_timer_arch_init(void); /* * These register accessors are marked inline so the compiler can @@ -110,16 +109,6 @@ static inline void __cpuinit arch_counter_set_user_access(void) asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl)); } -#else -static inline int arch_timer_of_register(void) -{ - return -ENXIO; -} - -static inline int arch_timer_sched_clock_init(void) -{ - return -ENXIO; -} #endif #endif diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h index 7eb18c1d8d6c..4f009c10540d 100644 --- a/arch/arm/include/asm/cmpxchg.h +++ b/arch/arm/include/asm/cmpxchg.h @@ -233,15 +233,15 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, ((__typeof__(*(ptr)))atomic64_cmpxchg(container_of((ptr), \ atomic64_t, \ counter), \ - (unsigned long)(o), \ - (unsigned long)(n))) + (unsigned long long)(o), \ + (unsigned long long)(n))) #define cmpxchg64_local(ptr, o, n) \ ((__typeof__(*(ptr)))local64_cmpxchg(container_of((ptr), \ local64_t, \ a), \ - (unsigned long)(o), \ - (unsigned long)(n))) + (unsigned long long)(o), \ + (unsigned long long)(n))) #endif /* __LINUX_ARM_ARCH__ >= 6 */ diff --git a/arch/arm/include/asm/hardware/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h index 2dd9d3f83f29..bb28af7c32de 100644 --- a/arch/arm/include/asm/hardware/timer-sp.h +++ b/arch/arm/include/asm/hardware/timer-sp.h @@ -1,15 +1,23 @@ +struct clk; + void __sp804_clocksource_and_sched_clock_init(void __iomem *, - const char *, int); + const char *, struct clk *, int); +void __sp804_clockevents_init(void __iomem *, unsigned int, + struct clk *, const char *); static inline void sp804_clocksource_init(void __iomem *base, const char *name) { - __sp804_clocksource_and_sched_clock_init(base, name, 0); + __sp804_clocksource_and_sched_clock_init(base, name, NULL, 0); } static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base, const char *name) { - __sp804_clocksource_and_sched_clock_init(base, name, 1); + __sp804_clocksource_and_sched_clock_init(base, name, NULL, 1); } -void sp804_clockevents_init(void __iomem *, unsigned int, const char *); +static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name) +{ + __sp804_clockevents_init(base, irq, NULL, name); + +} diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index e3f757263438..3d520ddca61b 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h @@ -11,4 +11,6 @@ extern void sched_clock_postinit(void); extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); +extern unsigned long long (*sched_clock_func)(void); + #endif diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h index 8a823253d775..799f42ecca63 100644 --- a/arch/arm/include/asm/xen/hypercall.h +++ b/arch/arm/include/asm/xen/hypercall.h @@ -46,6 +46,7 @@ int HYPERVISOR_event_channel_op(int cmd, void *arg); unsigned long HYPERVISOR_hvm_op(int op, void *arg); int HYPERVISOR_memory_op(unsigned int cmd, void *arg); int HYPERVISOR_physdev_op(int cmd, void *arg); +int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args); static inline void MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va, diff --git a/arch/arm/include/debug/mvebu.S b/arch/arm/include/debug/mvebu.S index 865c6d02b332..df191afa3be1 100644 --- a/arch/arm/include/debug/mvebu.S +++ b/arch/arm/include/debug/mvebu.S @@ -12,7 +12,7 @@ */ #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 -#define ARMADA_370_XP_REGS_VIRT_BASE 0xfeb00000 +#define ARMADA_370_XP_REGS_VIRT_BASE 0xfec00000 .macro addruart, rp, rv, tmp ldr \rp, =ARMADA_370_XP_REGS_PHYS_BASE diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index d957a51435d8..59dcdced6e30 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -22,9 +22,11 @@ static unsigned long arch_timer_read_counter_long(void) return arch_timer_read_counter(); } -static u32 arch_timer_read_counter_u32(void) +static u32 sched_clock_mult __read_mostly; + +static unsigned long long notrace arch_timer_sched_clock(void) { - return arch_timer_read_counter(); + return arch_timer_read_counter() * sched_clock_mult; } static struct delay_timer arch_delay_timer; @@ -37,25 +39,20 @@ static void __init arch_timer_delay_timer_register(void) register_current_timer_delay(&arch_delay_timer); } -int __init arch_timer_of_register(void) +int __init arch_timer_arch_init(void) { - int ret; + u32 arch_timer_rate = arch_timer_get_rate(); - ret = arch_timer_init(); - if (ret) - return ret; + if (arch_timer_rate == 0) + return -ENXIO; arch_timer_delay_timer_register(); - return 0; -} - -int __init arch_timer_sched_clock_init(void) -{ - if (arch_timer_get_rate() == 0) - return -ENXIO; + /* Cache the sched_clock multiplier to save a divide in the hot path. */ + sched_clock_mult = NSEC_PER_SEC / arch_timer_rate; + sched_clock_func = arch_timer_sched_clock; + pr_info("sched_clock: ARM arch timer >56 bits at %ukHz, resolution %uns\n", + arch_timer_rate / 1000, sched_clock_mult); - setup_sched_clock(arch_timer_read_counter_u32, - 32, arch_timer_get_rate()); return 0; } diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 70f1bdeb241b..5af04f6daa33 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -180,6 +180,13 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) unsigned long dt_root; const char *model; +#ifdef CONFIG_ARCH_MULTIPLATFORM + DT_MACHINE_START(GENERIC_DT, "Generic DT based system") + MACHINE_END + + mdesc_best = (struct machine_desc *)&__mach_desc_GENERIC_DT; +#endif + if (!dt_phys) return NULL; diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index 59d2adb764a9..e8edcaa0e432 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c @@ -20,6 +20,7 @@ struct clock_data { u64 epoch_ns; u32 epoch_cyc; u32 epoch_cyc_copy; + unsigned long rate; u32 mult; u32 shift; bool suspended; @@ -113,11 +114,14 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) u64 res, wrap; char r_unit; + if (cd.rate > rate) + return; + BUG_ON(bits > 32); WARN_ON(!irqs_disabled()); - WARN_ON(read_sched_clock != jiffy_sched_clock_read); read_sched_clock = read; sched_clock_mask = (1 << bits) - 1; + cd.rate = rate; /* calculate the mult/shift to convert counter ticks to ns. */ clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); @@ -161,12 +165,19 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) pr_debug("Registered %pF as sched_clock source\n", read); } -unsigned long long notrace sched_clock(void) +static unsigned long long notrace sched_clock_32(void) { u32 cyc = read_sched_clock(); return cyc_to_sched_clock(cyc, sched_clock_mask); } +unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32; + +unsigned long long notrace sched_clock(void) +{ + return sched_clock_func(); +} + void __init sched_clock_postinit(void) { /* diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 728007c4a2b7..1522c7ae31b0 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -18,6 +18,7 @@ #include <linux/bootmem.h> #include <linux/seq_file.h> #include <linux/screen_info.h> +#include <linux/of_platform.h> #include <linux/init.h> #include <linux/kexec.h> #include <linux/of_fdt.h> @@ -659,9 +660,19 @@ struct screen_info screen_info = { static int __init customize_machine(void) { - /* customizes platform devices, or adds new ones */ + /* + * customizes platform devices, or adds new ones + * On DT based machines, we fall back to populating the + * machine from the device tree, if no callback is provided, + * otherwise we would always need an init_machine callback. + */ if (machine_desc->init_machine) machine_desc->init_machine(); +#ifdef CONFIG_OF + else + of_platform_populate(NULL, of_default_bus_match_table, + NULL, NULL); +#endif return 0; } arch_initcall(customize_machine); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 47ab90563bf4..550d63cef68e 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -251,7 +251,7 @@ void __ref cpu_die(void) * this returns, power and/or clocks can be removed at any point * from this CPU and its cache by platform_cpu_kill(). */ - RCU_NONIDLE(complete(&cpu_died)); + complete(&cpu_died); /* * Ensure that the cache lines associated with that completion are diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 955d92d265e5..abff4e9aaee0 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -22,6 +22,7 @@ #include <linux/errno.h> #include <linux/profile.h> #include <linux/timer.h> +#include <linux/clocksource.h> #include <linux/irq.h> #include <asm/thread_info.h> @@ -115,6 +116,10 @@ int __init register_persistent_clock(clock_access_fn read_boot, void __init time_init(void) { - machine_desc->init_time(); + if (machine_desc->init_time) + machine_desc->init_time(); + else + clocksource_of_init(); + sched_clock_postinit(); } diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 48f1228c611c..69f9e3bbf4e5 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -36,6 +36,8 @@ static int at91_enter_idle(struct cpuidle_device *dev, at91rm9200_standby(); else if (cpu_is_at91sam9g45()) at91sam9g45_standby(); + else if (cpu_is_at91sam9263()) + at91sam9263_standby(); else at91sam9_standby(); diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index 0f3379fe645f..d3d7b993846b 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -86,7 +86,7 @@ enum at91_soc_type { AT91_SOC_SAMA5D3, /* Unknown type */ - AT91_SOC_NONE + AT91_SOC_UNKNOWN, }; enum at91_soc_subtype { @@ -107,8 +107,11 @@ enum at91_soc_subtype { AT91_SOC_SAMA5D31, AT91_SOC_SAMA5D33, AT91_SOC_SAMA5D34, AT91_SOC_SAMA5D35, + /* No subtype for this SoC */ + AT91_SOC_SUBTYPE_NONE, + /* Unknown subtype */ - AT91_SOC_SUBTYPE_NONE + AT91_SOC_SUBTYPE_UNKNOWN, }; struct at91_socinfo { @@ -122,7 +125,7 @@ const char *at91_get_soc_subtype(struct at91_socinfo *c); static inline int at91_soc_is_detected(void) { - return at91_soc_initdata.type != AT91_SOC_NONE; + return at91_soc_initdata.type != AT91_SOC_UNKNOWN; } #ifdef CONFIG_SOC_AT91RM9200 diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 73f1f250403a..530db304ec5e 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -270,6 +270,8 @@ static int at91_pm_enter(suspend_state_t state) at91rm9200_standby(); else if (cpu_is_at91sam9g45()) at91sam9g45_standby(); + else if (cpu_is_at91sam9263()) + at91sam9263_standby(); else at91sam9_standby(); break; diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h index 38f467c6b710..2f5908f0b8c5 100644 --- a/arch/arm/mach-at91/pm.h +++ b/arch/arm/mach-at91/pm.h @@ -70,13 +70,31 @@ static inline void at91sam9g45_standby(void) at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); } -#ifdef CONFIG_SOC_AT91SAM9263 -/* - * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use; - * handle those cases both here and in the Suspend-To-RAM support. +/* We manage both DDRAM/SDRAM controllers, we need more than one value to + * remember. */ -#warning Assuming EB1 SDRAM controller is *NOT* used -#endif +static inline void at91sam9263_standby(void) +{ + u32 lpr0, lpr1; + u32 saved_lpr0, saved_lpr1; + + saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR); + lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB; + lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH; + + saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR); + lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB; + lpr0 |= AT91_SDRAMC_LPCB_SELF_REFRESH; + + /* self-refresh mode now */ + at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0); + at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1); + + cpu_do_idle(); + + at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0); + at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); +} static inline void at91sam9_standby(void) { diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index e8491e77b1f7..e2f4bdd146d6 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -105,28 +105,32 @@ static void __init soc_detect(u32 dbgu_base) switch (socid) { case ARCH_ID_AT91RM9200: at91_soc_initdata.type = AT91_SOC_RM9200; - if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE) + if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_UNKNOWN) at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; at91_boot_soc = at91rm9200_soc; break; case ARCH_ID_AT91SAM9260: at91_soc_initdata.type = AT91_SOC_SAM9260; + at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; at91_boot_soc = at91sam9260_soc; break; case ARCH_ID_AT91SAM9261: at91_soc_initdata.type = AT91_SOC_SAM9261; + at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; at91_boot_soc = at91sam9261_soc; break; case ARCH_ID_AT91SAM9263: at91_soc_initdata.type = AT91_SOC_SAM9263; + at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; at91_boot_soc = at91sam9263_soc; break; case ARCH_ID_AT91SAM9G20: at91_soc_initdata.type = AT91_SOC_SAM9G20; + at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; at91_boot_soc = at91sam9260_soc; break; @@ -139,6 +143,7 @@ static void __init soc_detect(u32 dbgu_base) case ARCH_ID_AT91SAM9RL64: at91_soc_initdata.type = AT91_SOC_SAM9RL; + at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; at91_boot_soc = at91sam9rl_soc; break; @@ -161,6 +166,7 @@ static void __init soc_detect(u32 dbgu_base) /* at91sam9g10 */ if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { at91_soc_initdata.type = AT91_SOC_SAM9G10; + at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; at91_boot_soc = at91sam9261_soc; } /* at91sam9xe */ @@ -242,7 +248,7 @@ static const char *soc_name[] = { [AT91_SOC_SAM9X5] = "at91sam9x5", [AT91_SOC_SAM9N12] = "at91sam9n12", [AT91_SOC_SAMA5D3] = "sama5d3", - [AT91_SOC_NONE] = "Unknown" + [AT91_SOC_UNKNOWN] = "Unknown", }; const char *at91_get_soc_type(struct at91_socinfo *c) @@ -268,7 +274,8 @@ static const char *soc_subtype_name[] = { [AT91_SOC_SAMA5D33] = "sama5d33", [AT91_SOC_SAMA5D34] = "sama5d34", [AT91_SOC_SAMA5D35] = "sama5d35", - [AT91_SOC_SUBTYPE_NONE] = "Unknown" + [AT91_SOC_SUBTYPE_NONE] = "None", + [AT91_SOC_SUBTYPE_UNKNOWN] = "Unknown", }; const char *at91_get_soc_subtype(struct at91_socinfo *c) @@ -282,8 +289,8 @@ void __init at91_map_io(void) /* Map peripherals */ iotable_init(&at91_io_desc, 1); - at91_soc_initdata.type = AT91_SOC_NONE; - at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE; + at91_soc_initdata.type = AT91_SOC_UNKNOWN; + at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_UNKNOWN; soc_detect(AT91_BASE_DBGU0); if (!at91_soc_is_detected()) @@ -294,8 +301,9 @@ void __init at91_map_io(void) pr_info("AT91: Detected soc type: %s\n", at91_get_soc_type(&at91_soc_initdata)); - pr_info("AT91: Detected soc subtype: %s\n", - at91_get_soc_subtype(&at91_soc_initdata)); + if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE) + pr_info("AT91: Detected soc subtype: %s\n", + at91_get_soc_subtype(&at91_soc_initdata)); if (!at91_soc_is_enabled()) panic("AT91: Soc not enabled"); diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c index b1c0a5958275..961aea8bbad5 100644 --- a/arch/arm/mach-davinci/da8xx-dt.c +++ b/arch/arm/mach-davinci/da8xx-dt.c @@ -41,6 +41,12 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL), OF_DEV_AUXDATA("ti,davinci-wdt", 0x01c21000, "watchdog", NULL), OF_DEV_AUXDATA("ti,da830-mmc", 0x01c40000, "da830-mmc.0", NULL), + OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f00000, "ehrpwm", NULL), + OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f02000, "ehrpwm", NULL), + OF_DEV_AUXDATA("ti,da850-ecap", 0x01f06000, "ecap", NULL), + OF_DEV_AUXDATA("ti,da850-ecap", 0x01f07000, "ecap", NULL), + OF_DEV_AUXDATA("ti,da850-ecap", 0x01f08000, "ecap", NULL), + OF_DEV_AUXDATA("ti,da830-spi", 0x01f0e000, "spi_davinci.1", NULL), {} }; diff --git a/arch/arm/mach-dove/Makefile b/arch/arm/mach-dove/Makefile index 3f0a858fb597..4d9d2ffc4535 100644 --- a/arch/arm/mach-dove/Makefile +++ b/arch/arm/mach-dove/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o irq.o +obj-y += common.o irq.o obj-$(CONFIG_DOVE_LEGACY) += mpp.o obj-$(CONFIG_PCI) += pcie.o obj-$(CONFIG_MACH_DOVE_DB) += dove-db-setup.o diff --git a/arch/arm/mach-dove/addr-map.c b/arch/arm/mach-dove/addr-map.c deleted file mode 100644 index 2a06c0163418..000000000000 --- a/arch/arm/mach-dove/addr-map.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * arch/arm/mach-dove/addr-map.c - * - * Address map functions for Marvell Dove 88AP510 SoC - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <asm/mach/arch.h> -#include <asm/setup.h> -#include <mach/dove.h> -#include <plat/addr-map.h> -#include "common.h" - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DDR 0x0 -#define TARGET_BOOTROM 0x1 -#define TARGET_CESA 0x3 -#define TARGET_PCIE0 0x4 -#define TARGET_PCIE1 0x8 -#define TARGET_SCRATCHPAD 0xd - -#define ATTR_CESA 0x01 -#define ATTR_BOOTROM 0xfd -#define ATTR_DEV_SPI0_ROM 0xfe -#define ATTR_DEV_SPI1_ROM 0xfb -#define ATTR_PCIE_IO 0xe0 -#define ATTR_PCIE_MEM 0xe8 -#define ATTR_SCRATCHPAD 0x0 - -static inline void __iomem *ddr_map_sc(int i) -{ - return (void __iomem *)(DOVE_MC_VIRT_BASE + 0x100 + ((i) << 4)); -} - -/* - * Description of the windows needed by the platform code - */ -static struct __initdata orion_addr_map_cfg addr_map_cfg = { - .num_wins = 8, - .remappable_wins = 4, - .bridge_virt_base = BRIDGE_VIRT_BASE, -}; - -static const struct __initdata orion_addr_map_info addr_map_info[] = { - /* - * Windows for PCIe IO+MEM space. - */ - { 0, DOVE_PCIE0_IO_PHYS_BASE, DOVE_PCIE0_IO_SIZE, - TARGET_PCIE0, ATTR_PCIE_IO, DOVE_PCIE0_IO_BUS_BASE - }, - { 1, DOVE_PCIE1_IO_PHYS_BASE, DOVE_PCIE1_IO_SIZE, - TARGET_PCIE1, ATTR_PCIE_IO, DOVE_PCIE1_IO_BUS_BASE - }, - { 2, DOVE_PCIE0_MEM_PHYS_BASE, DOVE_PCIE0_MEM_SIZE, - TARGET_PCIE0, ATTR_PCIE_MEM, -1 - }, - { 3, DOVE_PCIE1_MEM_PHYS_BASE, DOVE_PCIE1_MEM_SIZE, - TARGET_PCIE1, ATTR_PCIE_MEM, -1 - }, - /* - * Window for CESA engine. - */ - { 4, DOVE_CESA_PHYS_BASE, DOVE_CESA_SIZE, - TARGET_CESA, ATTR_CESA, -1 - }, - /* - * Window to the BootROM for Standby and Sleep Resume - */ - { 5, DOVE_BOOTROM_PHYS_BASE, DOVE_BOOTROM_SIZE, - TARGET_BOOTROM, ATTR_BOOTROM, -1 - }, - /* - * Window to the PMU Scratch Pad space - */ - { 6, DOVE_SCRATCHPAD_PHYS_BASE, DOVE_SCRATCHPAD_SIZE, - TARGET_SCRATCHPAD, ATTR_SCRATCHPAD, -1 - }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 } -}; - -void __init dove_setup_cpu_mbus(void) -{ - int i; - int cs; - - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, addr_map_info); - - /* - * Setup MBUS dram target info. - */ - orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; - - for (i = 0, cs = 0; i < 2; i++) { - u32 map = readl(ddr_map_sc(i)); - - /* - * Chip select enabled? - */ - if (map & 1) { - struct mbus_dram_window *w; - - w = &orion_mbus_dram_info.cs[cs++]; - w->cs_index = i; - w->mbus_attr = 0; /* CS address decoding done inside */ - /* the DDR controller, no need to */ - /* provide attributes */ - w->base = map & 0xff800000; - w->size = 0x100000 << (((map & 0x000f0000) >> 16) - 4); - } - } - orion_mbus_dram_info.num_cs = cs; -} diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c index fbde1dd67113..0b142803b2e1 100644 --- a/arch/arm/mach-dove/board-dt.c +++ b/arch/arm/mach-dove/board-dt.c @@ -64,7 +64,7 @@ static void __init dove_dt_init(void) #ifdef CONFIG_CACHE_TAUROS2 tauros2_init(0); #endif - dove_setup_cpu_mbus(); + dove_setup_cpu_wins(); /* Setup root of clk tree */ dove_of_clk_init(); diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index c6b3b2bb50e7..e2b5da031f96 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -224,6 +224,9 @@ void __init dove_i2c_init(void) void __init dove_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); + mvebu_mbus_init("marvell,dove-mbus", + BRIDGE_WINS_BASE, BRIDGE_WINS_SZ, + DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ); } static int __init dove_find_tclk(void) @@ -326,6 +329,40 @@ void __init dove_sdio1_init(void) platform_device_register(&dove_sdio1); } +void __init dove_setup_cpu_wins(void) +{ + /* + * The PCIe windows will no longer be statically allocated + * here once Dove is migrated to the pci-mvebu driver. + */ + mvebu_mbus_add_window_remap_flags("pcie0.0", + DOVE_PCIE0_IO_PHYS_BASE, + DOVE_PCIE0_IO_SIZE, + DOVE_PCIE0_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie1.0", + DOVE_PCIE1_IO_PHYS_BASE, + DOVE_PCIE1_IO_SIZE, + DOVE_PCIE1_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie0.0", + DOVE_PCIE0_MEM_PHYS_BASE, + DOVE_PCIE0_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags("pcie1.0", + DOVE_PCIE1_MEM_PHYS_BASE, + DOVE_PCIE1_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window("cesa", DOVE_CESA_PHYS_BASE, + DOVE_CESA_SIZE); + mvebu_mbus_add_window("bootrom", DOVE_BOOTROM_PHYS_BASE, + DOVE_BOOTROM_SIZE); + mvebu_mbus_add_window("scratchpad", DOVE_SCRATCHPAD_PHYS_BASE, + DOVE_SCRATCHPAD_SIZE); +} + void __init dove_init(void) { pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n", @@ -334,7 +371,7 @@ void __init dove_init(void) #ifdef CONFIG_CACHE_TAUROS2 tauros2_init(0); #endif - dove_setup_cpu_mbus(); + dove_setup_cpu_wins(); /* Setup root of clk tree */ dove_clk_init(); diff --git a/arch/arm/mach-dove/common.h b/arch/arm/mach-dove/common.h index ee59fba4c6d1..e86347928b67 100644 --- a/arch/arm/mach-dove/common.h +++ b/arch/arm/mach-dove/common.h @@ -23,7 +23,7 @@ void dove_map_io(void); void dove_init(void); void dove_init_early(void); void dove_init_irq(void); -void dove_setup_cpu_mbus(void); +void dove_setup_cpu_wins(void); void dove_ge00_init(struct mv643xx_eth_platform_data *eth_data); void dove_sata_init(struct mv_sata_platform_data *sata_data); #ifdef CONFIG_PCI diff --git a/arch/arm/mach-dove/include/mach/dove.h b/arch/arm/mach-dove/include/mach/dove.h index 661725e3115a..0c4b35f4ee5b 100644 --- a/arch/arm/mach-dove/include/mach/dove.h +++ b/arch/arm/mach-dove/include/mach/dove.h @@ -77,6 +77,8 @@ /* North-South Bridge */ #define BRIDGE_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE + 0x20000) #define BRIDGE_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE + 0x20000) +#define BRIDGE_WINS_BASE (BRIDGE_PHYS_BASE) +#define BRIDGE_WINS_SZ (0x80) /* Cryptographic Engine */ #define DOVE_CRYPT_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE + 0x30000) @@ -168,6 +170,9 @@ #define DOVE_SSP_CLOCK_ENABLE (1 << 1) #define DOVE_SSP_BPB_CLOCK_SRC_SSP (1 << 11) /* Memory Controller */ +#define DOVE_MC_PHYS_BASE (DOVE_NB_REGS_PHYS_BASE + 0x00000) +#define DOVE_MC_WINS_BASE (DOVE_MC_PHYS_BASE + 0x100) +#define DOVE_MC_WINS_SZ (0x8) #define DOVE_MC_VIRT_BASE (DOVE_NB_REGS_VIRT_BASE + 0x00000) /* LCD Controller */ diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 46089fe24705..745e304ad0de 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -120,17 +120,6 @@ static struct map_desc exynos_iodesc[] __initdata = { }, }; -#ifdef CONFIG_ARCH_EXYNOS5 -static struct map_desc exynos5440_iodesc[] __initdata = { - { - .virtual = (unsigned long)S5P_VA_CHIPID, - .pfn = __phys_to_pfn(EXYNOS5440_PA_CHIPID), - .length = SZ_4K, - .type = MT_DEVICE, - }, -}; -#endif - static struct map_desc exynos4_iodesc[] __initdata = { { .virtual = (unsigned long)S3C_VA_SYS, @@ -348,6 +337,31 @@ void __init exynos_init_late(void) exynos_pm_late_initcall(); } +#ifdef CONFIG_OF +int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, + int depth, void *data) +{ + struct map_desc iodesc; + __be32 *reg; + unsigned long len; + + if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") && + !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock")) + return 0; + + reg = of_get_flat_dt_prop(node, "reg", &len); + if (reg == NULL || len != (sizeof(unsigned long) * 2)) + return 0; + + iodesc.pfn = __phys_to_pfn(be32_to_cpu(reg[0])); + iodesc.length = be32_to_cpu(reg[1]) - 1; + iodesc.virtual = (unsigned long)S5P_VA_CHIPID; + iodesc.type = MT_DEVICE; + iotable_init(&iodesc, 1); + return 1; +} +#endif + /* * exynos_map_io * @@ -356,19 +370,12 @@ void __init exynos_init_late(void) void __init exynos_init_io(struct map_desc *mach_desc, int size) { - struct map_desc *iodesc = exynos_iodesc; - int iodesc_sz = ARRAY_SIZE(exynos_iodesc); -#if defined(CONFIG_OF) && defined(CONFIG_ARCH_EXYNOS5) - unsigned long root = of_get_flat_dt_root(); - - /* initialize the io descriptors we need for initialization */ - if (of_flat_dt_is_compatible(root, "samsung,exynos5440")) { - iodesc = exynos5440_iodesc; - iodesc_sz = ARRAY_SIZE(exynos5440_iodesc); - } +#ifdef CONFIG_OF + if (initial_boot_params) + of_scan_flat_dt(exynos_fdt_map_chipid, NULL); + else #endif - - iotable_init(iodesc, iodesc_sz); + iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc)); if (mach_desc) iotable_init(mach_desc, size); @@ -445,13 +452,26 @@ void __init exynos_init_time(void) } else { /* todo: remove after migrating legacy E4 platforms to dt */ #ifdef CONFIG_ARCH_EXYNOS4 - exynos4_clk_init(NULL); + exynos4_clk_init(NULL, !soc_is_exynos4210(), S5P_VA_CMU, readl(S5P_VA_CHIPID + 8) & 1); exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f); #endif - mct_init(); + mct_init(S5P_VA_SYSTIMER, EXYNOS4_IRQ_MCT_G0, EXYNOS4_IRQ_MCT_L0, EXYNOS4_IRQ_MCT_L1); } } +static unsigned int max_combiner_nr(void) +{ + if (soc_is_exynos5250()) + 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 + return EXYNOS4210_MAX_COMBINER_NR; +} + + void __init exynos4_init_irq(void) { unsigned int gic_bank_offset; @@ -466,14 +486,8 @@ void __init exynos4_init_irq(void) #endif if (!of_have_populated_dt()) - combiner_init(S5P_VA_COMBINER_BASE, NULL); - - /* - * The parameters of s5p_init_irq() are for VIC init. - * Theses parameters should be NULL and 0 because EXYNOS4 - * uses GIC instead of VIC. - */ - s5p_init_irq(NULL, 0); + combiner_init(S5P_VA_COMBINER_BASE, NULL, + max_combiner_nr(), COMBINER_IRQ(0, 0)); gic_arch_extn.irq_set_wake = s3c_irq_wake; } @@ -483,14 +497,6 @@ void __init exynos5_init_irq(void) #ifdef CONFIG_OF irqchip_init(); #endif - /* - * The parameters of s5p_init_irq() are for VIC init. - * Theses parameters should be NULL and 0 because EXYNOS4 - * uses GIC instead of VIC. - */ - if (!of_machine_is_compatible("samsung,exynos5440")) - s5p_init_irq(NULL, 0); - gic_arch_extn.irq_set_wake = s3c_irq_wake; } diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index b17448c1a164..60dd35cc01a6 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -14,7 +14,7 @@ #include <linux/of.h> -extern void mct_init(void); +void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1); void exynos_init_time(void); extern unsigned long xxti_f, xusbxti_f; @@ -27,7 +27,7 @@ void exynos5_restart(char mode, const char *cmd); void exynos_init_late(void); /* ToDo: remove these after migrating legacy exynos4 platforms to dt */ -void exynos4_clk_init(struct device_node *np); +void exynos4_clk_init(struct device_node *np, int is_exynos4210, void __iomem *reg_base, unsigned long xom); void exynos4_clk_register_fixed_ext(unsigned long, unsigned long); void exynos_firmware_init(void); @@ -71,7 +71,8 @@ void exynos4212_register_clocks(void); #endif struct device_node; -void combiner_init(void __iomem *combiner_base, struct device_node *np); +void combiner_init(void __iomem *combiner_base, struct device_node *np, + unsigned int max_nr, int irq_base); extern struct smp_operations exynos_smp_ops; diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 99e0a79f3b1f..92b29bb583cb 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -56,7 +56,6 @@ #define EXYNOS4_PA_ONENAND_DMA 0x0C600000 #define EXYNOS_PA_CHIPID 0x10000000 -#define EXYNOS5440_PA_CHIPID 0x00160000 #define EXYNOS4_PA_SYSCON 0x10010000 #define EXYNOS5_PA_SYSCON 0x10050100 diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h index 3f30aa1ae354..57344b7e98ce 100644 --- a/arch/arm/mach-exynos/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h @@ -344,6 +344,7 @@ #define EXYNOS5_FSYS_ARM_OPTION S5P_PMUREG(0x2208) #define EXYNOS5_ISP_ARM_OPTION S5P_PMUREG(0x2288) #define EXYNOS5_ARM_COMMON_OPTION S5P_PMUREG(0x2408) +#define EXYNOS5_ARM_L2_OPTION S5P_PMUREG(0x2608) #define EXYNOS5_TOP_PWR_OPTION S5P_PMUREG(0x2C48) #define EXYNOS5_TOP_PWR_SYSMEM_OPTION S5P_PMUREG(0x2CC8) #define EXYNOS5_JPEG_MEM_OPTION S5P_PMUREG(0x2F48) diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c index daebc1abc966..97d688526258 100644 --- a/arch/arm/mach-exynos/pmu.c +++ b/arch/arm/mach-exynos/pmu.c @@ -228,6 +228,7 @@ static struct exynos_pmu_conf exynos5250_pmu_config[] = { { EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, { EXYNOS5_ARM_COMMON_SYS_PWR_REG, { 0x0, 0x0, 0x2} }, { EXYNOS5_ARM_L2_SYS_PWR_REG, { 0x3, 0x3, 0x3} }, + { EXYNOS5_ARM_L2_OPTION, { 0x10, 0x10, 0x0 } }, { EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} }, { EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG, { 0x1, 0x0, 0x1} }, { EXYNOS5_CMU_RESET_SYS_PWR_REG, { 0x1, 0x1, 0x0} }, @@ -353,11 +354,9 @@ static void exynos5_init_pmu(void) /* * SKIP_DEACTIVATE_ACEACP_IN_PWDN_BITFIELD Enable - * MANUAL_L2RSTDISABLE_CONTROL_BITFIELD Enable */ tmp = __raw_readl(EXYNOS5_ARM_COMMON_OPTION); - tmp |= (EXYNOS5_MANUAL_L2RSTDISABLE_CONTROL | - EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN); + tmp |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN; __raw_writel(tmp, EXYNOS5_ARM_COMMON_OPTION); /* diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 76c1170b3528..e7df2dd43a40 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -15,6 +15,7 @@ */ #include <linux/clk.h> #include <linux/clkdev.h> +#include <linux/clocksource.h> #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/irq.h> @@ -28,12 +29,9 @@ #include <linux/amba/bus.h> #include <linux/clk-provider.h> -#include <asm/arch_timer.h> #include <asm/cacheflush.h> #include <asm/cputype.h> #include <asm/smp_plat.h> -#include <asm/hardware/arm_timer.h> -#include <asm/hardware/timer-sp.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -90,36 +88,16 @@ static void __init highbank_init_irq(void) #endif } -static struct clk_lookup lookup = { - .dev_id = "sp804", - .con_id = NULL, -}; - static void __init highbank_timer_init(void) { - int irq; struct device_node *np; - void __iomem *timer_base; /* Map system registers */ np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs"); sregs_base = of_iomap(np, 0); WARN_ON(!sregs_base); - np = of_find_compatible_node(NULL, NULL, "arm,sp804"); - timer_base = of_iomap(np, 0); - WARN_ON(!timer_base); - irq = irq_of_parse_and_map(np, 0); - of_clk_init(NULL); - lookup.clk = of_clk_get(np, 0); - clkdev_add(&lookup); - - sp804_clocksource_and_sched_clock_init(timer_base + 0x20, "timer1"); - sp804_clockevents_init(timer_base, irq, "timer0"); - - arch_timer_of_register(); - arch_timer_sched_clock_init(); clocksource_of_init(); } diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 2ebc97e16b91..ba44328464f3 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -5,6 +5,7 @@ config ARCH_MXC select AUTO_ZRELADDR if !ZBOOT_ROM select CLKDEV_LOOKUP select CLKSRC_MMIO + select GENERIC_ALLOCATOR select GENERIC_CLOCKEVENTS select GENERIC_IRQ_CHIP select MULTI_IRQ_HANDLER @@ -61,9 +62,8 @@ config MXC_ULPI config ARCH_HAS_RNGA bool -config IRAM_ALLOC +config HAVE_IMX_ANATOP bool - select GENERIC_ALLOCATOR config HAVE_IMX_GPC bool @@ -73,6 +73,7 @@ config HAVE_IMX_MMDC config HAVE_IMX_SRC def_bool y if SMP + select ARCH_HAS_RESET_CONTROLLER config IMX_HAVE_IOMUX_V1 bool @@ -115,6 +116,8 @@ config SOC_IMX25 config SOC_IMX27 bool + select ARCH_HAS_CPUFREQ + select ARCH_HAS_OPP select COMMON_CLK select CPU_ARM926T select IMX_HAVE_IOMUX_V1 @@ -142,6 +145,7 @@ config SOC_IMX35 config SOC_IMX5 bool select ARCH_HAS_CPUFREQ + select ARCH_HAS_OPP select ARCH_MXC_IOMUX_V3 select COMMON_CLK select CPU_V7 @@ -783,7 +787,7 @@ config SOC_IMX53 This enables support for Freescale i.MX53 processor. config SOC_IMX6Q - bool "i.MX6 Quad support" + bool "i.MX6 Quad/DualLite support" select ARCH_HAS_CPUFREQ select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM @@ -796,6 +800,7 @@ config SOC_IMX6Q select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if LOCAL_TIMERS select HAVE_CAN_FLEXCAN if CAN + select HAVE_IMX_ANATOP select HAVE_IMX_GPC select HAVE_IMX_MMDC select HAVE_IMX_SRC diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index fbe60a145344..70ae7c490ac0 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o obj-$(CONFIG_MXC_TZIC) += tzic.o obj-$(CONFIG_MXC_AVIC) += avic.o -obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o @@ -91,6 +90,7 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o +obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o obj-$(CONFIG_HAVE_IMX_SRC) += src.o diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c new file mode 100644 index 000000000000..0cfa07dd9aa4 --- /dev/null +++ b/arch/arm/mach-imx/anatop.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> +#include "common.h" + +#define REG_SET 0x4 +#define REG_CLR 0x8 + +#define ANADIG_REG_2P5 0x130 +#define ANADIG_REG_CORE 0x140 +#define ANADIG_ANA_MISC0 0x150 +#define ANADIG_USB1_CHRG_DETECT 0x1b0 +#define ANADIG_USB2_CHRG_DETECT 0x210 +#define ANADIG_DIGPROG 0x260 + +#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000 +#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000 +#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000 +#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000 +#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000 + +static struct regmap *anatop; + +static void imx_anatop_enable_weak2p5(bool enable) +{ + u32 reg, val; + + regmap_read(anatop, ANADIG_ANA_MISC0, &val); + + /* can only be enabled when stop_mode_config is clear. */ + reg = ANADIG_REG_2P5; + reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ? + REG_SET : REG_CLR; + regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG); +} + +static void imx_anatop_enable_fet_odrive(bool enable) +{ + regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR), + BM_ANADIG_REG_CORE_FET_ODRIVE); +} + +void imx_anatop_pre_suspend(void) +{ + imx_anatop_enable_weak2p5(true); + imx_anatop_enable_fet_odrive(true); +} + +void imx_anatop_post_resume(void) +{ + imx_anatop_enable_fet_odrive(false); + imx_anatop_enable_weak2p5(false); +} + +void imx_anatop_usb_chrg_detect_disable(void) +{ + regmap_write(anatop, ANADIG_USB1_CHRG_DETECT, + BM_ANADIG_USB_CHRG_DETECT_EN_B + | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); + regmap_write(anatop, ANADIG_USB2_CHRG_DETECT, + BM_ANADIG_USB_CHRG_DETECT_EN_B | + BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); +} + +u32 imx_anatop_get_digprog(void) +{ + struct device_node *np; + void __iomem *anatop_base; + static u32 digprog; + + if (digprog) + return digprog; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); + anatop_base = of_iomap(np, 0); + WARN_ON(!anatop_base); + digprog = readl_relaxed(anatop_base + ANADIG_DIGPROG); + + return digprog; +} + +void __init imx_anatop_init(void) +{ + anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop"); + if (IS_ERR(anatop)) { + pr_err("%s: failed to find imx6q-anatop regmap!\n", __func__); + return; + } +} diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index 2bc623b414c1..6fc486b6a3c6 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -45,16 +45,40 @@ static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", " static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", }; static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", }; static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", }; -static const char *tve_sel[] = { "tve_pred", "tve_ext_sel", }; +static const char *mx51_tve_sel[] = { "tve_pred", "tve_ext_sel", }; static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; +static const char *gpu3d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" }; +static const char *gpu2d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" }; static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", }; +static const char *mx53_cko1_sel[] = { + "cpu_podf", "pll1_sw", "pll2_sw", "pll3_sw", + "emi_slow_podf", "pll4_sw", "nfc_podf", "dummy", + "di_pred", "dummy", "dummy", "ahb", + "ipg", "per_root", "ckil", "dummy",}; +static const char *mx53_cko2_sel[] = { + "dummy"/* dptc_core */, "dummy"/* dptc_perich */, + "dummy", "esdhc_a_podf", + "usboh3_podf", "dummy"/* wrck_clk_root */, + "ecspi_podf", "dummy"/* pll1_ref_clk */, + "esdhc_b_podf", "dummy"/* ddr_clk_root */, + "dummy"/* arm_axi_clk_root */, "dummy"/* usb_phy_out */, + "vpu_sel", "ipu_sel", + "osc", "ckih1", + "dummy", "esdhc_c_sel", + "ssi1_root_podf", "ssi2_root_podf", + "dummy", "dummy", + "dummy"/* lpsr_clk_root */, "dummy"/* pgc_clk_root */, + "dummy"/* tve_out */, "usb_phy_sel", + "tve_sel", "lp_apm", + "uart_root", "dummy"/* spdif0_clk_root */, + "dummy", "dummy", }; enum imx5_clks { dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred, uart_root, esdhc_a_pred, esdhc_b_pred, esdhc_c_s, esdhc_d_s, emi_sel, emi_slow_podf, nfc_podf, ecspi_pred, ecspi_podf, usboh3_pred, - usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di, + usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di_unused, tve_s, uart1_ipg_gate, uart1_per_gate, uart2_ipg_gate, uart2_per_gate, uart3_ipg_gate, uart3_per_gate, i2c1_gate, i2c2_gate, gpt_ipg_gate, pwm1_ipg_gate, pwm1_hf_gate, pwm2_ipg_gate, pwm2_hf_gate, @@ -83,7 +107,10 @@ enum imx5_clks { ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate, epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate, can_sel, can1_serial_gate, can1_ipg_gate, - owire_gate, + owire_gate, gpu3d_s, gpu2d_s, gpu3d_gate, gpu2d_gate, garb_gate, + cko1_sel, cko1_podf, cko1, + cko2_sel, cko2_podf, cko2, + srtc_gate, pata_gate, clk_max }; @@ -160,8 +187,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str)); clk[cpu_podf] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3); clk[di_pred] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3); - clk[tve_di] = imx_clk_fixed("tve_di", 65000000); /* FIXME */ - clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, tve_sel, ARRAY_SIZE(tve_sel)); clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30); clk[uart1_ipg_gate] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6); clk[uart1_per_gate] = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8); @@ -200,6 +225,11 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk[nfc_gate] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20); clk[ipu_di0_gate] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10); clk[ipu_di1_gate] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12); + clk[gpu3d_s] = imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel)); + clk[gpu2d_s] = imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel)); + clk[gpu3d_gate] = imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2); + clk[garb_gate] = imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4); + clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14); clk[vpu_s] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel)); clk[vpu_gate] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6); clk[vpu_reference_gate] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8); @@ -235,6 +265,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk[epit2_ipg_gate] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6); clk[epit2_hf_gate] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8); clk[owire_gate] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22); + clk[srtc_gate] = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28); + clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0); for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) @@ -286,7 +318,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0"); clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1"); clk_register_clkdev(clk[dummy], NULL, "imx-keypad"); - clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0"); clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0"); clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL); clk_register_clkdev(clk[epit1_ipg_gate], "ipg", "imx-epit.0"); @@ -331,8 +362,10 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel)); clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel)); - clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, - mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel)); + clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, + mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT); + clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, + mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel)); clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30); clk[tve_pred] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3); clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); @@ -420,23 +453,23 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE); clk[pll4_sw] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE); - clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1, - mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel)); clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); - clk[ldb_di1_div] = imx_clk_divider("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1); + clk[ldb_di1_div] = imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0); + clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1, + mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT); clk[di_pll4_podf] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3); - clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1, - mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel)); clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); - clk[ldb_di0_div] = imx_clk_divider("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1); + clk[ldb_di0_div] = imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0); + clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1, + mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT); clk[ldb_di0_gate] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28); clk[ldb_di1_gate] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30); clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel)); clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel)); - clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, - mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel)); + clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, + mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT); clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30); clk[tve_pred] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3); clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); @@ -453,6 +486,16 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6); clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22); + clk[cko1_sel] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4, + mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel)); + clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3); + clk[cko1] = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7); + + clk[cko2_sel] = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5, + mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel)); + clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3); + clk[cko2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24); + for (i = 0; i < ARRAY_SIZE(clk); i++) if (IS_ERR(clk[i])) pr_err("i.MX53 clk %d: register failed with %ld\n", diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index d38e54f5b6d7..151259003086 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -14,6 +14,7 @@ #include <linux/types.h> #include <linux/clk.h> #include <linux/clkdev.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/io.h> #include <linux/of.h> @@ -22,6 +23,12 @@ #include "clk.h" #include "common.h" +#include "hardware.h" + +#define CCR 0x0 +#define BM_CCR_WB_COUNT (0x7 << 16) +#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) +#define BM_CCR_RBC_EN (0x1 << 27) #define CCGR0 0x68 #define CCGR1 0x6c @@ -67,6 +74,67 @@ void imx6q_set_chicken_bit(void) writel_relaxed(val, ccm_base + CGPR); } +static void imx6q_enable_rbc(bool enable) +{ + u32 val; + static bool last_rbc_mode; + + if (last_rbc_mode == enable) + return; + /* + * need to mask all interrupts in GPC before + * operating RBC configurations + */ + imx_gpc_mask_all(); + + /* configure RBC enable bit */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_RBC_EN; + val |= enable ? BM_CCR_RBC_EN : 0; + writel_relaxed(val, ccm_base + CCR); + + /* configure RBC count */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_RBC_BYPASS_COUNT; + val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; + writel(val, ccm_base + CCR); + + /* + * need to delay at least 2 cycles of CKIL(32K) + * due to hardware design requirement, which is + * ~61us, here we use 65us for safe + */ + udelay(65); + + /* restore GPC interrupt mask settings */ + imx_gpc_restore_all(); + + last_rbc_mode = enable; +} + +static void imx6q_enable_wb(bool enable) +{ + u32 val; + static bool last_wb_mode; + + if (last_wb_mode == enable) + return; + + /* configure well bias enable bit */ + val = readl_relaxed(ccm_base + CLPCR); + val &= ~BM_CLPCR_WB_PER_AT_LPM; + val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; + writel_relaxed(val, ccm_base + CLPCR); + + /* configure well bias count */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_WB_COUNT; + val |= enable ? BM_CCR_WB_COUNT : 0; + writel_relaxed(val, ccm_base + CCR); + + last_wb_mode = enable; +} + int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) { u32 val = readl_relaxed(ccm_base + CLPCR); @@ -74,6 +142,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) val &= ~BM_CLPCR_LPM; switch (mode) { case WAIT_CLOCKED: + imx6q_enable_wb(false); + imx6q_enable_rbc(false); break; case WAIT_UNCLOCKED: val |= 0x1 << BP_CLPCR_LPM; @@ -92,6 +162,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) val |= 0x3 << BP_CLPCR_STBY_COUNT; val |= BM_CLPCR_VSTBY; val |= BM_CLPCR_SBYOS; + imx6q_enable_wb(true); + imx6q_enable_rbc(true); break; default: return -EINVAL; @@ -109,29 +181,29 @@ static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", }; static const char *periph_sels[] = { "periph_pre", "periph_clk2", }; static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", }; static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "pll3_pfd1_540m", }; -static const char *audio_sels[] = { "pll4_audio", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", }; +static const char *audio_sels[] = { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", }; static const char *gpu_axi_sels[] = { "axi", "ahb", }; static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", }; static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", }; static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", }; static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", }; -static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; +static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", }; static const char *pcie_axi_sels[] = { "axi", "ahb", }; -static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio", }; +static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", }; static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", }; static const char *emi_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", }; static const char *vdo_axi_sels[] = { "axi", "ahb", }; static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", }; -static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video", +static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0", - "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio", }; + "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", }; enum mx6q_clks { dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m, @@ -165,7 +237,7 @@ enum mx6q_clks { pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg, ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, - usbphy2_gate, clk_max + usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, clk_max }; static struct clk *clk[clk_max]; @@ -182,6 +254,21 @@ static struct clk_div_table clk_enet_ref_table[] = { { .val = 3, .div = 4, }, }; +static struct clk_div_table post_div_table[] = { + { .val = 2, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 0, .div = 4, }, + { } +}; + +static struct clk_div_table video_div_table[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 2, .div = 1, }, + { .val = 3, .div = 4, }, + { } +}; + int __init mx6q_clocks_init(void) { struct device_node *np; @@ -208,6 +295,14 @@ int __init mx6q_clocks_init(void) base = of_iomap(np, 0); WARN_ON(!base); + /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */ + if (cpu_is_imx6q() && imx6q_revision() == IMX_CHIP_REVISION_1_0) { + post_div_table[1].div = 1; + post_div_table[2].div = 1; + video_div_table[1].div = 1; + video_div_table[2].div = 1; + }; + /* type name parent_name base div_mask */ clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); @@ -260,6 +355,10 @@ int __init mx6q_clocks_init(void) clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2); + clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); + clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); + clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm"); base = of_iomap(np, 0); WARN_ON(!base); @@ -283,8 +382,8 @@ int __init mx6q_clocks_init(void) clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels)); clk[ipu1_sel] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); - clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); - clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); + clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); + clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); @@ -332,9 +431,9 @@ int __init mx6q_clocks_init(void) clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3); clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3); clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); - clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1); + clk[ldb_di0_podf] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0); clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); - clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1); + clk[ldb_di1_podf] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0); clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3); clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3); clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3); @@ -448,6 +547,11 @@ int __init mx6q_clocks_init(void) clk_register_clkdev(clk[cko1], "cko1", NULL); clk_register_clkdev(clk[arm], NULL, "cpu0"); + if (imx6q_revision() != IMX_CHIP_REVISION_1_0) { + clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]); + clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]); + } + /* * The gpmi needs 100MHz frequency in the EDO/Sync mode, * We can not get the 100MHz from the pll2_pfd0_352m. diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 9d1f3b99d1d3..d9d9d9c66dff 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -59,6 +59,14 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent, reg, shift, width, 0, &imx_ccm_lock); } +static inline struct clk *imx_clk_divider_flags(const char *name, + const char *parent, void __iomem *reg, u8 shift, u8 width, + unsigned long flags) +{ + return clk_register_divider(NULL, name, parent, flags, + reg, shift, width, 0, &imx_ccm_lock); +} + static inline struct clk *imx_clk_gate(const char *name, const char *parent, void __iomem *reg, u8 shift) { @@ -73,6 +81,15 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg, width, 0, &imx_ccm_lock); } +static inline struct clk *imx_clk_mux_flags(const char *name, + void __iomem *reg, u8 shift, u8 width, const char **parents, + int num_parents, unsigned long flags) +{ + return clk_register_mux(NULL, name, parents, num_parents, + flags, reg, shift, width, 0, + &imx_ccm_lock); +} + static inline struct clk *imx_clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div) { diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 9fea2522d7a3..c08ae3f99cee 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -12,6 +12,7 @@ #define __ASM_ARCH_MXC_COMMON_H__ struct platform_device; +struct pt_regs; struct clk; enum mxc_cpu_pwr_mode; @@ -74,6 +75,7 @@ extern void mxc_set_cpu_type(unsigned int type); extern void mxc_restart(char, const char *); extern void mxc_arch_reset_init(void __iomem *); extern int mx53_revision(void); +extern int imx6q_revision(void); extern int mx53_display_revision(void); extern void imx_set_aips(void __iomem *); extern int mxc_device_init(void); @@ -128,6 +130,13 @@ extern void imx_src_prepare_restart(void); extern void imx_gpc_init(void); extern void imx_gpc_pre_suspend(void); extern void imx_gpc_post_resume(void); +extern void imx_gpc_mask_all(void); +extern void imx_gpc_restore_all(void); +extern void imx_anatop_init(void); +extern void imx_anatop_pre_suspend(void); +extern void imx_anatop_post_resume(void); +extern void imx_anatop_usb_chrg_detect_disable(void); +extern u32 imx_anatop_get_digprog(void); extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); extern void imx6q_set_chicken_bit(void); diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 02b61cdf39b9..44a65e9ff1fc 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -69,6 +69,27 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } +void imx_gpc_mask_all(void) +{ + void __iomem *reg_imr1 = gpc_base + GPC_IMR1; + int i; + + for (i = 0; i < IMR_NUM; i++) { + gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); + writel_relaxed(~0, reg_imr1 + i * 4); + } + +} + +void imx_gpc_restore_all(void) +{ + void __iomem *reg_imr1 = gpc_base + GPC_IMR1; + int i; + + for (i = 0; i < IMR_NUM; i++) + writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); +} + static void imx_gpc_irq_unmask(struct irq_data *d) { void __iomem *reg; diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S index a58c8b0527cc..67b9c48dcafe 100644 --- a/arch/arm/mach-imx/headsmp.S +++ b/arch/arm/mach-imx/headsmp.S @@ -24,7 +24,7 @@ ENTRY(v7_secondary_startup) ENDPROC(v7_secondary_startup) #endif -#ifdef CONFIG_PM +#ifdef CONFIG_ARM_CPU_SUSPEND /* * The following code must assume it is running from physical address * where absolute virtual addresses to the data section have to be diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 5e91112dcbee..3daf1ed90579 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -11,7 +11,9 @@ */ #include <linux/errno.h> +#include <linux/jiffies.h> #include <asm/cp15.h> +#include <asm/proc-fns.h> #include "common.h" diff --git a/arch/arm/mach-imx/iram_alloc.c b/arch/arm/mach-imx/iram_alloc.c deleted file mode 100644 index e05cf407db65..000000000000 --- a/arch/arm/mach-imx/iram_alloc.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/genalloc.h> -#include "linux/platform_data/imx-iram.h" - -static unsigned long iram_phys_base; -static void __iomem *iram_virt_base; -static struct gen_pool *iram_pool; - -static inline void __iomem *iram_phys_to_virt(unsigned long p) -{ - return iram_virt_base + (p - iram_phys_base); -} - -void __iomem *iram_alloc(unsigned int size, unsigned long *dma_addr) -{ - if (!iram_pool) - return NULL; - - *dma_addr = gen_pool_alloc(iram_pool, size); - pr_debug("iram alloc - %dB@0x%lX\n", size, *dma_addr); - if (!*dma_addr) - return NULL; - return iram_phys_to_virt(*dma_addr); -} -EXPORT_SYMBOL(iram_alloc); - -void iram_free(unsigned long addr, unsigned int size) -{ - if (!iram_pool) - return; - - gen_pool_free(iram_pool, addr, size); -} -EXPORT_SYMBOL(iram_free); - -int __init iram_init(unsigned long base, unsigned long size) -{ - iram_phys_base = base; - - iram_pool = gen_pool_create(PAGE_SHIFT, -1); - if (!iram_pool) - return -ENOMEM; - - gen_pool_add(iram_pool, base, size, -1); - iram_virt_base = ioremap(iram_phys_base, size); - if (!iram_virt_base) - return -EIO; - - pr_debug("i.MX IRAM pool: %ld KB@0x%p\n", size / 1024, iram_virt_base); - return 0; -} diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 99502eeefdf7..5536fd81379a 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -38,38 +38,32 @@ #include "cpuidle.h" #include "hardware.h" -#define IMX6Q_ANALOG_DIGPROG 0x260 +static u32 chip_revision; -static int imx6q_revision(void) +int imx6q_revision(void) { - struct device_node *np; - void __iomem *base; - static u32 rev; - - if (!rev) { - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); - if (!np) - return IMX_CHIP_REVISION_UNKNOWN; - base = of_iomap(np, 0); - if (!base) { - of_node_put(np); - return IMX_CHIP_REVISION_UNKNOWN; - } - rev = readl_relaxed(base + IMX6Q_ANALOG_DIGPROG); - iounmap(base); - of_node_put(np); - } + return chip_revision; +} + +static void __init imx6q_init_revision(void) +{ + u32 rev = imx_anatop_get_digprog(); switch (rev & 0xff) { case 0: - return IMX_CHIP_REVISION_1_0; + chip_revision = IMX_CHIP_REVISION_1_0; + break; case 1: - return IMX_CHIP_REVISION_1_1; + chip_revision = IMX_CHIP_REVISION_1_1; + break; case 2: - return IMX_CHIP_REVISION_1_2; + chip_revision = IMX_CHIP_REVISION_1_2; + break; default: - return IMX_CHIP_REVISION_UNKNOWN; + chip_revision = IMX_CHIP_REVISION_UNKNOWN; } + + mxc_set_cpu_type(rev >> 16 & 0xff); } static void imx6q_restart(char mode, const char *cmd) @@ -164,29 +158,7 @@ static void __init imx6q_1588_init(void) } static void __init imx6q_usb_init(void) { - struct regmap *anatop; - -#define HW_ANADIG_USB1_CHRG_DETECT 0x000001b0 -#define HW_ANADIG_USB2_CHRG_DETECT 0x00000210 - -#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x00100000 -#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x00080000 - - anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop"); - if (!IS_ERR(anatop)) { - /* - * The external charger detector needs to be disabled, - * or the signal at DP will be poor - */ - regmap_write(anatop, HW_ANADIG_USB1_CHRG_DETECT, - BM_ANADIG_USB_CHRG_DETECT_EN_B - | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); - regmap_write(anatop, HW_ANADIG_USB2_CHRG_DETECT, - BM_ANADIG_USB_CHRG_DETECT_EN_B | - BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); - } else { - pr_warn("failed to find fsl,imx6q-anatop regmap\n"); - } + imx_anatop_usb_chrg_detect_disable(); } static void __init imx6q_init_machine(void) @@ -196,6 +168,7 @@ static void __init imx6q_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + imx_anatop_init(); imx6q_pm_init(); imx6q_usb_init(); imx6q_1588_init(); @@ -282,6 +255,7 @@ static void __init imx6q_map_io(void) static void __init imx6q_init_irq(void) { + imx6q_init_revision(); l2x0_of_init(0, ~0UL); imx_src_init(); imx_gpc_init(); @@ -292,15 +266,17 @@ static void __init imx6q_timer_init(void) { mx6q_clocks_init(); clocksource_of_init(); - imx_print_silicon_rev("i.MX6Q", imx6q_revision()); + imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q", + imx6q_revision()); } static const char *imx6q_dt_compat[] __initdata = { + "fsl,imx6dl", "fsl,imx6q", NULL, }; -DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)") +DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)") .smp = smp_ops(imx_smp_ops), .map_io = imx6q_map_io, .init_irq = imx6q_init_irq, diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c index 7a146671e65a..3c609c52d3eb 100644 --- a/arch/arm/mach-imx/mm-imx1.c +++ b/arch/arm/mach-imx/mm-imx1.c @@ -51,6 +51,8 @@ void __init mx1_init_irq(void) void __init imx1_soc_init(void) { + mxc_device_init(); + mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256, MX1_GPIO_INT_PORTA, 0); mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256, diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h index 7dce17a9fe6c..8629e5be7ecd 100644 --- a/arch/arm/mach-imx/mxc.h +++ b/arch/arm/mach-imx/mxc.h @@ -34,6 +34,8 @@ #define MXC_CPU_MX35 35 #define MXC_CPU_MX51 51 #define MXC_CPU_MX53 53 +#define MXC_CPU_IMX6DL 0x61 +#define MXC_CPU_IMX6Q 0x63 #define IMX_CHIP_REVISION_1_0 0x10 #define IMX_CHIP_REVISION_1_1 0x11 @@ -150,6 +152,15 @@ extern unsigned int __mxc_cpu_type; #endif #ifndef __ASSEMBLY__ +static inline bool cpu_is_imx6dl(void) +{ + return __mxc_cpu_type == MXC_CPU_IMX6DL; +} + +static inline bool cpu_is_imx6q(void) +{ + return __mxc_cpu_type == MXC_CPU_IMX6Q; +} struct cpu_op { u32 cpu_rate; diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 77e9a25ed0f6..4a69305db65e 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -68,8 +68,8 @@ static void __init imx_smp_init_cpus(void) ncores = scu_get_core_count(scu_base); - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); + for (i = ncores; i < NR_CPUS; i++) + set_cpu_possible(i, false); } void imx_smp_prepare(void) diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c index 5faba7a3c95f..204942749e21 100644 --- a/arch/arm/mach-imx/pm-imx6q.c +++ b/arch/arm/mach-imx/pm-imx6q.c @@ -1,5 +1,5 @@ /* - * Copyright 2011 Freescale Semiconductor, Inc. + * Copyright 2011-2013 Freescale Semiconductor, Inc. * Copyright 2011 Linaro Ltd. * * The code contained herein is licensed under the GNU General Public @@ -34,10 +34,12 @@ static int imx6q_pm_enter(suspend_state_t state) case PM_SUSPEND_MEM: imx6q_set_lpm(STOP_POWER_OFF); imx_gpc_pre_suspend(); + imx_anatop_pre_suspend(); imx_set_cpu_jump(0, v7_cpu_resume); /* Zzz ... */ cpu_suspend(0, imx6q_suspend_finish); imx_smp_prepare(); + imx_anatop_post_resume(); imx_gpc_post_resume(); imx6q_set_lpm(WAIT_CLOCKED); break; diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 97d086889481..10a6b1a8c5ac 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -14,6 +14,7 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/reset-controller.h> #include <linux/smp.h> #include <asm/smp_plat.h> #include "common.h" @@ -21,10 +22,65 @@ #define SRC_SCR 0x000 #define SRC_GPR1 0x020 #define BP_SRC_SCR_WARM_RESET_ENABLE 0 +#define BP_SRC_SCR_SW_GPU_RST 1 +#define BP_SRC_SCR_SW_VPU_RST 2 +#define BP_SRC_SCR_SW_IPU1_RST 3 +#define BP_SRC_SCR_SW_OPEN_VG_RST 4 +#define BP_SRC_SCR_SW_IPU2_RST 12 #define BP_SRC_SCR_CORE1_RST 14 #define BP_SRC_SCR_CORE1_ENABLE 22 static void __iomem *src_base; +static DEFINE_SPINLOCK(scr_lock); + +static const int sw_reset_bits[5] = { + BP_SRC_SCR_SW_GPU_RST, + BP_SRC_SCR_SW_VPU_RST, + BP_SRC_SCR_SW_IPU1_RST, + BP_SRC_SCR_SW_OPEN_VG_RST, + BP_SRC_SCR_SW_IPU2_RST +}; + +static int imx_src_reset_module(struct reset_controller_dev *rcdev, + unsigned long sw_reset_idx) +{ + unsigned long timeout; + unsigned long flags; + int bit; + u32 val; + + if (!src_base) + return -ENODEV; + + if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits)) + return -EINVAL; + + bit = 1 << sw_reset_bits[sw_reset_idx]; + + spin_lock_irqsave(&scr_lock, flags); + val = readl_relaxed(src_base + SRC_SCR); + val |= bit; + writel_relaxed(val, src_base + SRC_SCR); + spin_unlock_irqrestore(&scr_lock, flags); + + timeout = jiffies + msecs_to_jiffies(1000); + while (readl(src_base + SRC_SCR) & bit) { + if (time_after(jiffies, timeout)) + return -ETIME; + cpu_relax(); + } + + return 0; +} + +static struct reset_control_ops imx_src_ops = { + .reset = imx_src_reset_module, +}; + +static struct reset_controller_dev imx_reset_controller = { + .ops = &imx_src_ops, + .nr_resets = ARRAY_SIZE(sw_reset_bits), +}; void imx_enable_cpu(int cpu, bool enable) { @@ -32,9 +88,11 @@ void imx_enable_cpu(int cpu, bool enable) cpu = cpu_logical_map(cpu); mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1); + spin_lock(&scr_lock); val = readl_relaxed(src_base + SRC_SCR); val = enable ? val | mask : val & ~mask; writel_relaxed(val, src_base + SRC_SCR); + spin_unlock(&scr_lock); } void imx_set_cpu_jump(int cpu, void *jump_addr) @@ -61,9 +119,11 @@ void imx_src_prepare_restart(void) u32 val; /* clear enable bits of secondary cores */ + spin_lock(&scr_lock); val = readl_relaxed(src_base + SRC_SCR); val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE); writel_relaxed(val, src_base + SRC_SCR); + spin_unlock(&scr_lock); /* clear persistent entry register of primary core */ writel_relaxed(0, src_base + SRC_GPR1); @@ -80,11 +140,17 @@ void __init imx_src_init(void) src_base = of_iomap(np, 0); WARN_ON(!src_base); + imx_reset_controller.of_node = np; + if (IS_ENABLED(CONFIG_RESET_CONTROLLER)) + reset_controller_register(&imx_reset_controller); + /* * force warm reset sources to generate cold reset * for a more reliable restart */ + spin_lock(&scr_lock); val = readl_relaxed(src_base + SRC_SCR); val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE); writel_relaxed(val, src_base + SRC_SCR); + spin_unlock(&scr_lock); } diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index da1091be0887..8c60fcb08a98 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -250,39 +250,6 @@ static void __init intcp_init_early(void) } #ifdef CONFIG_OF - -static void __init cp_of_timer_init(void) -{ - struct device_node *node; - const char *path; - void __iomem *base; - int err; - int irq; - - err = of_property_read_string(of_aliases, - "arm,timer-primary", &path); - if (WARN_ON(err)) - return; - node = of_find_node_by_path(path); - base = of_iomap(node, 0); - if (WARN_ON(!base)) - return; - writel(0, base + TIMER_CTRL); - sp804_clocksource_init(base, node->name); - - err = of_property_read_string(of_aliases, - "arm,timer-secondary", &path); - if (WARN_ON(err)) - return; - node = of_find_node_by_path(path); - base = of_iomap(node, 0); - if (WARN_ON(!base)) - return; - irq = irq_of_parse_and_map(node, 0); - writel(0, base + TIMER_CTRL); - sp804_clockevents_init(base, irq, node->name); -} - static const struct of_device_id fpga_irq_of_match[] __initconst = { { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, { /* Sentinel */ } @@ -383,7 +350,6 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)") .init_early = intcp_init_early, .init_irq = intcp_init_irq_of, .handle_irq = fpga_handle_irq, - .init_time = cp_of_timer_init, .init_machine = intcp_init_of, .restart = integrator_restart, .dt_compat = intcp_dt_board_compat, diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index cdbca328a412..e1f3735d3415 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o irq.o pcie.o mpp.o +obj-y += common.o irq.o pcie.o mpp.o obj-$(CONFIG_MACH_D2NET_V2) += d2net_v2-setup.o lacie_v2-common.o obj-$(CONFIG_MACH_DB88F6281_BP) += db88f6281-bp-setup.o diff --git a/arch/arm/mach-kirkwood/addr-map.c b/arch/arm/mach-kirkwood/addr-map.c deleted file mode 100644 index 8f0d162a1e1d..000000000000 --- a/arch/arm/mach-kirkwood/addr-map.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * arch/arm/mach-kirkwood/addr-map.c - * - * Address map functions for Marvell Kirkwood SoCs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <mach/hardware.h> -#include <plat/addr-map.h> -#include "common.h" - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DEV_BUS 1 -#define TARGET_SRAM 3 -#define TARGET_PCIE 4 -#define ATTR_DEV_SPI_ROM 0x1e -#define ATTR_DEV_BOOT 0x1d -#define ATTR_DEV_NAND 0x2f -#define ATTR_DEV_CS3 0x37 -#define ATTR_DEV_CS2 0x3b -#define ATTR_DEV_CS1 0x3d -#define ATTR_DEV_CS0 0x3e -#define ATTR_PCIE_IO 0xe0 -#define ATTR_PCIE_MEM 0xe8 -#define ATTR_PCIE1_IO 0xd0 -#define ATTR_PCIE1_MEM 0xd8 -#define ATTR_SRAM 0x01 - -/* - * Description of the windows needed by the platform code - */ -static struct __initdata orion_addr_map_cfg addr_map_cfg = { - .num_wins = 8, - .remappable_wins = 4, - .bridge_virt_base = BRIDGE_VIRT_BASE, -}; - -static const struct __initdata orion_addr_map_info addr_map_info[] = { - /* - * Windows for PCIe IO+MEM space. - */ - { 0, KIRKWOOD_PCIE_IO_PHYS_BASE, KIRKWOOD_PCIE_IO_SIZE, - TARGET_PCIE, ATTR_PCIE_IO, KIRKWOOD_PCIE_IO_BUS_BASE - }, - { 1, KIRKWOOD_PCIE_MEM_PHYS_BASE, KIRKWOOD_PCIE_MEM_SIZE, - TARGET_PCIE, ATTR_PCIE_MEM, KIRKWOOD_PCIE_MEM_BUS_BASE - }, - { 2, KIRKWOOD_PCIE1_IO_PHYS_BASE, KIRKWOOD_PCIE1_IO_SIZE, - TARGET_PCIE, ATTR_PCIE1_IO, KIRKWOOD_PCIE1_IO_BUS_BASE - }, - { 3, KIRKWOOD_PCIE1_MEM_PHYS_BASE, KIRKWOOD_PCIE1_MEM_SIZE, - TARGET_PCIE, ATTR_PCIE1_MEM, KIRKWOOD_PCIE1_MEM_BUS_BASE - }, - /* - * Window for NAND controller. - */ - { 4, KIRKWOOD_NAND_MEM_PHYS_BASE, KIRKWOOD_NAND_MEM_SIZE, - TARGET_DEV_BUS, ATTR_DEV_NAND, -1 - }, - /* - * Window for SRAM. - */ - { 5, KIRKWOOD_SRAM_PHYS_BASE, KIRKWOOD_SRAM_SIZE, - TARGET_SRAM, ATTR_SRAM, -1 - }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 } -}; - -void __init kirkwood_setup_cpu_mbus(void) -{ - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, addr_map_info); - - /* - * Setup MBUS dram target info. - */ - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) DDR_WINDOW_CPU_BASE); -} diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 7904758e771f..e9647b80cb59 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -93,7 +93,7 @@ static void __init kirkwood_dt_init(void) */ writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG); - kirkwood_setup_cpu_mbus(); + kirkwood_setup_wins(); kirkwood_l2_init(); diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 49792a0cd2d3..c2cae69e6d2b 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -33,7 +33,6 @@ #include <linux/platform_data/usb-ehci-orion.h> #include <plat/common.h> #include <plat/time.h> -#include <plat/addr-map.h> #include <linux/platform_data/dma-mv_xor.h> #include "common.h" @@ -535,6 +534,9 @@ void __init kirkwood_init_early(void) * the allocations won't fail. */ init_dma_coherent_pool_size(SZ_1M); + mvebu_mbus_init("marvell,kirkwood-mbus", + BRIDGE_WINS_BASE, BRIDGE_WINS_SZ, + DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ); } int kirkwood_tclk; @@ -650,6 +652,38 @@ char * __init kirkwood_id(void) } } +void __init kirkwood_setup_wins(void) +{ + /* + * The PCIe windows will no longer be statically allocated + * here once Kirkwood is migrated to the pci-mvebu driver. + */ + mvebu_mbus_add_window_remap_flags("pcie0.0", + KIRKWOOD_PCIE_IO_PHYS_BASE, + KIRKWOOD_PCIE_IO_SIZE, + KIRKWOOD_PCIE_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie0.0", + KIRKWOOD_PCIE_MEM_PHYS_BASE, + KIRKWOOD_PCIE_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags("pcie1.0", + KIRKWOOD_PCIE1_IO_PHYS_BASE, + KIRKWOOD_PCIE1_IO_SIZE, + KIRKWOOD_PCIE1_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie1.0", + KIRKWOOD_PCIE1_MEM_PHYS_BASE, + KIRKWOOD_PCIE1_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window("nand", KIRKWOOD_NAND_MEM_PHYS_BASE, + KIRKWOOD_NAND_MEM_SIZE); + mvebu_mbus_add_window("sram", KIRKWOOD_SRAM_PHYS_BASE, + KIRKWOOD_SRAM_SIZE); +} + void __init kirkwood_l2_init(void) { #ifdef CONFIG_CACHE_FEROCEON_L2 @@ -675,7 +709,7 @@ void __init kirkwood_init(void) */ writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG); - kirkwood_setup_cpu_mbus(); + kirkwood_setup_wins(); kirkwood_l2_init(); diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h index 3147be2f34da..21da3b1ebd7b 100644 --- a/arch/arm/mach-kirkwood/common.h +++ b/arch/arm/mach-kirkwood/common.h @@ -30,7 +30,7 @@ void kirkwood_init(void); void kirkwood_init_early(void); void kirkwood_init_irq(void); -void kirkwood_setup_cpu_mbus(void); +void kirkwood_setup_wins(void); void kirkwood_enable_pcie(void); void kirkwood_pcie_id(u32 *dev, u32 *rev); diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index a05563a31c95..92976cef3910 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -60,8 +60,9 @@ * Register Map */ #define DDR_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x00000) -#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000) -#define DDR_WINDOW_CPU_BASE (DDR_VIRT_BASE + 0x1500) +#define DDR_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x00000) +#define DDR_WINDOW_CPU_BASE (DDR_PHYS_BASE + 0x1500) +#define DDR_WINDOW_CPU_SZ (0x20) #define DDR_OPERATION_BASE (DDR_PHYS_BASE + 0x1418) #define DEV_BUS_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x10000) @@ -80,6 +81,8 @@ #define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE + 0x20000) #define BRIDGE_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x20000) +#define BRIDGE_WINS_BASE (BRIDGE_PHYS_BASE) +#define BRIDGE_WINS_SZ (0x80) #define CRYPTO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE + 0x30000) diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index d96ad4c09972..7f43e6c2f8c0 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -17,7 +17,6 @@ #include <asm/mach/pci.h> #include <plat/pcie.h> #include <mach/bridge-regs.h> -#include <plat/addr-map.h> #include "common.h" static void kirkwood_enable_pcie_clk(const char *port) diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c index 7777767ee89a..9c392a29fc7e 100644 --- a/arch/arm/mach-msm/last_radio_log.c +++ b/arch/arm/mach-msm/last_radio_log.c @@ -66,6 +66,6 @@ void msm_init_last_radio_log(struct module *owner) pr_err("%s: last radio log is %d bytes long\n", __func__, radio_log_size); last_radio_log_fops.owner = owner; - entry->size = radio_log_size; + proc_set_size(entry, radio_log_size); } EXPORT_SYMBOL(msm_init_last_radio_log); diff --git a/arch/arm/mach-mv78xx0/Makefile b/arch/arm/mach-mv78xx0/Makefile index 67a13f9bfe64..7cd04634d302 100644 --- a/arch/arm/mach-mv78xx0/Makefile +++ b/arch/arm/mach-mv78xx0/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o mpp.o irq.o pcie.o +obj-y += common.o mpp.o irq.o pcie.o obj-$(CONFIG_MACH_DB78X00_BP) += db78x00-bp-setup.o obj-$(CONFIG_MACH_RD78X00_MASA) += rd78x00-masa-setup.o obj-$(CONFIG_MACH_TERASTATION_WXL) += buffalo-wxl-setup.o diff --git a/arch/arm/mach-mv78xx0/addr-map.c b/arch/arm/mach-mv78xx0/addr-map.c deleted file mode 100644 index 26e9876b50e9..000000000000 --- a/arch/arm/mach-mv78xx0/addr-map.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * arch/arm/mach-mv78xx0/addr-map.c - * - * Address map functions for Marvell MV78xx0 SoCs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <plat/addr-map.h> -#include <mach/mv78xx0.h> -#include "common.h" - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DEV_BUS 1 -#define TARGET_PCIE0 4 -#define TARGET_PCIE1 8 -#define TARGET_PCIE(i) ((i) ? TARGET_PCIE1 : TARGET_PCIE0) -#define ATTR_DEV_SPI_ROM 0x1f -#define ATTR_DEV_BOOT 0x2f -#define ATTR_DEV_CS3 0x37 -#define ATTR_DEV_CS2 0x3b -#define ATTR_DEV_CS1 0x3d -#define ATTR_DEV_CS0 0x3e -#define ATTR_PCIE_IO(l) (0xf0 & ~(0x10 << (l))) -#define ATTR_PCIE_MEM(l) (0xf8 & ~(0x10 << (l))) - -/* - * CPU Address Decode Windows registers - */ -#define WIN0_OFF(n) (BRIDGE_VIRT_BASE + 0x0000 + ((n) << 4)) -#define WIN8_OFF(n) (BRIDGE_VIRT_BASE + 0x0900 + (((n) - 8) << 4)) - -static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, int win) -{ - /* - * Find the control register base address for this window. - * - * BRIDGE_VIRT_BASE points to the right (CPU0's or CPU1's) - * MBUS bridge depending on which CPU core we're running on, - * so we don't need to take that into account here. - */ - - return (win < 8) ? WIN0_OFF(win) : WIN8_OFF(win); -} - -/* - * Description of the windows needed by the platform code - */ -static struct orion_addr_map_cfg addr_map_cfg __initdata = { - .num_wins = 14, - .remappable_wins = 8, - .win_cfg_base = win_cfg_base, -}; - -void __init mv78xx0_setup_cpu_mbus(void) -{ - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, NULL); - - /* - * Setup MBUS dram target info. - */ - if (mv78xx0_core_index() == 0) - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) DDR_WINDOW_CPU0_BASE); - else - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) DDR_WINDOW_CPU1_BASE); -} - -void __init mv78xx0_setup_pcie_io_win(int window, u32 base, u32 size, - int maj, int min) -{ - orion_setup_cpu_win(&addr_map_cfg, window, base, size, - TARGET_PCIE(maj), ATTR_PCIE_IO(min), 0); -} - -void __init mv78xx0_setup_pcie_mem_win(int window, u32 base, u32 size, - int maj, int min) -{ - orion_setup_cpu_win(&addr_map_cfg, window, base, size, - TARGET_PCIE(maj), ATTR_PCIE_MEM(min), -1); -} diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c index 0efa14498ebc..749a7f8c4992 100644 --- a/arch/arm/mach-mv78xx0/common.c +++ b/arch/arm/mach-mv78xx0/common.c @@ -334,6 +334,14 @@ void __init mv78xx0_uart3_init(void) void __init mv78xx0_init_early(void) { orion_time_set_base(TIMER_VIRT_BASE); + if (mv78xx0_core_index() == 0) + mvebu_mbus_init("marvell,mv78xx0-mbus", + BRIDGE_WINS_CPU0_BASE, BRIDGE_WINS_SZ, + DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ); + else + mvebu_mbus_init("marvell,mv78xx0-mbus", + BRIDGE_WINS_CPU1_BASE, BRIDGE_WINS_SZ, + DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ); } void __init_refok mv78xx0_timer_init(void) @@ -397,8 +405,6 @@ void __init mv78xx0_init(void) printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000); printk("TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000); - mv78xx0_setup_cpu_mbus(); - #ifdef CONFIG_CACHE_FEROCEON_L2 feroceon_l2_init(is_l2_writethrough()); #endif diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h index 46200a183cf2..723748d8ba7d 100644 --- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h +++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h @@ -60,13 +60,18 @@ */ #define BRIDGE_VIRT_BASE (MV78XX0_CORE_REGS_VIRT_BASE) #define BRIDGE_PHYS_BASE (MV78XX0_CORE_REGS_PHYS_BASE) +#define BRIDGE_WINS_CPU0_BASE (MV78XX0_CORE0_REGS_PHYS_BASE) +#define BRIDGE_WINS_CPU1_BASE (MV78XX0_CORE1_REGS_PHYS_BASE) +#define BRIDGE_WINS_SZ (0xA000) /* * Register Map */ #define DDR_VIRT_BASE (MV78XX0_REGS_VIRT_BASE + 0x00000) -#define DDR_WINDOW_CPU0_BASE (DDR_VIRT_BASE + 0x1500) -#define DDR_WINDOW_CPU1_BASE (DDR_VIRT_BASE + 0x1570) +#define DDR_PHYS_BASE (MV78XX0_REGS_PHYS_BASE + 0x00000) +#define DDR_WINDOW_CPU0_BASE (DDR_PHYS_BASE + 0x1500) +#define DDR_WINDOW_CPU1_BASE (DDR_PHYS_BASE + 0x1570) +#define DDR_WINDOW_CPU_SZ (0x20) #define DEV_BUS_PHYS_BASE (MV78XX0_REGS_PHYS_BASE + 0x10000) #define DEV_BUS_VIRT_BASE (MV78XX0_REGS_VIRT_BASE + 0x10000) diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c index ee8c0b51df2c..dc26a654c496 100644 --- a/arch/arm/mach-mv78xx0/pcie.c +++ b/arch/arm/mach-mv78xx0/pcie.c @@ -10,11 +10,11 @@ #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/mbus.h> #include <video/vga.h> #include <asm/irq.h> #include <asm/mach/pci.h> #include <plat/pcie.h> -#include <plat/addr-map.h> #include <mach/mv78xx0.h> #include "common.h" @@ -54,7 +54,6 @@ static void __init mv78xx0_pcie_preinit(void) int i; u32 size_each; u32 start; - int win = 0; pcie_io_space.name = "PCIe I/O Space"; pcie_io_space.start = MV78XX0_PCIE_IO_PHYS_BASE(0); @@ -72,6 +71,7 @@ static void __init mv78xx0_pcie_preinit(void) start = MV78XX0_PCIE_MEM_PHYS_BASE; for (i = 0; i < num_pcie_ports; i++) { struct pcie_port *pp = pcie_port + i; + char winname[MVEBU_MBUS_MAX_WINNAME_SZ]; snprintf(pp->mem_space_name, sizeof(pp->mem_space_name), "PCIe %d.%d MEM", pp->maj, pp->min); @@ -85,12 +85,17 @@ static void __init mv78xx0_pcie_preinit(void) if (request_resource(&iomem_resource, &pp->res)) panic("can't allocate PCIe MEM sub-space"); - mv78xx0_setup_pcie_mem_win(win + i + 8, pp->res.start, - resource_size(&pp->res), - pp->maj, pp->min); - - mv78xx0_setup_pcie_io_win(win + i, i * SZ_64K, SZ_64K, - pp->maj, pp->min); + snprintf(winname, sizeof(winname), "pcie%d.%d", + pp->maj, pp->min); + + mvebu_mbus_add_window_remap_flags(winname, + pp->res.start, + resource_size(&pp->res), + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags(winname, + i * SZ_64K, SZ_64K, + 0, MVEBU_MBUS_PCI_IO); } } diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 440b13ef1fed..e11acbb0a46d 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -13,6 +13,8 @@ config ARCH_MVEBU select MVEBU_CLK_CORE select MVEBU_CLK_CPU select MVEBU_CLK_GATING + select MVEBU_MBUS + select ZONE_DMA if ARM_LPAE if ARCH_MVEBU diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index da93bcbc74c1..2d04f0e21870 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -5,6 +5,6 @@ AFLAGS_coherency_ll.o := -Wa,-march=armv7-a obj-y += system-controller.o obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o -obj-$(CONFIG_ARCH_MVEBU) += addr-map.o coherency.o coherency_ll.o pmsu.o irq-armada-370-xp.o +obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-mvebu/addr-map.c b/arch/arm/mach-mvebu/addr-map.c deleted file mode 100644 index ab9b3bd4fef5..000000000000 --- a/arch/arm/mach-mvebu/addr-map.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Address map functions for Marvell 370 / XP SoCs - * - * Copyright (C) 2012 Marvell - * - * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <plat/addr-map.h> - -/* - * Generic Address Decode Windows bit settings - */ -#define ARMADA_XP_TARGET_DEV_BUS 1 -#define ARMADA_XP_ATTR_DEV_BOOTROM 0x1D -#define ARMADA_XP_TARGET_ETH1 3 -#define ARMADA_XP_TARGET_PCIE_0_2 4 -#define ARMADA_XP_TARGET_ETH0 7 -#define ARMADA_XP_TARGET_PCIE_1_3 8 - -#define ARMADA_370_TARGET_DEV_BUS 1 -#define ARMADA_370_ATTR_DEV_BOOTROM 0x1D -#define ARMADA_370_TARGET_PCIE_0 4 -#define ARMADA_370_TARGET_PCIE_1 8 - -#define ARMADA_WINDOW_8_PLUS_OFFSET 0x90 -#define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180 - -static const struct __initdata orion_addr_map_info -armada_xp_addr_map_info[] = { - /* - * Window for the BootROM, needed for SMP on Armada XP - */ - { 0, 0xfff00000, SZ_1M, ARMADA_XP_TARGET_DEV_BUS, - ARMADA_XP_ATTR_DEV_BOOTROM, -1 }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 }, -}; - -static const struct __initdata orion_addr_map_info -armada_370_addr_map_info[] = { - /* End marker */ - { -1, 0, 0, 0, 0, 0 }, -}; - -static struct of_device_id of_addr_decoding_controller_table[] = { - { .compatible = "marvell,armada-addr-decoding-controller" }, - { /* end of list */ }, -}; - -static void __iomem * -armada_cfg_base(const struct orion_addr_map_cfg *cfg, int win) -{ - unsigned int offset; - - /* The register layout is a bit annoying and the below code - * tries to cope with it. - * - At offset 0x0, there are the registers for the first 8 - * windows, with 4 registers of 32 bits per window (ctrl, - * base, remap low, remap high) - * - Then at offset 0x80, there is a hole of 0x10 bytes for - * the internal registers base address and internal units - * sync barrier register. - * - Then at offset 0x90, there the registers for 12 - * windows, with only 2 registers of 32 bits per window - * (ctrl, base). - */ - if (win < 8) - offset = (win << 4); - else - offset = ARMADA_WINDOW_8_PLUS_OFFSET + ((win - 8) << 3); - - return cfg->bridge_virt_base + offset; -} - -static struct __initdata orion_addr_map_cfg addr_map_cfg = { - .num_wins = 20, - .remappable_wins = 8, - .win_cfg_base = armada_cfg_base, -}; - -static int __init armada_setup_cpu_mbus(void) -{ - struct device_node *np; - void __iomem *mbus_unit_addr_decoding_base; - void __iomem *sdram_addr_decoding_base; - - np = of_find_matching_node(NULL, of_addr_decoding_controller_table); - if (!np) - return -ENODEV; - - mbus_unit_addr_decoding_base = of_iomap(np, 0); - BUG_ON(!mbus_unit_addr_decoding_base); - - sdram_addr_decoding_base = - mbus_unit_addr_decoding_base + - ARMADA_SDRAM_ADDR_DECODING_OFFSET; - - addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base; - - if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric")) - addr_map_cfg.hw_io_coherency = 1; - - /* - * Disable, clear and configure windows. - */ - if (of_machine_is_compatible("marvell,armadaxp")) - orion_config_wins(&addr_map_cfg, armada_xp_addr_map_info); - else if (of_machine_is_compatible("marvell,armada370")) - orion_config_wins(&addr_map_cfg, armada_370_addr_map_info); - else { - pr_err("Unsupported SoC\n"); - return -EINVAL; - } - - /* - * Setup MBUS dram target info. - */ - orion_setup_cpu_mbus_target(&addr_map_cfg, - sdram_addr_decoding_base); - return 0; -} - -/* Using a early_initcall is needed so that this initialization gets - * done before the SMP initialization, which requires the BootROM to - * be remapped. */ -early_initcall(armada_setup_cpu_mbus); diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c index a5ea616d6d12..42a4cb3087e2 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.c +++ b/arch/arm/mach-mvebu/armada-370-xp.c @@ -19,6 +19,9 @@ #include <linux/time-armada-370-xp.h> #include <linux/clk/mvebu.h> #include <linux/dma-mapping.h> +#include <linux/mbus.h> +#include <linux/irqchip.h> +#include <asm/hardware/cache-l2x0.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -48,12 +51,33 @@ void __init armada_370_xp_timer_and_clk_init(void) void __init armada_370_xp_init_early(void) { + char *mbus_soc_name; + /* * Some Armada 370/XP devices allocate their coherent buffers * from atomic context. Increase size of atomic coherent pool * to make sure such the allocations won't fail. */ init_dma_coherent_pool_size(SZ_1M); + + /* + * This initialization will be replaced by a DT-based + * initialization once the mvebu-mbus driver gains DT support. + */ + if (of_machine_is_compatible("marvell,armada370")) + mbus_soc_name = "marvell,armada370-mbus"; + else + mbus_soc_name = "marvell,armadaxp-mbus"; + + mvebu_mbus_init(mbus_soc_name, + ARMADA_370_XP_MBUS_WINS_BASE, + ARMADA_370_XP_MBUS_WINS_SIZE, + ARMADA_370_XP_SDRAM_WINS_BASE, + ARMADA_370_XP_SDRAM_WINS_SIZE); + +#ifdef CONFIG_CACHE_L2X0 + l2x0_of_init(0, ~0UL); +#endif } static void __init armada_370_xp_dt_init(void) @@ -72,8 +96,7 @@ DT_MACHINE_START(ARMADA_XP_DT, "Marvell Armada 370/XP (Device Tree)") .init_machine = armada_370_xp_dt_init, .map_io = armada_370_xp_map_io, .init_early = armada_370_xp_init_early, - .init_irq = armada_370_xp_init_irq, - .handle_irq = armada_370_xp_handle_irq, + .init_irq = irqchip_init, .init_time = armada_370_xp_timer_and_clk_init, .restart = mvebu_restart, .dt_compat = armada_370_xp_dt_compat, diff --git a/arch/arm/mach-mvebu/armada-370-xp.h b/arch/arm/mach-mvebu/armada-370-xp.h index c6a7d74fddfe..2070e1b4f342 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.h +++ b/arch/arm/mach-mvebu/armada-370-xp.h @@ -16,9 +16,15 @@ #define __MACH_ARMADA_370_XP_H #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000 -#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfeb00000) +#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfec00000) #define ARMADA_370_XP_REGS_SIZE SZ_1M +/* These defines can go away once mvebu-mbus has a DT binding */ +#define ARMADA_370_XP_MBUS_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20000) +#define ARMADA_370_XP_MBUS_WINS_SIZE 0x100 +#define ARMADA_370_XP_SDRAM_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20180) +#define ARMADA_370_XP_SDRAM_WINS_SIZE 0x20 + #ifdef CONFIG_SMP #include <linux/cpumask.h> diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c deleted file mode 100644 index 830139a3e2ba..000000000000 --- a/arch/arm/mach-mvebu/irq-armada-370-xp.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Marvell Armada 370 and Armada XP SoC IRQ handling - * - * Copyright (C) 2012 Marvell - * - * Lior Amsalem <alior@marvell.com> - * Gregory CLEMENT <gregory.clement@free-electrons.com> - * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> - * Ben Dooks <ben.dooks@codethink.co.uk> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/irqdomain.h> -#include <asm/mach/arch.h> -#include <asm/exception.h> -#include <asm/smp_plat.h> -#include <asm/hardware/cache-l2x0.h> - -/* Interrupt Controller Registers Map */ -#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48) -#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C) - -#define ARMADA_370_XP_INT_CONTROL (0x00) -#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) -#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) -#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) - -#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) - -#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4) -#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc) -#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8) - -#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) - -#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ (5) - -#define ACTIVE_DOORBELLS (8) - -static DEFINE_RAW_SPINLOCK(irq_controller_lock); - -static void __iomem *per_cpu_int_base; -static void __iomem *main_int_base; -static struct irq_domain *armada_370_xp_mpic_domain; - -/* - * In SMP mode: - * For shared global interrupts, mask/unmask global enable bit - * For CPU interrupts, mask/unmask the calling CPU's bit - */ -static void armada_370_xp_irq_mask(struct irq_data *d) -{ - irq_hw_number_t hwirq = irqd_to_hwirq(d); - - if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) - writel(hwirq, main_int_base + - ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); - else - writel(hwirq, per_cpu_int_base + - ARMADA_370_XP_INT_SET_MASK_OFFS); -} - -static void armada_370_xp_irq_unmask(struct irq_data *d) -{ - irq_hw_number_t hwirq = irqd_to_hwirq(d); - - if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) - writel(hwirq, main_int_base + - ARMADA_370_XP_INT_SET_ENABLE_OFFS); - else - writel(hwirq, per_cpu_int_base + - ARMADA_370_XP_INT_CLEAR_MASK_OFFS); -} - -#ifdef CONFIG_SMP -static int armada_xp_set_affinity(struct irq_data *d, - const struct cpumask *mask_val, bool force) -{ - unsigned long reg; - unsigned long new_mask = 0; - unsigned long online_mask = 0; - unsigned long count = 0; - irq_hw_number_t hwirq = irqd_to_hwirq(d); - int cpu; - - for_each_cpu(cpu, mask_val) { - new_mask |= 1 << cpu_logical_map(cpu); - count++; - } - - /* - * Forbid mutlicore interrupt affinity - * This is required since the MPIC HW doesn't limit - * several CPUs from acknowledging the same interrupt. - */ - if (count > 1) - return -EINVAL; - - for_each_cpu(cpu, cpu_online_mask) - online_mask |= 1 << cpu_logical_map(cpu); - - raw_spin_lock(&irq_controller_lock); - - reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - reg = (reg & (~online_mask)) | new_mask; - writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); - - raw_spin_unlock(&irq_controller_lock); - - return 0; -} -#endif - -static struct irq_chip armada_370_xp_irq_chip = { - .name = "armada_370_xp_irq", - .irq_mask = armada_370_xp_irq_mask, - .irq_mask_ack = armada_370_xp_irq_mask, - .irq_unmask = armada_370_xp_irq_unmask, -#ifdef CONFIG_SMP - .irq_set_affinity = armada_xp_set_affinity, -#endif -}; - -static int armada_370_xp_mpic_irq_map(struct irq_domain *h, - unsigned int virq, irq_hw_number_t hw) -{ - armada_370_xp_irq_mask(irq_get_irq_data(virq)); - if (hw != ARMADA_370_XP_TIMER0_PER_CPU_IRQ) - writel(hw, per_cpu_int_base + - ARMADA_370_XP_INT_CLEAR_MASK_OFFS); - else - writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS); - irq_set_status_flags(virq, IRQ_LEVEL); - - if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) { - irq_set_percpu_devid(virq); - irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, - handle_percpu_devid_irq); - - } else { - irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, - handle_level_irq); - } - set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); - - return 0; -} - -#ifdef CONFIG_SMP -void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq) -{ - int cpu; - unsigned long map = 0; - - /* Convert our logical CPU mask into a physical one. */ - for_each_cpu(cpu, mask) - map |= 1 << cpu_logical_map(cpu); - - /* - * Ensure that stores to Normal memory are visible to the - * other CPUs before issuing the IPI. - */ - dsb(); - - /* submit softirq */ - writel((map << 8) | irq, main_int_base + - ARMADA_370_XP_SW_TRIG_INT_OFFS); -} - -void armada_xp_mpic_smp_cpu_init(void) -{ - /* Clear pending IPIs */ - writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); - - /* Enable first 8 IPIs */ - writel((1 << ACTIVE_DOORBELLS) - 1, per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_MSK_OFFS); - - /* Unmask IPI interrupt */ - writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); -} -#endif /* CONFIG_SMP */ - -static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { - .map = armada_370_xp_mpic_irq_map, - .xlate = irq_domain_xlate_onecell, -}; - -static int __init armada_370_xp_mpic_of_init(struct device_node *node, - struct device_node *parent) -{ - u32 control; - - main_int_base = of_iomap(node, 0); - per_cpu_int_base = of_iomap(node, 1); - - BUG_ON(!main_int_base); - BUG_ON(!per_cpu_int_base); - - control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL); - - armada_370_xp_mpic_domain = - irq_domain_add_linear(node, (control >> 2) & 0x3ff, - &armada_370_xp_mpic_irq_ops, NULL); - - if (!armada_370_xp_mpic_domain) - panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n"); - - irq_set_default_host(armada_370_xp_mpic_domain); - -#ifdef CONFIG_SMP - armada_xp_mpic_smp_cpu_init(); - - /* - * Set the default affinity from all CPUs to the boot cpu. - * This is required since the MPIC doesn't limit several CPUs - * from acknowledging the same interrupt. - */ - cpumask_clear(irq_default_affinity); - cpumask_set_cpu(smp_processor_id(), irq_default_affinity); - -#endif - - return 0; -} - -asmlinkage void __exception_irq_entry armada_370_xp_handle_irq(struct pt_regs - *regs) -{ - u32 irqstat, irqnr; - - do { - irqstat = readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_CPU_INTACK_OFFS); - irqnr = irqstat & 0x3FF; - - if (irqnr > 1022) - break; - - if (irqnr > 0) { - irqnr = irq_find_mapping(armada_370_xp_mpic_domain, - irqnr); - handle_IRQ(irqnr, regs); - continue; - } -#ifdef CONFIG_SMP - /* IPI Handling */ - if (irqnr == 0) { - u32 ipimask, ipinr; - - ipimask = readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) - & 0xFF; - - writel(0x0, per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); - - /* Handle all pending doorbells */ - for (ipinr = 0; ipinr < ACTIVE_DOORBELLS; ipinr++) { - if (ipimask & (0x1 << ipinr)) - handle_IPI(ipinr, regs); - } - continue; - } -#endif - - } while (1); -} - -static const struct of_device_id mpic_of_match[] __initconst = { - {.compatible = "marvell,mpic", .data = armada_370_xp_mpic_of_init}, - {}, -}; - -void __init armada_370_xp_init_irq(void) -{ - of_irq_init(mpic_of_match); -#ifdef CONFIG_CACHE_L2X0 - l2x0_of_init(0, ~0UL); -#endif -} diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index fe16aaf7c19c..875ea748391c 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -21,6 +21,7 @@ #include <linux/smp.h> #include <linux/clk.h> #include <linux/of.h> +#include <linux/mbus.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> #include "common.h" @@ -109,6 +110,7 @@ void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus) set_secondary_cpus_clock(); flush_cache_all(); set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); + mvebu_mbus_add_window("bootrom", 0xfff00000, SZ_1M); } struct smp_operations armada_xp_smp_ops __initdata = { diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index b5c1bdd3dcdf..5b62b6489d4b 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -22,7 +22,6 @@ #include <linux/irqchip.h> #include <linux/irqchip/mxs.h> #include <linux/micrel_phy.h> -#include <linux/mxsfb.h> #include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/phy.h> @@ -61,106 +60,6 @@ static inline void __mxs_togl(u32 mask, void __iomem *reg) __raw_writel(mask, reg + MXS_TOG_ADDR); } -static struct fb_videomode mx23evk_video_modes[] = { - { - .name = "Samsung-LMS430HF02", - .refresh = 60, - .xres = 480, - .yres = 272, - .pixclock = 108096, /* picosecond (9.2 MHz) */ - .left_margin = 15, - .right_margin = 8, - .upper_margin = 12, - .lower_margin = 4, - .hsync_len = 1, - .vsync_len = 1, - }, -}; - -static struct fb_videomode mx28evk_video_modes[] = { - { - .name = "Seiko-43WVF1G", - .refresh = 60, - .xres = 800, - .yres = 480, - .pixclock = 29851, /* picosecond (33.5 MHz) */ - .left_margin = 89, - .right_margin = 164, - .upper_margin = 23, - .lower_margin = 10, - .hsync_len = 10, - .vsync_len = 10, - }, -}; - -static struct fb_videomode m28evk_video_modes[] = { - { - .name = "Ampire AM-800480R2TMQW-T01H", - .refresh = 60, - .xres = 800, - .yres = 480, - .pixclock = 30066, /* picosecond (33.26 MHz) */ - .left_margin = 0, - .right_margin = 256, - .upper_margin = 0, - .lower_margin = 45, - .hsync_len = 1, - .vsync_len = 1, - }, -}; - -static struct fb_videomode apx4devkit_video_modes[] = { - { - .name = "HannStar PJ70112A", - .refresh = 60, - .xres = 800, - .yres = 480, - .pixclock = 33333, /* picosecond (30.00 MHz) */ - .left_margin = 88, - .right_margin = 40, - .upper_margin = 32, - .lower_margin = 13, - .hsync_len = 48, - .vsync_len = 3, - .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - }, -}; - -static struct fb_videomode apf28dev_video_modes[] = { - { - .name = "LW700", - .refresh = 60, - .xres = 800, - .yres = 480, - .pixclock = 30303, /* picosecond */ - .left_margin = 96, - .right_margin = 96, /* at least 3 & 1 */ - .upper_margin = 0x14, - .lower_margin = 0x15, - .hsync_len = 64, - .vsync_len = 4, - .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - }, -}; - -static struct fb_videomode cfa10049_video_modes[] = { - { - .name = "Himax HX8357-B", - .refresh = 60, - .xres = 320, - .yres = 480, - .pixclock = 108506, /* picosecond (9.216 MHz) */ - .left_margin = 2, - .right_margin = 2, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 15, - .vsync_len = 15, - }, -}; - -static struct mxsfb_platform_data mxsfb_pdata __initdata; - /* * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers */ @@ -191,8 +90,6 @@ static void mx28evk_flexcan1_switch(int enable) static struct flexcan_platform_data flexcan_pdata[2]; static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), - OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]), OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]), { /* sentinel */ } @@ -342,16 +239,6 @@ static void __init update_fec_mac_prop(enum mac_oui oui) } } -static void __init imx23_evk_init(void) -{ - mxsfb_pdata.mode_list = mx23evk_video_modes; - mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes); - mxsfb_pdata.default_bpp = 32; - mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; - mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | - MXSFB_SYNC_DOTCLK_FAILING_ACT; -} - static inline void enable_clk_enet_out(void) { struct clk *clk = clk_get_sys("enet_out", NULL); @@ -362,16 +249,8 @@ static inline void enable_clk_enet_out(void) static void __init imx28_evk_init(void) { - enable_clk_enet_out(); update_fec_mac_prop(OUI_FSL); - mxsfb_pdata.mode_list = mx28evk_video_modes; - mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); - mxsfb_pdata.default_bpp = 32; - mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; - mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | - MXSFB_SYNC_DOTCLK_FAILING_ACT; - mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); } @@ -384,20 +263,6 @@ static void __init imx28_evk_post_init(void) } } -static void __init m28evk_init(void) -{ - mxsfb_pdata.mode_list = m28evk_video_modes; - mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); - mxsfb_pdata.default_bpp = 16; - mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT; - mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; -} - -static void __init sc_sps1_init(void) -{ - enable_clk_enet_out(); -} - static int apx4devkit_phy_fixup(struct phy_device *phy) { phy->dev_flags |= MICREL_PHY_50MHZ_CLK; @@ -411,13 +276,6 @@ static void __init apx4devkit_init(void) if (IS_BUILTIN(CONFIG_PHYLIB)) phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, apx4devkit_phy_fixup); - - mxsfb_pdata.mode_list = apx4devkit_video_modes; - mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes); - mxsfb_pdata.default_bpp = 32; - mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; - mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | - MXSFB_SYNC_DOTCLK_FAILING_ACT; } #define ENET0_MDC__GPIO_4_0 MXS_GPIO_NR(4, 0) @@ -496,52 +354,24 @@ static void __init tx28_post_init(void) static void __init cfa10049_init(void) { - enable_clk_enet_out(); update_fec_mac_prop(OUI_CRYSTALFONTZ); - - mxsfb_pdata.mode_list = cfa10049_video_modes; - mxsfb_pdata.mode_count = ARRAY_SIZE(cfa10049_video_modes); - mxsfb_pdata.default_bpp = 32; - mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT; - mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; } static void __init cfa10037_init(void) { - enable_clk_enet_out(); update_fec_mac_prop(OUI_CRYSTALFONTZ); } -static void __init apf28_init(void) -{ - enable_clk_enet_out(); - - mxsfb_pdata.mode_list = apf28dev_video_modes; - mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes); - mxsfb_pdata.default_bpp = 16; - mxsfb_pdata.ld_intf_width = STMLCDIF_16BIT; - mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT | - MXSFB_SYNC_DOTCLK_FAILING_ACT; -} - static void __init mxs_machine_init(void) { if (of_machine_is_compatible("fsl,imx28-evk")) imx28_evk_init(); - else if (of_machine_is_compatible("fsl,imx23-evk")) - imx23_evk_init(); - else if (of_machine_is_compatible("denx,m28evk")) - m28evk_init(); else if (of_machine_is_compatible("bluegiga,apx4devkit")) apx4devkit_init(); else if (of_machine_is_compatible("crystalfontz,cfa10037")) cfa10037_init(); else if (of_machine_is_compatible("crystalfontz,cfa10049")) cfa10049_init(); - else if (of_machine_is_compatible("armadeus,imx28-apf28")) - apf28_init(); - else if (of_machine_is_compatible("schulercontrol,imx28-sps1")) - sc_sps1_init(); of_platform_populate(NULL, of_default_bus_match_table, mxs_auxdata_lookup, NULL); diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c index 1a4e887f028d..68ab858e27b7 100644 --- a/arch/arm/mach-omap1/dma.c +++ b/arch/arm/mach-omap1/dma.c @@ -301,7 +301,7 @@ static int __init omap1_system_dma_init(void) if (ret) { dev_err(&pdev->dev, "%s: Unable to add resources for %s%d\n", __func__, pdev->name, pdev->id); - goto exit_device_put; + goto exit_iounmap; } p = kzalloc(sizeof(struct omap_system_dma_plat_info), GFP_KERNEL); @@ -309,7 +309,7 @@ static int __init omap1_system_dma_init(void) dev_err(&pdev->dev, "%s: Unable to allocate 'p' for %s\n", __func__, pdev->name); ret = -ENOMEM; - goto exit_device_del; + goto exit_iounmap; } d = kzalloc(sizeof(struct omap_dma_dev_attr), GFP_KERNEL); @@ -402,8 +402,8 @@ exit_release_d: kfree(d); exit_release_p: kfree(p); -exit_device_del: - platform_device_del(pdev); +exit_iounmap: + iounmap(dma_base); exit_device_put: platform_device_put(pdev); diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 857b1f097fd8..f49cd51e162a 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -37,8 +37,6 @@ config ARCH_OMAP2PLUS_TYPICAL select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5 select PM_RUNTIME select REGULATOR - select SERIAL_OMAP - select SERIAL_OMAP_CONSOLE select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4 select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4 select VFP diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 62bb352c2d37..55a9d6777683 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -32,12 +32,12 @@ obj-$(CONFIG_SOC_HAS_OMAP2_SDRC) += sdrc.o # SMP support ONLY available for OMAP4 -obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o +smp-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o +smp-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o omap-4-5-common = omap4-common.o omap-wakeupgen.o \ sleep44xx.o -obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-common) -obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-common) +obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-common) $(smp-y) +obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-common) $(smp-y) plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec) diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 5b86423c89fa..244d8a5aa54b 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -108,24 +108,13 @@ static struct platform_device *sdp2430_devices[] __initdata = { #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 #define SDP2430_LCD_PANEL_ENABLE_GPIO 154 -static int sdp2430_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 1); - gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 1); - - return 0; -} - -static void sdp2430_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP2430_LCD_PANEL_ENABLE_GPIO, 0); - gpio_direction_output(SDP2430_LCD_PANEL_BACKLIGHT_GPIO, 0); -} - static struct panel_generic_dpi_data sdp2430_panel_data = { .name = "nec_nl2432dr22-11b", - .platform_enable = sdp2430_panel_enable_lcd, - .platform_disable = sdp2430_panel_disable_lcd, + .num_gpios = 2, + .gpios = { + SDP2430_LCD_PANEL_ENABLE_GPIO, + SDP2430_LCD_PANEL_BACKLIGHT_GPIO, + }, }; static struct omap_dss_device sdp2430_lcd_device = { @@ -146,26 +135,6 @@ static struct omap_dss_board_info sdp2430_dss_data = { .default_device = &sdp2430_lcd_device, }; -static void __init sdp2430_display_init(void) -{ - int r; - - static struct gpio gpios[] __initdata = { - { SDP2430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, - "LCD reset" }, - { SDP2430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, - "LCD Backlight" }, - }; - - r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); - if (r) { - pr_err("Cannot request LCD GPIOs, error %d\n", r); - return; - } - - omap_display_init(&sdp2430_dss_data); -} - #if IS_ENABLED(CONFIG_SMC91X) static struct omap_smc91x_platform_data board_smc91x_data = { @@ -273,7 +242,7 @@ static void __init omap_2430sdp_init(void) gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW, "Secondary LCD backlight"); - sdp2430_display_init(); + omap_display_init(&sdp2430_dss_data); } MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board") diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index a4d4664894e1..23b004afa3f8 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -108,53 +108,38 @@ static struct twl4030_keypad_data sdp3430_kp_data = { #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 #define SDP3430_LCD_PANEL_ENABLE_GPIO 5 -static struct gpio sdp3430_dss_gpios[] __initdata = { - {SDP3430_LCD_PANEL_ENABLE_GPIO, GPIOF_OUT_INIT_LOW, "LCD reset" }, - {SDP3430_LCD_PANEL_BACKLIGHT_GPIO, GPIOF_OUT_INIT_LOW, "LCD Backlight"}, -}; - static void __init sdp3430_display_init(void) { int r; - r = gpio_request_array(sdp3430_dss_gpios, - ARRAY_SIZE(sdp3430_dss_gpios)); + /* + * the backlight GPIO doesn't directly go to the panel, it enables + * an internal circuit on 3430sdp to create the signal V_BKL_28V, + * this is connected to LED+ pin of the sharp panel. This GPIO + * is left enabled in the board file, and not passed to the panel + * as platform_data. + */ + r = gpio_request_one(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, + GPIOF_OUT_INIT_HIGH, "LCD Backlight"); if (r) - printk(KERN_ERR "failed to get LCD control GPIOs\n"); - -} + pr_err("failed to get LCD Backlight GPIO\n"); -static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 1); - gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 1); - - return 0; -} - -static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_direction_output(SDP3430_LCD_PANEL_ENABLE_GPIO, 0); - gpio_direction_output(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, 0); -} - -static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev) -{ } +static struct panel_sharp_ls037v7dw01_data sdp3430_lcd_data = { + .resb_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO, + .ini_gpio = -1, + .mo_gpio = -1, + .lr_gpio = -1, + .ud_gpio = -1, +}; static struct omap_dss_device sdp3430_lcd_device = { .name = "lcd", .driver_name = "sharp_ls_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 16, - .platform_enable = sdp3430_panel_enable_lcd, - .platform_disable = sdp3430_panel_disable_lcd, + .data = &sdp3430_lcd_data, }; static struct tfp410_platform_data dvi_panel = { @@ -175,8 +160,6 @@ static struct omap_dss_device sdp3430_tv_device = { .driver_name = "venc", .type = OMAP_DISPLAY_TYPE_VENC, .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = sdp3430_panel_enable_tv, - .platform_disable = sdp3430_panel_disable_tv, }; diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 00d72902ef4f..56a9a4f855c7 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -730,7 +730,7 @@ static void __init omap_4430sdp_init(void) omap4_sdp4430_wifi_init(); omap4_twl6030_hsmmc_init(mmc); - usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto"); + usb_bind_phy("musb-hdrc.2.auto", 0, "omap-usb2.3.auto"); usb_musb_init(&musb_board_data); status = omap_ethernet_init(); diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index c29d2e743688..d63f14b534b5 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -120,63 +120,14 @@ static int __init am3517_evm_i2c_init(void) return 0; } -static int lcd_enabled; -static int dvi_enabled; - -#if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ - defined(CONFIG_PANEL_SHARP_LQ043T1DG01_MODULE) -static struct gpio am3517_evm_dss_gpios[] __initdata = { - /* GPIO 182 = LCD Backlight Power */ - { LCD_PANEL_BKLIGHT_PWR, GPIOF_OUT_INIT_HIGH, "lcd_backlight_pwr" }, - /* GPIO 181 = LCD Panel PWM */ - { LCD_PANEL_PWM, GPIOF_OUT_INIT_HIGH, "lcd bl enable" }, - /* GPIO 176 = LCD Panel Power enable pin */ - { LCD_PANEL_PWR, GPIOF_OUT_INIT_HIGH, "dvi enable" }, -}; - -static void __init am3517_evm_display_init(void) -{ - int r; - - omap_mux_init_gpio(LCD_PANEL_PWR, OMAP_PIN_INPUT_PULLUP); - omap_mux_init_gpio(LCD_PANEL_BKLIGHT_PWR, OMAP_PIN_INPUT_PULLDOWN); - omap_mux_init_gpio(LCD_PANEL_PWM, OMAP_PIN_INPUT_PULLDOWN); - - r = gpio_request_array(am3517_evm_dss_gpios, - ARRAY_SIZE(am3517_evm_dss_gpios)); - if (r) { - printk(KERN_ERR "failed to get DSS panel control GPIOs\n"); - return; - } - - printk(KERN_INFO "Display initialized successfully\n"); -} -#else -static void __init am3517_evm_display_init(void) {} -#endif - -static int am3517_evm_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - gpio_set_value(LCD_PANEL_PWR, 1); - lcd_enabled = 1; - - return 0; -} - -static void am3517_evm_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_set_value(LCD_PANEL_PWR, 0); - lcd_enabled = 0; -} - static struct panel_generic_dpi_data lcd_panel = { .name = "sharp_lq", - .platform_enable = am3517_evm_panel_enable_lcd, - .platform_disable = am3517_evm_panel_disable_lcd, + .num_gpios = 3, + .gpios = { + LCD_PANEL_PWR, + LCD_PANEL_BKLIGHT_PWR, + LCD_PANEL_PWM, + }, }; static struct omap_dss_device am3517_evm_lcd_device = { @@ -187,22 +138,11 @@ static struct omap_dss_device am3517_evm_lcd_device = { .phy.dpi.data_lines = 16, }; -static int am3517_evm_panel_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void am3517_evm_panel_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct omap_dss_device am3517_evm_tv_device = { .type = OMAP_DISPLAY_TYPE_VENC, .name = "tv", .driver_name = "venc", .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = am3517_evm_panel_enable_tv, - .platform_disable = am3517_evm_panel_disable_tv, }; static struct tfp410_platform_data dvi_panel = { @@ -365,8 +305,6 @@ static void __init am3517_evm_init(void) usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); usbhs_init(&usbhs_bdata); am3517_evm_hecc_init(&am3517_evm_hecc_pdata); - /* DSS */ - am3517_evm_display_init(); /* RTC - S35390A */ am3517_evm_rtc_init(); diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index e0ed8c07fc54..ee6218c74807 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -190,45 +190,12 @@ static inline void cm_t35_init_nand(void) {} #define CM_T35_LCD_BL_GPIO 58 #define CM_T35_DVI_EN_GPIO 54 -static int lcd_enabled; -static int dvi_enabled; - -static int cm_t35_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - - gpio_set_value(CM_T35_LCD_EN_GPIO, 1); - gpio_set_value(CM_T35_LCD_BL_GPIO, 1); - - lcd_enabled = 1; - - return 0; -} - -static void cm_t35_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - lcd_enabled = 0; - - gpio_set_value(CM_T35_LCD_BL_GPIO, 0); - gpio_set_value(CM_T35_LCD_EN_GPIO, 0); -} - -static int cm_t35_panel_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void cm_t35_panel_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct panel_generic_dpi_data lcd_panel = { .name = "toppoly_tdo35s", - .platform_enable = cm_t35_panel_enable_lcd, - .platform_disable = cm_t35_panel_disable_lcd, + .num_gpios = 1, + .gpios = { + CM_T35_LCD_BL_GPIO, + }, }; static struct omap_dss_device cm_t35_lcd_device = { @@ -257,8 +224,6 @@ static struct omap_dss_device cm_t35_tv_device = { .driver_name = "venc", .type = OMAP_DISPLAY_TYPE_VENC, .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = cm_t35_panel_enable_tv, - .platform_disable = cm_t35_panel_disable_tv, }; static struct omap_dss_device *cm_t35_dss_devices[] = { @@ -292,11 +257,6 @@ static struct spi_board_info cm_t35_lcd_spi_board_info[] __initdata = { }, }; -static struct gpio cm_t35_dss_gpios[] __initdata = { - { CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW, "lcd enable" }, - { CM_T35_LCD_BL_GPIO, GPIOF_OUT_INIT_LOW, "lcd bl enable" }, -}; - static void __init cm_t35_init_display(void) { int err; @@ -304,23 +264,21 @@ static void __init cm_t35_init_display(void) spi_register_board_info(cm_t35_lcd_spi_board_info, ARRAY_SIZE(cm_t35_lcd_spi_board_info)); - err = gpio_request_array(cm_t35_dss_gpios, - ARRAY_SIZE(cm_t35_dss_gpios)); + + err = gpio_request_one(CM_T35_LCD_EN_GPIO, GPIOF_OUT_INIT_LOW, + "lcd bl enable"); if (err) { - pr_err("CM-T35: failed to request DSS control GPIOs\n"); + pr_err("CM-T35: failed to request LCD EN GPIO\n"); return; } - gpio_export(CM_T35_LCD_EN_GPIO, 0); - gpio_export(CM_T35_LCD_BL_GPIO, 0); - msleep(50); gpio_set_value(CM_T35_LCD_EN_GPIO, 1); err = omap_display_init(&cm_t35_dss_data); if (err) { pr_err("CM-T35: failed to register DSS device\n"); - gpio_free_array(cm_t35_dss_gpios, ARRAY_SIZE(cm_t35_dss_gpios)); + gpio_free(CM_T35_LCD_EN_GPIO); } } diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index e44b804f75ae..576420544178 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -103,19 +103,6 @@ static struct omap2_hsmmc_info mmc[] = { {} /* Terminator */ }; -static int devkit8000_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(dssdev->reset_gpio)) - gpio_set_value_cansleep(dssdev->reset_gpio, 1); - return 0; -} - -static void devkit8000_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(dssdev->reset_gpio)) - gpio_set_value_cansleep(dssdev->reset_gpio, 0); -} - static struct regulator_consumer_supply devkit8000_vmmc1_supply[] = { REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), }; @@ -127,8 +114,7 @@ static struct regulator_consumer_supply devkit8000_vio_supply[] = { static struct panel_generic_dpi_data lcd_panel = { .name = "innolux_at070tn83", - .platform_enable = devkit8000_panel_enable_lcd, - .platform_disable = devkit8000_panel_disable_lcd, + /* gpios filled in code */ }; static struct omap_dss_device devkit8000_lcd_device = { @@ -210,8 +196,6 @@ static struct gpio_led gpio_leds[]; static int devkit8000_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int ret; - /* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0].gpio_cd = gpio + 0; omap_hsmmc_late_init(mmc); @@ -220,13 +204,8 @@ static int devkit8000_twl_gpio_setup(struct device *dev, gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; /* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */ - devkit8000_lcd_device.reset_gpio = gpio + TWL4030_GPIO_MAX + 0; - ret = gpio_request_one(devkit8000_lcd_device.reset_gpio, - GPIOF_OUT_INIT_LOW, "LCD_PWREN"); - if (ret < 0) { - devkit8000_lcd_device.reset_gpio = -EINVAL; - printk(KERN_ERR "Failed to request GPIO for LCD_PWRN\n"); - } + lcd_panel.num_gpios = 1; + lcd_panel.gpios[0] = gpio + TWL4030_GPIO_MAX + 0; /* gpio + 7 is "DVI_PD" (out, active low) */ dvi_panel.power_down_gpio = gpio + 7; diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 78813b397209..88aa6b1835c3 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -110,6 +110,7 @@ MACHINE_END static const char *omap3_gp_boards_compat[] __initdata = { "ti,omap3-beagle", + "timll,omap3-devkit8000", NULL, }; diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 8a8e505a0e90..d0d17bc58d9b 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -181,34 +181,13 @@ static inline void __init ldp_init_smsc911x(void) /* LCD */ -static int ldp_backlight_gpio; -static int ldp_lcd_enable_gpio; - #define LCD_PANEL_RESET_GPIO 55 #define LCD_PANEL_QVGA_GPIO 56 -static int ldp_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(ldp_lcd_enable_gpio)) - gpio_direction_output(ldp_lcd_enable_gpio, 1); - if (gpio_is_valid(ldp_backlight_gpio)) - gpio_direction_output(ldp_backlight_gpio, 1); - - return 0; -} - -static void ldp_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - if (gpio_is_valid(ldp_lcd_enable_gpio)) - gpio_direction_output(ldp_lcd_enable_gpio, 0); - if (gpio_is_valid(ldp_backlight_gpio)) - gpio_direction_output(ldp_backlight_gpio, 0); -} - static struct panel_generic_dpi_data ldp_panel_data = { .name = "nec_nl2432dr22-11b", - .platform_enable = ldp_panel_enable_lcd, - .platform_disable = ldp_panel_disable_lcd, + .num_gpios = 4, + /* gpios filled in code */ }; static struct omap_dss_device ldp_lcd_device = { @@ -231,41 +210,19 @@ static struct omap_dss_board_info ldp_dss_data = { static void __init ldp_display_init(void) { - int r; - - static struct gpio gpios[] __initdata = { - {LCD_PANEL_RESET_GPIO, GPIOF_OUT_INIT_HIGH, "LCD RESET"}, - {LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "LCD QVGA"}, - }; - - r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); - if (r) { - pr_err("Cannot request LCD GPIOs, error %d\n", r); - return; - } + ldp_panel_data.gpios[2] = LCD_PANEL_RESET_GPIO; + ldp_panel_data.gpios[3] = LCD_PANEL_QVGA_GPIO; omap_display_init(&ldp_dss_data); } static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { - int r; - - struct gpio gpios[] = { - {gpio + 7 , GPIOF_OUT_INIT_LOW, "LCD ENABLE"}, - {gpio + 15, GPIOF_OUT_INIT_LOW, "LCD BACKLIGHT"}, - }; - - r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); - if (r) { - pr_err("Cannot request LCD GPIOs, error %d\n", r); - ldp_backlight_gpio = -EINVAL; - ldp_lcd_enable_gpio = -EINVAL; - return r; - } - - ldp_backlight_gpio = gpio + 15; - ldp_lcd_enable_gpio = gpio + 7; + ldp_panel_data.gpios[0] = gpio + 7; + ldp_panel_data.gpio_invert[0] = true; + + ldp_panel_data.gpios[1] = gpio + 15; + ldp_panel_data.gpio_invert[1] = true; return 0; } diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 6de78605c0af..04c116555412 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -112,13 +112,13 @@ static u8 omap3_beagle_version; */ static struct { int mmc1_gpio_wp; - int usb_pwr_level; + bool usb_pwr_level; /* 0 - Active Low, 1 - Active High */ int dvi_pd_gpio; int usr_button_gpio; int mmc_caps; } beagle_config = { .mmc1_gpio_wp = -EINVAL, - .usb_pwr_level = GPIOF_OUT_INIT_LOW, + .usb_pwr_level = 0, .dvi_pd_gpio = -EINVAL, .usr_button_gpio = 4, .mmc_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, @@ -178,7 +178,7 @@ static void __init omap3_beagle_init_rev(void) case 0: printk(KERN_INFO "OMAP3 Beagle Rev: xM Ax/Bx\n"); omap3_beagle_version = OMAP3BEAGLE_BOARD_XM; - beagle_config.usb_pwr_level = GPIOF_OUT_INIT_HIGH; + beagle_config.usb_pwr_level = 1; beagle_config.mmc_caps &= ~MMC_CAP_8_BIT_DATA; break; case 2: diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 4f1bbc3cc29b..f76d0de7b406 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -155,61 +155,43 @@ static inline void __init omap3evm_init_smsc911x(void) { return; } #define OMAP3EVM_LCD_PANEL_LR 2 #define OMAP3EVM_LCD_PANEL_UD 3 #define OMAP3EVM_LCD_PANEL_INI 152 -#define OMAP3EVM_LCD_PANEL_ENVDD 153 #define OMAP3EVM_LCD_PANEL_QVGA 154 #define OMAP3EVM_LCD_PANEL_RESB 155 + +#define OMAP3EVM_LCD_PANEL_ENVDD 153 #define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO 210 + +/* + * OMAP3EVM DVI control signals + */ #define OMAP3EVM_DVI_PANEL_EN_GPIO 199 -static struct gpio omap3_evm_dss_gpios[] __initdata = { - { OMAP3EVM_LCD_PANEL_RESB, GPIOF_OUT_INIT_HIGH, "lcd_panel_resb" }, - { OMAP3EVM_LCD_PANEL_INI, GPIOF_OUT_INIT_HIGH, "lcd_panel_ini" }, - { OMAP3EVM_LCD_PANEL_QVGA, GPIOF_OUT_INIT_LOW, "lcd_panel_qvga" }, - { OMAP3EVM_LCD_PANEL_LR, GPIOF_OUT_INIT_HIGH, "lcd_panel_lr" }, - { OMAP3EVM_LCD_PANEL_UD, GPIOF_OUT_INIT_HIGH, "lcd_panel_ud" }, - { OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW, "lcd_panel_envdd" }, +static struct panel_sharp_ls037v7dw01_data omap3_evm_lcd_data = { + .resb_gpio = OMAP3EVM_LCD_PANEL_RESB, + .ini_gpio = OMAP3EVM_LCD_PANEL_INI, + .mo_gpio = OMAP3EVM_LCD_PANEL_QVGA, + .lr_gpio = OMAP3EVM_LCD_PANEL_LR, + .ud_gpio = OMAP3EVM_LCD_PANEL_UD, }; -static int lcd_enabled; -static int dvi_enabled; - static void __init omap3_evm_display_init(void) { int r; - r = gpio_request_array(omap3_evm_dss_gpios, - ARRAY_SIZE(omap3_evm_dss_gpios)); + r = gpio_request_one(OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW, + "lcd_panel_envdd"); if (r) - printk(KERN_ERR "failed to get lcd_panel_* gpios\n"); -} + pr_err("failed to get lcd_panel_envdd GPIO\n"); -static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0); + r = gpio_request_one(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, + GPIOF_OUT_INIT_LOW, "lcd_panel_bklight"); + if (r) + pr_err("failed to get lcd_panel_bklight GPIO\n"); if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); else gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); - - lcd_enabled = 1; - return 0; -} - -static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1); - - if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) - gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); - else - gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); - - lcd_enabled = 0; } static struct omap_dss_device omap3_evm_lcd_device = { @@ -217,26 +199,14 @@ static struct omap_dss_device omap3_evm_lcd_device = { .driver_name = "sharp_ls_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 18, - .platform_enable = omap3_evm_enable_lcd, - .platform_disable = omap3_evm_disable_lcd, + .data = &omap3_evm_lcd_data, }; -static int omap3_evm_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void omap3_evm_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct omap_dss_device omap3_evm_tv_device = { .name = "tv", .driver_name = "venc", .type = OMAP_DISPLAY_TYPE_VENC, .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, - .platform_enable = omap3_evm_enable_tv, - .platform_disable = omap3_evm_disable_tv, }; static struct tfp410_platform_data dvi_panel = { diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 1004d2aaa68f..28133d5b4fed 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -44,6 +44,7 @@ #include "common.h" #include <video/omapdss.h> +#include <video/omap-panel-data.h> #include <linux/platform_data/mtd-nand-omap2.h> #include "mux.h" @@ -230,12 +231,16 @@ static struct twl4030_keypad_data pandora_kp_data = { .rep = 1, }; +static struct panel_tpo_td043_data lcd_data = { + .nreset_gpio = 157, +}; + static struct omap_dss_device pandora_lcd_device = { .name = "lcd", .driver_name = "tpo_td043mtea1_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 24, - .reset_gpio = 157, + .data = &lcd_data, }; static struct omap_dss_device pandora_tv_device = { diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c index 8afbba0923d6..d37e6b187ae4 100644 --- a/arch/arm/mach-omap2/board-omap3stalker.c +++ b/arch/arm/mach-omap2/board-omap3stalker.c @@ -94,15 +94,6 @@ static void __init omap3_stalker_display_init(void) return; } -static int omap3_stalker_enable_tv(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void omap3_stalker_disable_tv(struct omap_dss_device *dssdev) -{ -} - static struct omap_dss_device omap3_stalker_tv_device = { .name = "tv", .driver_name = "venc", @@ -112,8 +103,6 @@ static struct omap_dss_device omap3_stalker_tv_device = { #elif defined(CONFIG_OMAP2_VENC_OUT_TYPE_COMPOSITE) .u.venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE, #endif - .platform_enable = omap3_stalker_enable_tv, - .platform_disable = omap3_stalker_disable_tv, }; static struct tfp410_platform_data dvi_panel = { diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index a71ad345f20d..1e2c75eee912 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -435,7 +435,7 @@ static void __init omap4_panda_init(void) omap_sdrc_init(NULL, NULL); omap4_twl6030_hsmmc_init(mmc); omap4_ehci_init(); - usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto"); + usb_bind_phy("musb-hdrc.2.auto", 0, "omap-usb2.3.auto"); usb_musb_init(&musb_board_data); omap4_panda_display_init(); } diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index f9101407cd56..4ca6b680aa72 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -145,28 +145,9 @@ static inline void __init overo_init_smsc911x(void) { return; } #endif /* DSS */ -static int lcd_enabled; -static int dvi_enabled; - #define OVERO_GPIO_LCD_EN 144 #define OVERO_GPIO_LCD_BL 145 -static struct gpio overo_dss_gpios[] __initdata = { - { OVERO_GPIO_LCD_EN, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_EN" }, - { OVERO_GPIO_LCD_BL, GPIOF_OUT_INIT_HIGH, "OVERO_GPIO_LCD_BL" }, -}; - -static void __init overo_display_init(void) -{ - if (gpio_request_array(overo_dss_gpios, ARRAY_SIZE(overo_dss_gpios))) { - printk(KERN_ERR "could not obtain DSS control GPIOs\n"); - return; - } - - gpio_export(OVERO_GPIO_LCD_EN, 0); - gpio_export(OVERO_GPIO_LCD_BL, 0); -} - static struct tfp410_platform_data dvi_panel = { .i2c_bus_num = 3, .power_down_gpio = -1, @@ -187,30 +168,13 @@ static struct omap_dss_device overo_tv_device = { .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, }; -static int overo_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - if (dvi_enabled) { - printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); - return -EINVAL; - } - - gpio_set_value(OVERO_GPIO_LCD_EN, 1); - gpio_set_value(OVERO_GPIO_LCD_BL, 1); - lcd_enabled = 1; - return 0; -} - -static void overo_panel_disable_lcd(struct omap_dss_device *dssdev) -{ - gpio_set_value(OVERO_GPIO_LCD_EN, 0); - gpio_set_value(OVERO_GPIO_LCD_BL, 0); - lcd_enabled = 0; -} - static struct panel_generic_dpi_data lcd43_panel = { .name = "samsung_lte430wq_f0c", - .platform_enable = overo_panel_enable_lcd, - .platform_disable = overo_panel_disable_lcd, + .num_gpios = 2, + .gpios = { + OVERO_GPIO_LCD_EN, + OVERO_GPIO_LCD_BL + }, }; static struct omap_dss_device overo_lcd43_device = { @@ -223,13 +187,20 @@ static struct omap_dss_device overo_lcd43_device = { #if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \ defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE) +static struct panel_generic_dpi_data lcd35_panel = { + .num_gpios = 2, + .gpios = { + OVERO_GPIO_LCD_EN, + OVERO_GPIO_LCD_BL + }, +}; + static struct omap_dss_device overo_lcd35_device = { .type = OMAP_DISPLAY_TYPE_DPI, .name = "lcd35", .driver_name = "lgphilips_lb035q02_panel", .phy.dpi.data_lines = 24, - .platform_enable = overo_panel_enable_lcd, - .platform_disable = overo_panel_disable_lcd, + .data = &lcd35_panel, }; #endif @@ -508,7 +479,6 @@ static void __init overo_init(void) usbhs_init(&usbhs_bdata); overo_spi_init(); overo_init_smsc911x(); - overo_display_init(); overo_init_led(); overo_init_keys(); omap_twl4030_audio_init("overo", NULL); diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 1a884670a6c4..18ca61e300b3 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -73,11 +73,11 @@ #define LIS302_IRQ1_GPIO 181 #define LIS302_IRQ2_GPIO 180 /* Not yet in use */ -/* list all spi devices here */ +/* List all SPI devices here. Note that the list/probe order seems to matter! */ enum { RX51_SPI_WL1251, - RX51_SPI_MIPID, /* LCD panel */ RX51_SPI_TSC2005, /* Touch Controller */ + RX51_SPI_MIPID, /* LCD panel */ }; static struct wl12xx_platform_data wl1251_pdata; diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c index eb667261df08..bd74f9f6063b 100644 --- a/arch/arm/mach-omap2/board-rx51-video.c +++ b/arch/arm/mach-omap2/board-rx51-video.c @@ -16,6 +16,8 @@ #include <linux/mm.h> #include <asm/mach-types.h> #include <video/omapdss.h> +#include <video/omap-panel-data.h> + #include <linux/platform_data/spi-omap2-mcspi.h> #include "soc.h" @@ -27,25 +29,16 @@ #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) -static int rx51_lcd_enable(struct omap_dss_device *dssdev) -{ - gpio_set_value(dssdev->reset_gpio, 1); - return 0; -} - -static void rx51_lcd_disable(struct omap_dss_device *dssdev) -{ - gpio_set_value(dssdev->reset_gpio, 0); -} +static struct panel_acx565akm_data lcd_data = { + .reset_gpio = RX51_LCD_RESET_GPIO, +}; static struct omap_dss_device rx51_lcd_device = { .name = "lcd", .driver_name = "panel-acx565akm", .type = OMAP_DISPLAY_TYPE_SDI, .phy.sdi.datapairs = 2, - .reset_gpio = RX51_LCD_RESET_GPIO, - .platform_enable = rx51_lcd_enable, - .platform_disable = rx51_lcd_disable, + .data = &lcd_data, }; static struct omap_dss_device rx51_tv_device = { @@ -76,13 +69,8 @@ static int __init rx51_video_init(void) return 0; } - if (gpio_request_one(RX51_LCD_RESET_GPIO, GPIOF_OUT_INIT_HIGH, - "LCD ACX565AKM reset")) { - pr_err("%s failed to get LCD Reset GPIO\n", __func__); - return 0; - } - omap_display_init(&rx51_dss_board_info); + return 0; } diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c index 9a7174faac51..c2a079cb76fc 100644 --- a/arch/arm/mach-omap2/board-zoom-display.c +++ b/arch/arm/mach-omap2/board-zoom-display.c @@ -15,8 +15,9 @@ #include <linux/spi/spi.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <video/omapdss.h> -#include "board-zoom.h" +#include <video/omap-panel-data.h> +#include "board-zoom.h" #include "soc.h" #include "common.h" @@ -24,37 +25,17 @@ #define LCD_PANEL_RESET_GPIO_PILOT 55 #define LCD_PANEL_QVGA_GPIO 56 -static struct gpio zoom_lcd_gpios[] __initdata = { - { -EINVAL, GPIOF_OUT_INIT_HIGH, "lcd reset" }, - { LCD_PANEL_QVGA_GPIO, GPIOF_OUT_INIT_HIGH, "lcd qvga" }, +static struct panel_nec_nl8048_data zoom_lcd_data = { + /* res_gpio filled in code */ + .qvga_gpio = LCD_PANEL_QVGA_GPIO, }; -static void __init zoom_lcd_panel_init(void) -{ - zoom_lcd_gpios[0].gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? - LCD_PANEL_RESET_GPIO_PROD : - LCD_PANEL_RESET_GPIO_PILOT; - - if (gpio_request_array(zoom_lcd_gpios, ARRAY_SIZE(zoom_lcd_gpios))) - pr_err("%s: Failed to get LCD GPIOs.\n", __func__); -} - -static int zoom_panel_enable_lcd(struct omap_dss_device *dssdev) -{ - return 0; -} - -static void zoom_panel_disable_lcd(struct omap_dss_device *dssdev) -{ -} - static struct omap_dss_device zoom_lcd_device = { .name = "lcd", .driver_name = "NEC_8048_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 24, - .platform_enable = zoom_panel_enable_lcd, - .platform_disable = zoom_panel_disable_lcd, + .data = &zoom_lcd_data, }; static struct omap_dss_device *zoom_dss_devices[] = { @@ -67,6 +48,13 @@ static struct omap_dss_board_info zoom_dss_data = { .default_device = &zoom_lcd_device, }; +static void __init zoom_lcd_panel_init(void) +{ + zoom_lcd_data.res_gpio = (omap_rev() > OMAP3430_REV_ES3_0) ? + LCD_PANEL_RESET_GPIO_PROD : + LCD_PANEL_RESET_GPIO_PILOT; +} + static struct omap2_mcspi_device_config dss_lcd_mcspi_config = { .turbo_mode = 1, }; diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index dab9fc014b97..49fd0d501c9b 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -28,6 +28,7 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/dma-mapping.h> +#include <linux/of.h> #include <linux/omap-dma.h> #include "soc.h" @@ -304,6 +305,9 @@ static int __init omap2_system_dma_init(void) if (res) return res; + if (of_have_populated_dt()) + return res; + pdev = platform_device_register_full(&omap_dma_dev_info); if (IS_ERR(pdev)) return PTR_ERR(pdev); diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c index 9c49bbe825f7..393aeefaebb0 100644 --- a/arch/arm/mach-omap2/dss-common.c +++ b/arch/arm/mach-omap2/dss-common.c @@ -52,7 +52,6 @@ static struct omap_dss_device omap4_panda_dvi_device = { .driver_name = "tfp410", .data = &omap4_dvi_panel, .phy.dpi.data_lines = 24, - .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, .channel = OMAP_DSS_CHANNEL_LCD2, }; @@ -177,45 +176,12 @@ static struct picodlp_panel_data sdp4430_picodlp_pdata = { .pwrgood_gpio = 45, }; -static void sdp4430_picodlp_init(void) -{ - int r; - const struct gpio picodlp_gpios[] = { - {DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, - "DLP POWER ON"}, - {sdp4430_picodlp_pdata.emu_done_gpio, GPIOF_IN, - "DLP EMU DONE"}, - {sdp4430_picodlp_pdata.pwrgood_gpio, GPIOF_OUT_INIT_LOW, - "DLP PWRGOOD"}, - }; - - r = gpio_request_array(picodlp_gpios, ARRAY_SIZE(picodlp_gpios)); - if (r) - pr_err("Cannot request PicoDLP GPIOs, error %d\n", r); -} - -static int sdp4430_panel_enable_picodlp(struct omap_dss_device *dssdev) -{ - gpio_set_value(DISPLAY_SEL_GPIO, 0); - gpio_set_value(DLP_POWER_ON_GPIO, 1); - - return 0; -} - -static void sdp4430_panel_disable_picodlp(struct omap_dss_device *dssdev) -{ - gpio_set_value(DLP_POWER_ON_GPIO, 0); - gpio_set_value(DISPLAY_SEL_GPIO, 1); -} - static struct omap_dss_device sdp4430_picodlp_device = { .name = "picodlp", .driver_name = "picodlp_panel", .type = OMAP_DISPLAY_TYPE_DPI, .phy.dpi.data_lines = 24, .channel = OMAP_DSS_CHANNEL_LCD2, - .platform_enable = sdp4430_panel_enable_picodlp, - .platform_disable = sdp4430_panel_disable_picodlp, .data = &sdp4430_picodlp_pdata, }; @@ -232,17 +198,26 @@ static struct omap_dss_board_info sdp4430_dss_data = { .default_device = &sdp4430_lcd_device, }; +/* + * we select LCD2 by default (instead of Pico DLP) by setting DISPLAY_SEL_GPIO. + * Setting DLP_POWER_ON gpio enables the VDLP_2V5 VDLP_1V8 and VDLP_1V0 rails + * used by picodlp on the 4430sdp platform. Keep this gpio disabled as LCD2 is + * selected by default + */ void __init omap_4430sdp_display_init(void) { int r; - /* Enable LCD2 by default (instead of Pico DLP) */ r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH, "display_sel"); if (r) pr_err("%s: Could not get display_sel GPIO\n", __func__); - sdp4430_picodlp_init(); + r = gpio_request_one(DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, + "DLP POWER ON"); + if (r) + pr_err("%s: Could not get DLP POWER ON GPIO\n", __func__); + omap_display_init(&sdp4430_dss_data); /* * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and @@ -262,12 +237,15 @@ void __init omap_4430sdp_display_init_of(void) { int r; - /* Enable LCD2 by default (instead of Pico DLP) */ r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH, "display_sel"); if (r) pr_err("%s: Could not get display_sel GPIO\n", __func__); - sdp4430_picodlp_init(); + r = gpio_request_one(DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, + "DLP POWER ON"); + if (r) + pr_err("%s: Could not get DLP POWER ON GPIO\n", __func__); + omap_display_init(&sdp4430_dss_data); } diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index ed946df5ad8a..6c4da1254f53 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1520,36 +1520,22 @@ static int gpmc_probe_dt(struct platform_device *pdev) return ret; } - for_each_node_by_name(child, "nand") { - ret = gpmc_probe_nand_child(pdev, child); - if (ret < 0) { - of_node_put(child); - return ret; - } - } + for_each_child_of_node(pdev->dev.of_node, child) { - for_each_node_by_name(child, "onenand") { - ret = gpmc_probe_onenand_child(pdev, child); - if (ret < 0) { - of_node_put(child); - return ret; - } - } + if (!child->name) + continue; - for_each_node_by_name(child, "nor") { - ret = gpmc_probe_generic_child(pdev, child); - if (ret < 0) { - of_node_put(child); - return ret; - } - } + if (of_node_cmp(child->name, "nand") == 0) + ret = gpmc_probe_nand_child(pdev, child); + else if (of_node_cmp(child->name, "onenand") == 0) + ret = gpmc_probe_onenand_child(pdev, child); + else if (of_node_cmp(child->name, "ethernet") == 0 || + of_node_cmp(child->name, "nor") == 0) + ret = gpmc_probe_generic_child(pdev, child); - for_each_node_by_name(child, "ethernet") { - ret = gpmc_probe_generic_child(pdev, child); - if (ret < 0) { + if (WARN(ret < 0, "%s: probing gpmc child %s failed\n", + __func__, child->full_name)) of_node_put(child); - return ret; - } } return 0; diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 0f4c18e6e60c..1272c41d4749 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -419,11 +419,15 @@ void __init omap3xxx_check_revision(void) cpu_rev = "1.0"; break; case 1: - /* FALLTHROUGH */ - default: omap_revision = AM335X_REV_ES2_0; cpu_rev = "2.0"; break; + case 2: + /* FALLTHROUGH */ + default: + omap_revision = AM335X_REV_ES2_1; + cpu_rev = "2.1"; + break; } break; case 0xb8f2: @@ -644,13 +648,12 @@ void __init omap_soc_device_init(void) soc_dev_attr->revision = soc_rev; soc_dev = soc_device_register(soc_dev_attr); - if (IS_ERR_OR_NULL(soc_dev)) { + if (IS_ERR(soc_dev)) { kfree(soc_dev_attr); return; } parent = soc_device_to_device(soc_dev); - if (!IS_ERR_OR_NULL(parent)) - device_create_file(parent, &omap_soc_attr); + device_create_file(parent, &omap_soc_attr); } #endif /* CONFIG_SOC_BUS */ diff --git a/arch/arm/mach-omap2/mux34xx.h b/arch/arm/mach-omap2/mux34xx.h index 6543ebf8ecfc..3f26d297c082 100644 --- a/arch/arm/mach-omap2/mux34xx.h +++ b/arch/arm/mach-omap2/mux34xx.h @@ -393,6 +393,10 @@ #define OMAP3_CONTROL_PADCONF_SAD2D_SWAKEUP_OFFSET 0xa1c #define OMAP3_CONTROL_PADCONF_JTAG_RTCK_OFFSET 0xa1e #define OMAP3_CONTROL_PADCONF_JTAG_TDO_OFFSET 0xa20 +#define OMAP3_CONTROL_PADCONF_GPIO_127 0xa24 +#define OMAP3_CONTROL_PADCONF_GPIO_126 0xa26 +#define OMAP3_CONTROL_PADCONF_GPIO_128 0xa28 +#define OMAP3_CONTROL_PADCONF_GPIO_129 0xa2a #define OMAP3_CONTROL_PADCONF_MUX_SIZE \ - (OMAP3_CONTROL_PADCONF_JTAG_TDO_OFFSET + 0x2) + (OMAP3_CONTROL_PADCONF_GPIO_129 + 0x2) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index eeea4fa28fbc..e6d230700b2b 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -876,4 +876,4 @@ static int __init omap_device_late_init(void) bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle); return 0; } -omap_late_initcall(omap_device_late_init); +omap_late_initcall_sync(omap_device_late_init); diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 93f213b6a784..d25a95fe9921 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -139,6 +139,8 @@ #include <linux/slab.h> #include <linux/bootmem.h> #include <linux/cpu.h> +#include <linux/of.h> +#include <linux/of_address.h> #include <asm/system_misc.h> @@ -2350,6 +2352,34 @@ static int _shutdown(struct omap_hwmod *oh) } /** + * of_dev_hwmod_lookup - look up needed hwmod from dt blob + * @np: struct device_node * + * @oh: struct omap_hwmod * + * + * Parse the dt blob and find out needed hwmod. Recursive function is + * implemented to take care hierarchical dt blob parsing. + * Return: The device node on success or NULL on failure. + */ +static struct device_node *of_dev_hwmod_lookup(struct device_node *np, + struct omap_hwmod *oh) +{ + struct device_node *np0 = NULL, *np1 = NULL; + const char *p; + + for_each_child_of_node(np, np0) { + if (of_find_property(np0, "ti,hwmods", NULL)) { + p = of_get_property(np0, "ti,hwmods", NULL); + if (!strcmp(p, oh->name)) + return np0; + np1 = of_dev_hwmod_lookup(np0, oh); + if (np1) + return np1; + } + } + return NULL; +} + +/** * _init_mpu_rt_base - populate the virtual address for a hwmod * @oh: struct omap_hwmod * to locate the virtual address * @@ -2361,7 +2391,8 @@ static int _shutdown(struct omap_hwmod *oh) static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data) { struct omap_hwmod_addr_space *mem; - void __iomem *va_start; + void __iomem *va_start = NULL; + struct device_node *np; if (!oh) return; @@ -2375,10 +2406,18 @@ static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data) if (!mem) { pr_debug("omap_hwmod: %s: no MPU register target found\n", oh->name); - return; + + /* Extract the IO space from device tree blob */ + if (!of_have_populated_dt()) + return; + + np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); + if (np) + va_start = of_iomap(np, 0); + } else { + va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); } - va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); if (!va_start) { pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name); return; @@ -2410,7 +2449,8 @@ static int __init _init(struct omap_hwmod *oh, void *data) if (oh->_state != _HWMOD_STATE_REGISTERED) return 0; - _init_mpu_rt_base(oh, NULL); + if (oh->class->sysc) + _init_mpu_rt_base(oh, NULL); r = _init_clocks(oh, NULL); if (r < 0) { diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c index 9debf822687c..9ace8eae7ee8 100644 --- a/arch/arm/mach-omap2/pmu.c +++ b/arch/arm/mach-omap2/pmu.c @@ -11,6 +11,8 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ +#include <linux/of.h> + #include <asm/pmu.h> #include "soc.h" @@ -63,6 +65,15 @@ static int __init omap_init_pmu(void) unsigned oh_num; char **oh_names; + /* XXX Remove this check when the CTI driver is available */ + if (cpu_is_omap443x()) { + pr_info("ARM PMU: not yet supported on OMAP4430 due to missing CTI driver\n"); + return 0; + } + + if (of_have_populated_dt()) + return 0; + /* * To create an ARM-PMU device the following HWMODs * are required for the various OMAP2+ devices. @@ -75,9 +86,6 @@ static int __init omap_init_pmu(void) if (cpu_is_omap443x()) { oh_num = ARRAY_SIZE(omap4430_pmu_oh_names); oh_names = omap4430_pmu_oh_names; - /* XXX Remove the next two lines when CTI driver available */ - pr_info("ARM PMU: not yet supported on OMAP4430 due to missing CTI driver\n"); - return 0; } else if (cpu_is_omap34xx() || cpu_is_omap44xx()) { oh_num = ARRAY_SIZE(omap3_pmu_oh_names); oh_names = omap3_pmu_oh_names; diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h index 18fdeeb3a44a..197cc16870d9 100644 --- a/arch/arm/mach-omap2/soc.h +++ b/arch/arm/mach-omap2/soc.h @@ -396,6 +396,7 @@ IS_OMAP_TYPE(3430, 0x3430) #define AM335X_CLASS 0x33500033 #define AM335X_REV_ES1_0 AM335X_CLASS #define AM335X_REV_ES2_0 (AM335X_CLASS | (0x1 << 8)) +#define AM335X_REV_ES2_1 (AM335X_CLASS | (0x2 << 8)) #define OMAP443X_CLASS 0x44300044 #define OMAP4430_REV_ES1_0 (OMAP443X_CLASS | (0x10 << 8)) @@ -496,6 +497,7 @@ level(__##fn); #define omap_subsys_initcall(fn) omap_initcall(subsys_initcall, fn) #define omap_device_initcall(fn) omap_initcall(device_initcall, fn) #define omap_late_initcall(fn) omap_initcall(late_initcall, fn) +#define omap_late_initcall_sync(fn) omap_initcall(late_initcall_sync, fn) #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index f12aa6c15da4..f8b23b8040d9 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -46,7 +46,6 @@ #include <asm/smp_twd.h> #include <asm/sched_clock.h> -#include <asm/arch_timer.h> #include "omap_hwmod.h" #include "omap_device.h" #include <plat/counter-32k.h> @@ -133,7 +132,12 @@ static struct property device_disabled = { }; static struct of_device_id omap_timer_match[] __initdata = { - { .compatible = "ti,omap2-timer", }, + { .compatible = "ti,omap2420-timer", }, + { .compatible = "ti,omap3430-timer", }, + { .compatible = "ti,omap4430-timer", }, + { .compatible = "ti,omap5430-timer", }, + { .compatible = "ti,am335x-timer", }, + { .compatible = "ti,am335x-timer-1ms", }, { } }; @@ -549,6 +553,8 @@ static inline void __init realtime_counter_init(void) clksrc_nr, clksrc_src, clksrc_prop) \ void __init omap##name##_gptimer_timer_init(void) \ { \ + if (omap_clk_init) \ + omap_clk_init(); \ omap_dmtimer_init(); \ omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src, \ @@ -559,6 +565,8 @@ void __init omap##name##_gptimer_timer_init(void) \ clksrc_nr, clksrc_src, clksrc_prop) \ void __init omap##name##_sync32k_timer_init(void) \ { \ + if (omap_clk_init) \ + omap_clk_init(); \ omap_dmtimer_init(); \ omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop); \ /* Enable the use of clocksource="gp_timer" kernel parameter */ \ @@ -622,14 +630,10 @@ void __init omap4_local_timer_init(void) #ifdef CONFIG_SOC_OMAP5 void __init omap5_realtime_timer_init(void) { - int err; - omap4_sync32k_timer_init(); realtime_counter_init(); - err = arch_timer_of_register(); - if (err) - pr_err("%s: arch_timer_register failed %d\n", __func__, err); + clocksource_of_init(); } #endif /* CONFIG_SOC_OMAP5 */ diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile index 9e809a7c05c0..45da805fb236 100644 --- a/arch/arm/mach-orion5x/Makefile +++ b/arch/arm/mach-orion5x/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o pci.o irq.o mpp.o +obj-y += common.o pci.o irq.o mpp.o obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c deleted file mode 100644 index b5efc0fd31cb..000000000000 --- a/arch/arm/mach-orion5x/addr-map.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * arch/arm/mach-orion5x/addr-map.c - * - * Address map functions for Marvell Orion 5x SoCs - * - * Maintainer: Tzachi Perelstein <tzachi@marvell.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <mach/hardware.h> -#include <plat/addr-map.h> -#include "common.h" - -/* - * The Orion has fully programmable address map. There's a separate address - * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB, - * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own - * address decode windows that allow it to access any of the Orion resources. - * - * CPU address decoding -- - * Linux assumes that it is the boot loader that already setup the access to - * DDR and internal registers. - * Setup access to PCI and PCIe IO/MEM space is issued by this file. - * Setup access to various devices located on the device bus interface (e.g. - * flashes, RTC, etc) should be issued by machine-setup.c according to - * specific board population (by using orion5x_setup_*_win()). - * - * Non-CPU Masters address decoding -- - * Unlike the CPU, we setup the access from Orion's master interfaces to DDR - * banks only (the typical use case). - * Setup access for each master to DDR is issued by platform device setup. - */ - -/* - * Generic Address Decode Windows bit settings - */ -#define TARGET_DEV_BUS 1 -#define TARGET_PCI 3 -#define TARGET_PCIE 4 -#define TARGET_SRAM 9 -#define ATTR_PCIE_MEM 0x59 -#define ATTR_PCIE_IO 0x51 -#define ATTR_PCIE_WA 0x79 -#define ATTR_PCI_MEM 0x59 -#define ATTR_PCI_IO 0x51 -#define ATTR_DEV_CS0 0x1e -#define ATTR_DEV_CS1 0x1d -#define ATTR_DEV_CS2 0x1b -#define ATTR_DEV_BOOT 0xf -#define ATTR_SRAM 0x0 - -static int __initdata win_alloc_count; - -static int __init cpu_win_can_remap(const struct orion_addr_map_cfg *cfg, - const int win) -{ - u32 dev, rev; - - orion5x_pcie_id(&dev, &rev); - if ((dev == MV88F5281_DEV_ID && win < 4) - || (dev == MV88F5182_DEV_ID && win < 2) - || (dev == MV88F5181_DEV_ID && win < 2) - || (dev == MV88F6183_DEV_ID && win < 4)) - return 1; - - return 0; -} - -/* - * Description of the windows needed by the platform code - */ -static struct orion_addr_map_cfg addr_map_cfg __initdata = { - .num_wins = 8, - .cpu_win_can_remap = cpu_win_can_remap, - .bridge_virt_base = ORION5X_BRIDGE_VIRT_BASE, -}; - -static const struct __initdata orion_addr_map_info addr_map_info[] = { - /* - * Setup windows for PCI+PCIe IO+MEM space. - */ - { 0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE, - TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE - }, - { 1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE, - TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE - }, - { 2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE, - TARGET_PCIE, ATTR_PCIE_MEM, -1 - }, - { 3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE, - TARGET_PCI, ATTR_PCI_MEM, -1 - }, - /* End marker */ - { -1, 0, 0, 0, 0, 0 } -}; - -void __init orion5x_setup_cpu_mbus_bridge(void) -{ - /* - * Disable, clear and configure windows. - */ - orion_config_wins(&addr_map_cfg, addr_map_info); - win_alloc_count = 4; - - /* - * Setup MBUS dram target info. - */ - orion_setup_cpu_mbus_target(&addr_map_cfg, - (void __iomem *) ORION5X_DDR_WINDOW_CPU_BASE); -} - -void __init orion5x_setup_dev_boot_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_BOOT, -1); -} - -void __init orion5x_setup_dev0_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_CS0, -1); -} - -void __init orion5x_setup_dev1_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_CS1, -1); -} - -void __init orion5x_setup_dev2_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_DEV_BUS, ATTR_DEV_CS2, -1); -} - -void __init orion5x_setup_pcie_wa_win(u32 base, u32 size) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, base, size, - TARGET_PCIE, ATTR_PCIE_WA, -1); -} - -void __init orion5x_setup_sram_win(void) -{ - orion_setup_cpu_win(&addr_map_cfg, win_alloc_count++, - ORION5X_SRAM_PHYS_BASE, ORION5X_SRAM_SIZE, - TARGET_SRAM, ATTR_SRAM, -1); -} diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c index 94fbb815680c..b91002ca92f3 100644 --- a/arch/arm/mach-orion5x/board-dt.c +++ b/arch/arm/mach-orion5x/board-dt.c @@ -42,7 +42,7 @@ static void __init orion5x_dt_init(void) /* * Setup Orion address map */ - orion5x_setup_cpu_mbus_bridge(); + orion5x_setup_wins(); /* Setup root of clk tree */ clk_init(); diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 2075bf8e3d90..b97fd672e89d 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -35,7 +35,6 @@ #include <linux/platform_data/usb-ehci-orion.h> #include <plat/time.h> #include <plat/common.h> -#include <plat/addr-map.h> #include "common.h" /***************************************************************************** @@ -175,7 +174,8 @@ void __init orion5x_xor_init(void) ****************************************************************************/ static void __init orion5x_crypto_init(void) { - orion5x_setup_sram_win(); + mvebu_mbus_add_window("sram", ORION5X_SRAM_PHYS_BASE, + ORION5X_SRAM_SIZE); orion_crypto_init(ORION5X_CRYPTO_PHYS_BASE, ORION5X_SRAM_PHYS_BASE, SZ_8K, IRQ_ORION5X_CESA); } @@ -194,6 +194,9 @@ void __init orion5x_wdt_init(void) ****************************************************************************/ void __init orion5x_init_early(void) { + u32 rev, dev; + const char *mbus_soc_name; + orion_time_set_base(TIMER_VIRT_BASE); /* @@ -202,6 +205,46 @@ void __init orion5x_init_early(void) * the allocations won't fail. */ init_dma_coherent_pool_size(SZ_1M); + + /* Initialize the MBUS driver */ + orion5x_pcie_id(&dev, &rev); + if (dev == MV88F5281_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5281-mbus"; + else if (dev == MV88F5182_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5182-mbus"; + else if (dev == MV88F5181_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5181-mbus"; + else if (dev == MV88F6183_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f6183-mbus"; + else + mbus_soc_name = NULL; + mvebu_mbus_init(mbus_soc_name, ORION5X_BRIDGE_WINS_BASE, + ORION5X_BRIDGE_WINS_SZ, + ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ); +} + +void orion5x_setup_wins(void) +{ + /* + * The PCIe windows will no longer be statically allocated + * here once Orion5x is migrated to the pci-mvebu driver. + */ + mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_IO_PHYS_BASE, + ORION5X_PCIE_IO_SIZE, + ORION5X_PCIE_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pcie0.0", ORION5X_PCIE_MEM_PHYS_BASE, + ORION5X_PCIE_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); + mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_IO_PHYS_BASE, + ORION5X_PCI_IO_SIZE, + ORION5X_PCI_IO_BUS_BASE, + MVEBU_MBUS_PCI_IO); + mvebu_mbus_add_window_remap_flags("pci0.0", ORION5X_PCI_MEM_PHYS_BASE, + ORION5X_PCI_MEM_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_MEM); } int orion5x_tclk; @@ -283,7 +326,7 @@ void __init orion5x_init(void) /* * Setup Orion address map */ - orion5x_setup_cpu_mbus_bridge(); + orion5x_setup_wins(); /* Setup root of clk tree */ clk_init(); diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index e60345760283..cdaa01f3d186 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -17,18 +17,7 @@ void clk_init(void); extern int orion5x_tclk; extern void orion5x_timer_init(void); -/* - * Enumerations and functions for Orion windows mapping. Used by Orion core - * functions to map its interfaces and by the machine-setup to map its on- - * board devices. Details in /mach-orion/addr-map.c - */ -void orion5x_setup_cpu_mbus_bridge(void); -void orion5x_setup_dev_boot_win(u32 base, u32 size); -void orion5x_setup_dev0_win(u32 base, u32 size); -void orion5x_setup_dev1_win(u32 base, u32 size); -void orion5x_setup_dev2_win(u32 base, u32 size); -void orion5x_setup_pcie_wa_win(u32 base, u32 size); -void orion5x_setup_sram_win(void); +void orion5x_setup_wins(void); void orion5x_ehci0_init(void); void orion5x_ehci1_init(void); diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c index 57d0af74874d..16c88bbabc98 100644 --- a/arch/arm/mach-orion5x/d2net-setup.c +++ b/arch/arm/mach-orion5x/d2net-setup.c @@ -317,8 +317,8 @@ static void __init d2net_init(void) d2net_sata_power_init(); orion5x_sata_init(&d2net_sata_data); - orion5x_setup_dev_boot_win(D2NET_NOR_BOOT_BASE, - D2NET_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", D2NET_NOR_BOOT_BASE, + D2NET_NOR_BOOT_SIZE); platform_device_register(&d2net_nor_flash); platform_device_register(&d2net_gpio_buttons); diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c index 76665640087b..4e1263da38bb 100644 --- a/arch/arm/mach-orion5x/db88f5281-setup.c +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -340,16 +340,19 @@ static void __init db88f5281_init(void) orion5x_uart0_init(); orion5x_uart1_init(); - orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE, - DB88F5281_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", DB88F5281_NOR_BOOT_BASE, + DB88F5281_NOR_BOOT_SIZE); platform_device_register(&db88f5281_boot_flash); - orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE); + mvebu_mbus_add_window("devbus-cs0", DB88F5281_7SEG_BASE, + DB88F5281_7SEG_SIZE); - orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE); + mvebu_mbus_add_window("devbus-cs1", DB88F5281_NOR_BASE, + DB88F5281_NOR_SIZE); platform_device_register(&db88f5281_nor_flash); - orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE); + mvebu_mbus_add_window("devbus-cs2", DB88F5281_NAND_BASE, + DB88F5281_NAND_SIZE); platform_device_register(&db88f5281_nand_flash); i2c_register_board_info(0, &db88f5281_i2c_rtc, 1); diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 6eb1732757fd..9e6baf581ed3 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -611,7 +611,8 @@ static void __init dns323_init(void) /* setup flash mapping * CS3 holds a 8 MB Spansion S29GL064M90TFIR4 */ - orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", DNS323_NOR_BOOT_BASE, + DNS323_NOR_BOOT_SIZE); platform_device_register(&dns323_nor_flash); /* Sort out LEDs, Buttons and i2c devices */ diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c index d675e727803d..147615510dd0 100644 --- a/arch/arm/mach-orion5x/edmini_v2-setup.c +++ b/arch/arm/mach-orion5x/edmini_v2-setup.c @@ -154,8 +154,8 @@ void __init edmini_v2_init(void) orion5x_ehci0_init(); orion5x_eth_init(&edmini_v2_eth_data); - orion5x_setup_dev_boot_win(EDMINI_V2_NOR_BOOT_BASE, - EDMINI_V2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", EDMINI_V2_NOR_BOOT_BASE, + EDMINI_V2_NOR_BOOT_SIZE); platform_device_register(&edmini_v2_nor_flash); pr_notice("edmini_v2: USB device port, flash write and power-off " diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index d265f5484a8e..b78ff3248868 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -66,8 +66,10 @@ * Orion Registers Map ******************************************************************************/ +#define ORION5X_DDR_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x00000) +#define ORION5X_DDR_WINS_BASE (ORION5X_DDR_PHYS_BASE + 0x1500) +#define ORION5X_DDR_WINS_SZ (0x10) #define ORION5X_DDR_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x00000) -#define ORION5X_DDR_WINDOW_CPU_BASE (ORION5X_DDR_VIRT_BASE + 0x1500) #define ORION5X_DEV_BUS_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x10000) #define ORION5X_DEV_BUS_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x10000) #define ORION5X_DEV_BUS_REG(x) (ORION5X_DEV_BUS_VIRT_BASE + (x)) @@ -81,6 +83,8 @@ #define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x20000) #define ORION5X_BRIDGE_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x20000) +#define ORION5X_BRIDGE_WINS_BASE (ORION5X_BRIDGE_PHYS_BASE) +#define ORION5X_BRIDGE_WINS_SZ (0x80) #define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x30000) diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c index b98403526218..aae10e4a917c 100644 --- a/arch/arm/mach-orion5x/kurobox_pro-setup.c +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -359,13 +359,13 @@ static void __init kurobox_pro_init(void) orion5x_uart1_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE, - KUROBOX_PRO_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", KUROBOX_PRO_NOR_BOOT_BASE, + KUROBOX_PRO_NOR_BOOT_SIZE); platform_device_register(&kurobox_pro_nor_flash); if (machine_is_kurobox_pro()) { - orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, - KUROBOX_PRO_NAND_SIZE); + mvebu_mbus_add_window("devbus-cs0", KUROBOX_PRO_NAND_BASE, + KUROBOX_PRO_NAND_SIZE); platform_device_register(&kurobox_pro_nand_flash); } diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c index 044da5b6a6ae..24f4e14e5893 100644 --- a/arch/arm/mach-orion5x/ls-chl-setup.c +++ b/arch/arm/mach-orion5x/ls-chl-setup.c @@ -294,8 +294,8 @@ static void __init lschl_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(LSCHL_NOR_BOOT_BASE, - LSCHL_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", LSCHL_NOR_BOOT_BASE, + LSCHL_NOR_BOOT_SIZE); platform_device_register(&lschl_nor_flash); platform_device_register(&lschl_leds); diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c index d49f93423f52..fc653bb41e78 100644 --- a/arch/arm/mach-orion5x/ls_hgl-setup.c +++ b/arch/arm/mach-orion5x/ls_hgl-setup.c @@ -243,8 +243,8 @@ static void __init ls_hgl_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(LS_HGL_NOR_BOOT_BASE, - LS_HGL_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", LS_HGL_NOR_BOOT_BASE, + LS_HGL_NOR_BOOT_SIZE); platform_device_register(&ls_hgl_nor_flash); platform_device_register(&ls_hgl_button_device); diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c index 8e3965c6c0fe..18e66e617dc2 100644 --- a/arch/arm/mach-orion5x/lsmini-setup.c +++ b/arch/arm/mach-orion5x/lsmini-setup.c @@ -244,8 +244,8 @@ static void __init lsmini_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(LSMINI_NOR_BOOT_BASE, - LSMINI_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", LSMINI_NOR_BOOT_BASE, + LSMINI_NOR_BOOT_SIZE); platform_device_register(&lsmini_nor_flash); platform_device_register(&lsmini_button_device); diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c index 0ec94a1f2b16..827acbafc9dc 100644 --- a/arch/arm/mach-orion5x/mss2-setup.c +++ b/arch/arm/mach-orion5x/mss2-setup.c @@ -241,7 +241,8 @@ static void __init mss2_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(MSS2_NOR_BOOT_BASE, MSS2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", MSS2_NOR_BOOT_BASE, + MSS2_NOR_BOOT_SIZE); platform_device_register(&mss2_nor_flash); platform_device_register(&mss2_button_device); diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c index 18143f2a9093..92600ae2b4b6 100644 --- a/arch/arm/mach-orion5x/mv2120-setup.c +++ b/arch/arm/mach-orion5x/mv2120-setup.c @@ -204,7 +204,8 @@ static void __init mv2120_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(MV2120_NOR_BOOT_BASE, MV2120_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", MV2120_NOR_BOOT_BASE, + MV2120_NOR_BOOT_SIZE); platform_device_register(&mv2120_nor_flash); platform_device_register(&mv2120_button_device); diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c index 282e503b003e..dd0641a0d074 100644 --- a/arch/arm/mach-orion5x/net2big-setup.c +++ b/arch/arm/mach-orion5x/net2big-setup.c @@ -397,8 +397,8 @@ static void __init net2big_init(void) net2big_sata_power_init(); orion5x_sata_init(&net2big_sata_data); - orion5x_setup_dev_boot_win(NET2BIG_NOR_BOOT_BASE, - NET2BIG_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", NET2BIG_NOR_BOOT_BASE, + NET2BIG_NOR_BOOT_SIZE); platform_device_register(&net2big_nor_flash); platform_device_register(&net2big_gpio_buttons); diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c index 973db98a3c27..503368023bb1 100644 --- a/arch/arm/mach-orion5x/pci.c +++ b/arch/arm/mach-orion5x/pci.c @@ -157,8 +157,11 @@ static int __init pcie_setup(struct pci_sys_data *sys) if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) { printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config " "read transaction workaround\n"); - orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE, - ORION5X_PCIE_WA_SIZE); + mvebu_mbus_add_window_remap_flags("pcie0.0", + ORION5X_PCIE_WA_PHYS_BASE, + ORION5X_PCIE_WA_SIZE, + MVEBU_MBUS_NO_REMAP, + MVEBU_MBUS_PCI_WA); pcie_ops.read = pcie_rd_conf_wa; } diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c index d6e72f672afb..1c4498bf650a 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c @@ -123,8 +123,8 @@ static void __init rd88f5181l_fxo_init(void) orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data, NO_IRQ); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(RD88F5181L_FXO_NOR_BOOT_BASE, - RD88F5181L_FXO_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", RD88F5181L_FXO_NOR_BOOT_BASE, + RD88F5181L_FXO_NOR_BOOT_SIZE); platform_device_register(&rd88f5181l_fxo_nor_boot_flash); } diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c index c8b7913310e5..adabe34c4fc6 100644 --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c @@ -130,8 +130,8 @@ static void __init rd88f5181l_ge_init(void) orion5x_i2c_init(); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(RD88F5181L_GE_NOR_BOOT_BASE, - RD88F5181L_GE_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", RD88F5181L_GE_NOR_BOOT_BASE, + RD88F5181L_GE_NOR_BOOT_SIZE); platform_device_register(&rd88f5181l_ge_nor_boot_flash); i2c_register_board_info(0, &rd88f5181l_ge_i2c_rtc, 1); diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c index f9e156725d7c..66e77ec91532 100644 --- a/arch/arm/mach-orion5x/rd88f5182-setup.c +++ b/arch/arm/mach-orion5x/rd88f5182-setup.c @@ -264,10 +264,11 @@ static void __init rd88f5182_init(void) orion5x_uart0_init(); orion5x_xor_init(); - orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE, - RD88F5182_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", RD88F5182_NOR_BOOT_BASE, + RD88F5182_NOR_BOOT_SIZE); - orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE); + mvebu_mbus_add_window("devbus-cs1", RD88F5182_NOR_BASE, + RD88F5182_NOR_SIZE); platform_device_register(&rd88f5182_nor_flash); platform_device_register(&rd88f5182_gpio_leds); diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c index acc0877ec1c9..a0bfa53e7556 100644 --- a/arch/arm/mach-orion5x/terastation_pro2-setup.c +++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c @@ -329,8 +329,8 @@ static void __init tsp2_init(void) /* * Configure peripherals. */ - orion5x_setup_dev_boot_win(TSP2_NOR_BOOT_BASE, - TSP2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", TSP2_NOR_BOOT_BASE, + TSP2_NOR_BOOT_SIZE); platform_device_register(&tsp2_nor_flash); orion5x_ehci0_init(); diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c index 9c17f0c2b488..80174f0f168e 100644 --- a/arch/arm/mach-orion5x/ts209-setup.c +++ b/arch/arm/mach-orion5x/ts209-setup.c @@ -286,8 +286,8 @@ static void __init qnap_ts209_init(void) /* * Configure peripherals. */ - orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE, - QNAP_TS209_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", QNAP_TS209_NOR_BOOT_BASE, + QNAP_TS209_NOR_BOOT_SIZE); platform_device_register(&qnap_ts209_nor_flash); orion5x_ehci0_init(); diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c index 8cc5ab6c503e..92592790d6da 100644 --- a/arch/arm/mach-orion5x/ts409-setup.c +++ b/arch/arm/mach-orion5x/ts409-setup.c @@ -277,8 +277,8 @@ static void __init qnap_ts409_init(void) /* * Configure peripherals. */ - orion5x_setup_dev_boot_win(QNAP_TS409_NOR_BOOT_BASE, - QNAP_TS409_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", QNAP_TS409_NOR_BOOT_BASE, + QNAP_TS409_NOR_BOOT_SIZE); platform_device_register(&qnap_ts409_nor_flash); orion5x_ehci0_init(); diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c index 66552ca7e05d..6b84863c018d 100644 --- a/arch/arm/mach-orion5x/wnr854t-setup.c +++ b/arch/arm/mach-orion5x/wnr854t-setup.c @@ -127,8 +127,8 @@ static void __init wnr854t_init(void) orion5x_eth_switch_init(&wnr854t_switch_plat_data, NO_IRQ); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(WNR854T_NOR_BOOT_BASE, - WNR854T_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", WNR854T_NOR_BOOT_BASE, + WNR854T_NOR_BOOT_SIZE); platform_device_register(&wnr854t_nor_flash); } diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c index 2c5408e2e689..fae684bc54f2 100644 --- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c +++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c @@ -213,8 +213,8 @@ static void __init wrt350n_v2_init(void) orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data, NO_IRQ); orion5x_uart0_init(); - orion5x_setup_dev_boot_win(WRT350N_V2_NOR_BOOT_BASE, - WRT350N_V2_NOR_BOOT_SIZE); + mvebu_mbus_add_window("devbus-boot", WRT350N_V2_NOR_BOOT_BASE, + WRT350N_V2_NOR_BOOT_SIZE); platform_device_register(&wrt350n_v2_nor_flash); platform_device_register(&wrt350n_v2_leds); platform_device_register(&wrt350n_v2_button_device); diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig index 80ca974b2f82..6988b117fc17 100644 --- a/arch/arm/mach-prima2/Kconfig +++ b/arch/arm/mach-prima2/Kconfig @@ -38,7 +38,7 @@ config ARCH_MARCO select CPU_V7 select HAVE_ARM_SCU if SMP select HAVE_SMP - select SMP_ON_UP + select SMP_ON_UP if SMP help Support for CSR SiRFSoC ARM Cortex A9 Platform diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 9075461999c1..96100dbf5a2e 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -162,7 +162,6 @@ config MACH_XCEP select MTD select MTD_CFI select MTD_CFI_INTELEXT - select MTD_CHAR select MTD_PHYSMAP select PXA25x select SMC91X diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index eb3a7ff19e72..1a517e2fe449 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -18,11 +18,28 @@ config ARCH_SH73A0 select SH_CLK_CPG select RENESAS_INTC_IRQPIN +config ARCH_R8A73A4 + bool "R-Mobile APE6 (R8A73A40)" + select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_GIC + select CPU_V7 + select ARM_ARCH_TIMER + select SH_CLK_CPG + select RENESAS_IRQC + config ARCH_R8A7740 bool "R-Mobile A1 (R8A77400)" select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_GIC select CPU_V7 select SH_CLK_CPG + select RENESAS_INTC_IRQPIN + +config ARCH_R8A7778 + bool "R-Car M1 (R8A77780)" + select CPU_V7 + select SH_CLK_CPG + select ARM_GIC config ARCH_R8A7779 bool "R-Car H1 (R8A77790)" @@ -34,6 +51,15 @@ config ARCH_R8A7779 select USB_ARCH_HAS_OHCI select RENESAS_INTC_IRQPIN +config ARCH_R8A7790 + bool "R-Car H2 (R8A77900)" + select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_GIC + select CPU_V7 + select ARM_ARCH_TIMER + select SH_CLK_CPG + select RENESAS_IRQC + config ARCH_EMEV2 bool "Emma Mobile EV2" select ARCH_WANT_OPTIONAL_GPIOLIB @@ -70,6 +96,11 @@ config MACH_AG5EVM select REGULATOR_FIXED_VOLTAGE if REGULATOR select SH_LCD_MIPI_DSI +config MACH_APE6EVM + bool "APE6EVM board" + depends on ARCH_R8A73A4 + select USE_OF + config MACH_MACKEREL bool "mackerel board" depends on ARCH_SH7372 @@ -98,6 +129,13 @@ config MACH_ARMADILLO800EVA select SND_SOC_WM8978 if SND_SIMPLE_CARD select USE_OF +config MACH_BOCKW + bool "BOCK-W platform" + depends on ARCH_R8A7778 + select ARCH_REQUIRE_GPIOLIB + select RENESAS_INTC_IRQPIN + select USE_OF + config MACH_MARZEN bool "MARZEN board" depends on ARCH_R8A7779 @@ -117,6 +155,11 @@ config MACH_MARZEN_REFERENCE This is intended to aid developers +config MACH_LAGER + bool "Lager board" + depends on ARCH_R8A7790 + select USE_OF + config MACH_KZM9D bool "KZM9D board" depends on ARCH_EMEV2 @@ -157,7 +200,8 @@ config MEMORY_START hex "Physical memory start address" default "0x40000000" if MACH_AP4EVB || MACH_AG5EVM || \ MACH_MACKEREL || MACH_BONITO || \ - MACH_ARMADILLO800EVA + MACH_ARMADILLO800EVA || MACH_APE6EVM || \ + MACH_LAGER default "0x41000000" if MACH_KOTA2 default "0x00000000" ---help--- @@ -167,6 +211,8 @@ config MEMORY_START config MEMORY_SIZE hex "Physical memory size" + default "0x80000000" if MACH_LAGER + default "0x40000000" if MACH_APE6EVM default "0x20000000" if MACH_AG5EVM || MACH_BONITO || \ MACH_ARMADILLO800EVA default "0x1e000000" if MACH_KOTA2 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index c621edfa6ead..068f1dadc46b 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -8,8 +8,11 @@ obj-y := timer.o console.o clock.o # CPU objects obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o +obj-$(CONFIG_ARCH_R8A73A4) += setup-r8a73a4.o clock-r8a73a4.o obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o +obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o clock-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o +obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o clock-r8a7790.o obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o # SMP objects @@ -34,11 +37,14 @@ obj-$(CONFIG_ARCH_SH73A0) += pm-sh73a0.o # Board objects obj-$(CONFIG_MACH_AP4EVB) += board-ap4evb.o obj-$(CONFIG_MACH_AG5EVM) += board-ag5evm.o +obj-$(CONFIG_MACH_APE6EVM) += board-ape6evm.o obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o obj-$(CONFIG_MACH_KOTA2) += board-kota2.o obj-$(CONFIG_MACH_BONITO) += board-bonito.o +obj-$(CONFIG_MACH_BOCKW) += board-bockw.o obj-$(CONFIG_MACH_MARZEN) += board-marzen.o obj-$(CONFIG_MACH_MARZEN_REFERENCE) += board-marzen-reference.o +obj-$(CONFIG_MACH_LAGER) += board-lager.o obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c new file mode 100644 index 000000000000..55b8c9fef954 --- /dev/null +++ b/arch/arm/mach-shmobile/board-ape6evm.c @@ -0,0 +1,94 @@ +/* + * APE6EVM board support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/irqchip.h> +#include <linux/kernel.h> +#include <linux/pinctrl/machine.h> +#include <linux/platform_device.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> +#include <linux/smsc911x.h> +#include <mach/common.h> +#include <mach/irqs.h> +#include <mach/r8a73a4.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + +/* SMSC LAN9220 */ +static const struct resource lan9220_res[] = { + DEFINE_RES_MEM(0x08000000, 0x1000), + { + .start = irq_pin(40), /* IRQ40 */ + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, + }, +}; + +static const struct smsc911x_platform_config lan9220_data = { + .flags = SMSC911X_USE_32BIT, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, +}; + +static const struct pinctrl_map ape6evm_pinctrl_map[] = { + /* SCIFA0 console */ + PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a73a4", + "scifa0_data", "scifa0"), + /* SMSC */ + PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a73a4", + "irqc_irq40", "irqc"), +}; + +static void __init ape6evm_add_standard_devices(void) +{ + r8a73a4_clock_init(); + pinctrl_register_mappings(ape6evm_pinctrl_map, + ARRAY_SIZE(ape6evm_pinctrl_map)); + r8a73a4_pinmux_init(); + r8a73a4_add_standard_devices(); + + /* LAN9220 ethernet */ + gpio_request_one(270, GPIOF_OUT_INIT_HIGH, NULL); /* smsc9220 RESET */ + + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + + platform_device_register_resndata(&platform_bus, "smsc911x", -1, + lan9220_res, ARRAY_SIZE(lan9220_res), + &lan9220_data, sizeof(lan9220_data)); +} + +static const char *ape6evm_boards_compat_dt[] __initdata = { + "renesas,ape6evm", + NULL, +}; + +DT_MACHINE_START(APE6EVM_DT, "ape6evm") + .init_irq = irqchip_init, + .init_time = shmobile_timer_init, + .init_machine = ape6evm_add_standard_devices, + .dt_compat = ape6evm_boards_compat_dt, +MACHINE_END diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 4dfe32262eb7..b85b2882dbd0 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -149,7 +149,7 @@ * see * usbhsf_power_ctrl() */ -#define IRQ7 evt2irq(0x02e0) +#define IRQ7 irq_pin(7) #define USBCR1 IOMEM(0xe605810a) #define USBH 0xC6700000 #define USBH_USBCTR 0x10834 @@ -338,7 +338,7 @@ static struct resource usbhsf_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = evt2irq(0x0A20), + .start = gic_spi(51), .flags = IORESOURCE_IRQ, }, }; @@ -371,7 +371,7 @@ static struct resource sh_eth_resources[] = { .end = 0xe9a02000 - 1, .flags = IORESOURCE_MEM, }, { - .start = evt2irq(0x0500), + .start = gic_spi(110), .flags = IORESOURCE_IRQ, }, }; @@ -425,7 +425,7 @@ static struct resource lcdc0_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = intcs_evt2irq(0x580), + .start = gic_spi(177), .flags = IORESOURCE_IRQ, }, }; @@ -460,7 +460,7 @@ static struct resource hdmi_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x1700), + .start = gic_spi(131), .flags = IORESOURCE_IRQ, }, [2] = { @@ -522,7 +522,7 @@ static struct resource hdmi_lcdc_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = intcs_evt2irq(0x1780), + .start = gic_spi(178), .flags = IORESOURCE_IRQ, }, }; @@ -686,7 +686,7 @@ static struct platform_device vcc_sdhi1 = { * We can use IRQ31 as card detect irq, * but it needs chattering removal operation */ -#define IRQ31 evt2irq(0x33E0) +#define IRQ31 irq_pin(31) static struct sh_mobile_sdhi_info sdhi0_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, @@ -708,12 +708,12 @@ static struct resource sdhi0_resources[] = { */ { .name = SH_MOBILE_SDHI_IRQ_SDCARD, - .start = evt2irq(0x0E20), + .start = gic_spi(118), .flags = IORESOURCE_IRQ, }, { .name = SH_MOBILE_SDHI_IRQ_SDIO, - .start = evt2irq(0x0E40), + .start = gic_spi(119), .flags = IORESOURCE_IRQ, }, }; @@ -747,15 +747,15 @@ static struct resource sdhi1_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x0E80), + .start = gic_spi(121), .flags = IORESOURCE_IRQ, }, [2] = { - .start = evt2irq(0x0EA0), + .start = gic_spi(122), .flags = IORESOURCE_IRQ, }, [3] = { - .start = evt2irq(0x0EC0), + .start = gic_spi(123), .flags = IORESOURCE_IRQ, }, }; @@ -798,12 +798,12 @@ static struct resource sh_mmcif_resources[] = { }, [1] = { /* MMC ERR */ - .start = evt2irq(0x1AC0), + .start = gic_spi(56), .flags = IORESOURCE_IRQ, }, [2] = { /* MMC NOR */ - .start = evt2irq(0x1AE0), + .start = gic_spi(57), .flags = IORESOURCE_IRQ, }, }; @@ -880,7 +880,7 @@ static struct resource ceu0_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = intcs_evt2irq(0x0500), + .start = gic_spi(160), .flags = IORESOURCE_IRQ, }, [2] = { @@ -922,7 +922,7 @@ static struct resource fsi_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x1840), + .start = gic_spi(9), .flags = IORESOURCE_IRQ, }, }; @@ -1009,7 +1009,7 @@ static struct st1232_pdata st1232_i2c0_pdata = { static struct i2c_board_info i2c0_devices[] = { { I2C_BOARD_INFO("st1232-ts", 0x55), - .irq = evt2irq(0x0340), + .irq = irq_pin(10), .platform_data = &st1232_i2c0_pdata, }, { @@ -1292,7 +1292,6 @@ DT_MACHINE_START(ARMADILLO800EVA_DT, "armadillo800eva") .map_io = r8a7740_map_io, .init_early = eva_add_early_devices, .init_irq = r8a7740_init_irq, - .handle_irq = shmobile_handle_irq_intc, .init_machine = eva_init, .init_late = shmobile_init_late, .init_time = eva_earlytimer_init, diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c new file mode 100644 index 000000000000..38e5e50fb318 --- /dev/null +++ b/arch/arm/mach-shmobile/board-bockw.c @@ -0,0 +1,81 @@ +/* + * Bock-W board support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/platform_device.h> +#include <linux/smsc911x.h> +#include <mach/common.h> +#include <mach/irqs.h> +#include <mach/r8a7778.h> +#include <asm/mach/arch.h> + +static struct smsc911x_platform_config smsc911x_data = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, + .flags = SMSC911X_USE_32BIT, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct resource smsc911x_resources[] = { + DEFINE_RES_MEM(0x18300000, 0x1000), + DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */ +}; + +#define IRQ0MR 0x30 +static void __init bockw_init(void) +{ + void __iomem *fpga; + + r8a7778_clock_init(); + r8a7778_init_irq_extpin(1); + r8a7778_add_standard_devices(); + + fpga = ioremap_nocache(0x18200000, SZ_1M); + if (fpga) { + /* + * CAUTION + * + * IRQ0/1 is cascaded interrupt from FPGA. + * it should be cared in the future + * Now, it is assuming IRQ0 was used only from SMSC. + */ + u16 val = ioread16(fpga + IRQ0MR); + val &= ~(1 << 4); /* enable SMSC911x */ + iowrite16(val, fpga + IRQ0MR); + iounmap(fpga); + + platform_device_register_resndata( + &platform_bus, "smsc911x", -1, + smsc911x_resources, ARRAY_SIZE(smsc911x_resources), + &smsc911x_data, sizeof(smsc911x_data)); + } +} + +static const char *bockw_boards_compat_dt[] __initdata = { + "renesas,bockw", + NULL, +}; + +DT_MACHINE_START(BOCKW_DT, "bockw") + .init_early = r8a7778_init_delay, + .init_irq = r8a7778_init_irq_dt, + .init_machine = bockw_init, + .init_time = shmobile_timer_init, + .dt_compat = bockw_boards_compat_dt, +MACHINE_END diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c index c254782aa727..c016ccd92433 100644 --- a/arch/arm/mach-shmobile/board-kzm9d.c +++ b/arch/arm/mach-shmobile/board-kzm9d.c @@ -90,6 +90,5 @@ DT_MACHINE_START(KZM9D_DT, "kzm9d") .init_irq = emev2_init_irq, .init_machine = kzm9d_add_standard_devices, .init_late = shmobile_init_late, - .init_time = shmobile_timer_init, .dt_compat = kzm9d_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c new file mode 100644 index 000000000000..f587187a8603 --- /dev/null +++ b/arch/arm/mach-shmobile/board-lager.c @@ -0,0 +1,46 @@ +/* + * Lager board support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/interrupt.h> +#include <linux/irqchip.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <mach/common.h> +#include <mach/r8a7790.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static void __init lager_add_standard_devices(void) +{ + r8a7790_clock_init(); + r8a7790_add_standard_devices(); +} + +static const char *lager_boards_compat_dt[] __initdata = { + "renesas,lager", + NULL, +}; + +DT_MACHINE_START(LAGER_DT, "lager") + .init_irq = irqchip_init, + .init_time = r8a7790_timer_init, + .init_machine = lager_add_standard_devices, + .dt_compat = lager_boards_compat_dt, +MACHINE_END diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 2b60f2bf1fbb..fa3407da682a 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -969,15 +969,6 @@ static struct platform_device nand_flash_device = { }, }; -/* - * The card detect pin of the top SD/MMC slot (CN7) is active low and is - * connected to GPIO A22 of SH7372 (GPIO 41). - */ -static int slot_cn7_get_cd(struct platform_device *pdev) -{ - return !gpio_get_value(41); -} - /* SDHI0 */ static struct sh_mobile_sdhi_info sdhi0_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, @@ -988,21 +979,17 @@ static struct sh_mobile_sdhi_info sdhi0_info = { }; static struct resource sdhi0_resources[] = { - [0] = { + { .name = "SDHI0", .start = 0xe6850000, .end = 0xe68500ff, .flags = IORESOURCE_MEM, - }, - [1] = { - .start = evt2irq(0x0e00) /* SDHI0_SDHI0I0 */, - .flags = IORESOURCE_IRQ, - }, - [2] = { + }, { + .name = SH_MOBILE_SDHI_IRQ_SDCARD, .start = evt2irq(0x0e20) /* SDHI0_SDHI0I1 */, .flags = IORESOURCE_IRQ, - }, - [3] = { + }, { + .name = SH_MOBILE_SDHI_IRQ_SDIO, .start = evt2irq(0x0e40) /* SDHI0_SDHI0I2 */, .flags = IORESOURCE_IRQ, }, @@ -1018,36 +1005,30 @@ static struct platform_device sdhi0_device = { }, }; -#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) +#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF) /* SDHI1 */ + +/* GPIO 41 can trigger IRQ8, but it is used by USBHS1, we have to poll */ static struct sh_mobile_sdhi_info sdhi1_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, - .tmio_ocr_mask = MMC_VDD_165_195, - .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, + .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_USE_GPIO_CD, .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL, - .get_cd = slot_cn7_get_cd, + .cd_gpio = 41, }; static struct resource sdhi1_resources[] = { - [0] = { + { .name = "SDHI1", .start = 0xe6860000, .end = 0xe68600ff, .flags = IORESOURCE_MEM, - }, - [1] = { - .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, - .start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */ - .flags = IORESOURCE_IRQ, - }, - [2] = { + }, { .name = SH_MOBILE_SDHI_IRQ_SDCARD, .start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */ .flags = IORESOURCE_IRQ, - }, - [3] = { + }, { .name = SH_MOBILE_SDHI_IRQ_SDIO, .start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */ .flags = IORESOURCE_IRQ, @@ -1065,43 +1046,32 @@ static struct platform_device sdhi1_device = { }; #endif +/* SDHI2 */ + /* * The card detect pin of the top SD/MMC slot (CN23) is active low and is - * connected to GPIO SCIFB_SCK of SH7372 (162). + * connected to GPIO SCIFB_SCK of SH7372 (GPIO 162). */ -static int slot_cn23_get_cd(struct platform_device *pdev) -{ - return !gpio_get_value(162); -} - -/* SDHI2 */ static struct sh_mobile_sdhi_info sdhi2_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI2_TX, .dma_slave_rx = SHDMA_SLAVE_SDHI2_RX, - .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE, + .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_USE_GPIO_CD, .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL, - .get_cd = slot_cn23_get_cd, + .cd_gpio = 162, }; static struct resource sdhi2_resources[] = { - [0] = { + { .name = "SDHI2", .start = 0xe6870000, .end = 0xe68700ff, .flags = IORESOURCE_MEM, - }, - [1] = { - .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, - .start = evt2irq(0x1200), /* SDHI2_SDHI2I0 */ - .flags = IORESOURCE_IRQ, - }, - [2] = { + }, { .name = SH_MOBILE_SDHI_IRQ_SDCARD, .start = evt2irq(0x1220), /* SDHI2_SDHI2I1 */ .flags = IORESOURCE_IRQ, - }, - [3] = { + }, { .name = SH_MOBILE_SDHI_IRQ_SDIO, .start = evt2irq(0x1240), /* SDHI2_SDHI2I2 */ .flags = IORESOURCE_IRQ, @@ -1119,6 +1089,7 @@ static struct platform_device sdhi2_device = { }; /* SH_MMCIF */ +#if IS_ENABLED(CONFIG_MMC_SH_MMCIF) static struct resource sh_mmcif_resources[] = { [0] = { .name = "MMCIF", @@ -1140,16 +1111,17 @@ static struct resource sh_mmcif_resources[] = { static struct sh_mmcif_plat_data sh_mmcif_plat = { .sup_pclk = 0, - .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | MMC_CAP_NEEDS_POLL, - .get_cd = slot_cn7_get_cd, + .use_cd_gpio = true, + /* card detect pin for SD/MMC slot (CN7) */ + .cd_gpio = 41, .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, }; -static struct platform_device sh_mmcif_device __maybe_unused = { +static struct platform_device sh_mmcif_device = { .name = "sh_mmcif", .id = 0, .dev = { @@ -1160,7 +1132,7 @@ static struct platform_device sh_mmcif_device __maybe_unused = { .num_resources = ARRAY_SIZE(sh_mmcif_resources), .resource = sh_mmcif_resources, }; - +#endif static int mackerel_camera_add(struct soc_camera_device *icd); static void mackerel_camera_del(struct soc_camera_device *icd); @@ -1267,11 +1239,12 @@ static struct platform_device *mackerel_devices[] __initdata = { &fsi_hdmi_device, &nand_flash_device, &sdhi0_device, -#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) +#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF) &sdhi1_device, +#else + &sh_mmcif_device, #endif &sdhi2_device, - &sh_mmcif_device, &ceu_device, &mackerel_camera, &hdmi_device, @@ -1336,11 +1309,6 @@ static struct i2c_board_info i2c1_devices[] = { }; static const struct pinctrl_map mackerel_pinctrl_map[] = { - /* MMCIF */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372", - "mmc0_data8_0", "mmc0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372", - "mmc0_ctrl_0", "mmc0"), /* SDHI0 */ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372", "sdhi0_data4", "sdhi0"), @@ -1349,11 +1317,17 @@ static const struct pinctrl_map mackerel_pinctrl_map[] = { PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372", "sdhi0_wp", "sdhi0"), /* SDHI1 */ -#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) +#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF) PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372", "sdhi1_data4", "sdhi1"), PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372", "sdhi1_ctrl", "sdhi1"), +#else + /* MMCIF */ + PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372", + "mmc0_data8_0", "mmc0"), + PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372", + "mmc0_ctrl_0", "mmc0"), #endif /* SDHI2 */ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh7372", @@ -1378,10 +1352,11 @@ static void __init mackerel_init(void) { "A3SP", &usbhs0_device, }, { "A3SP", &usbhs1_device, }, { "A3SP", &nand_flash_device, }, - { "A3SP", &sh_mmcif_device, }, { "A3SP", &sdhi0_device, }, -#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) +#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF) { "A3SP", &sdhi1_device, }, +#else + { "A3SP", &sh_mmcif_device, }, #endif { "A3SP", &sdhi2_device, }, { "A4R", &ceu_device, }, @@ -1492,12 +1467,6 @@ static void __init mackerel_init(void) /* SDHI0 PORT172 card-detect IRQ26 */ gpio_request(GPIO_FN_IRQ26_172, NULL); - /* card detect pin for MMC slot (CN7) */ - gpio_request_one(41, GPIOF_IN, NULL); - - /* card detect pin for microSD slot (CN23) */ - gpio_request_one(162, GPIOF_IN, NULL); - /* FLCTL */ gpio_request(GPIO_FN_D0_NAF0, NULL); gpio_request(GPIO_FN_D1_NAF1, NULL); diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index 2333a2d7c937..91052855cc12 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c @@ -25,6 +25,7 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/leds.h> #include <linux/dma-mapping.h> #include <linux/pinctrl/machine.h> #include <linux/regulator/fixed.h> @@ -168,12 +169,43 @@ static struct platform_device usb_phy_device = { .num_resources = ARRAY_SIZE(usb_phy_resources), }; +/* LEDS */ +static struct gpio_led marzen_leds[] = { + { + .name = "led2", + .gpio = 157, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, { + .name = "led3", + .gpio = 158, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, { + .name = "led4", + .gpio = 159, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, +}; + +static struct gpio_led_platform_data marzen_leds_pdata = { + .leds = marzen_leds, + .num_leds = ARRAY_SIZE(marzen_leds), +}; + +static struct platform_device leds_device = { + .name = "leds-gpio", + .id = 0, + .dev = { + .platform_data = &marzen_leds_pdata, + }, +}; + static struct platform_device *marzen_devices[] __initdata = { ð_device, &sdhi0_device, &thermal_device, &hspi_device, &usb_phy_device, + &leds_device, }; /* USB */ diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c new file mode 100644 index 000000000000..e710c00c3822 --- /dev/null +++ b/arch/arm/mach-shmobile/clock-r8a73a4.c @@ -0,0 +1,115 @@ +/* + * r8a73a4 clock framework support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/sh_clk.h> +#include <linux/clkdev.h> +#include <mach/common.h> + +#define CPG_BASE 0xe6150000 +#define CPG_LEN 0x270 + +#define MPCKCR 0xe6150080 +#define SMSTPCR2 0xe6150138 +#define SMSTPCR5 0xe6150144 + +static struct clk_mapping cpg_mapping = { + .phys = CPG_BASE, + .len = CPG_LEN, +}; + +static struct clk extalr_clk = { + .rate = 32768, + .mapping = &cpg_mapping, +}; + +static struct clk extal1_clk = { + .rate = 26000000, + .mapping = &cpg_mapping, +}; + +static struct clk extal2_clk = { + .rate = 48000000, + .mapping = &cpg_mapping, +}; + +static struct clk *main_clks[] = { + &extalr_clk, + &extal1_clk, + &extal2_clk, +}; + +enum { + MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, + MSTP522, + MSTP_NR +}; + +static struct clk mstp_clks[MSTP_NR] = { + [MSTP204] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 4, 0), /* SCIFA0 */ + [MSTP203] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 3, 0), /* SCIFA1 */ + [MSTP206] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 6, 0), /* SCIFB0 */ + [MSTP207] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 7, 0), /* SCIFB1 */ + [MSTP216] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 16, 0), /* SCIFB2 */ + [MSTP217] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR2, 17, 0), /* SCIFB3 */ + [MSTP522] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR5, 22, 0), /* Thermal */ +}; + +static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), + CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), + CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]), + CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]), + CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]), + CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]), + CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), + + /* for DT */ + CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]), +}; + +void __init r8a73a4_clock_init(void) +{ + void __iomem *cpg_base, *reg; + int k, ret = 0; + + /* fix MPCLK to EXTAL2 for now. + * this is needed until more detailed clock topology is supported + */ + cpg_base = ioremap_nocache(CPG_BASE, CPG_LEN); + BUG_ON(!cpg_base); + reg = cpg_base + (MPCKCR - CPG_BASE); + iowrite32(ioread32(reg) | 1 << 7 | 0x0c, reg); /* set CKSEL */ + iounmap(cpg_base); + + for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) + ret = clk_register(main_clks[k]); + + if (!ret) + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + if (!ret) + shmobile_clk_init(); + else + panic("failed to setup r8a73a4 clocks\n"); +} diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index 1feb9a2286a8..c0d39aa6de50 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -22,6 +22,7 @@ #include <linux/io.h> #include <linux/sh_clk.h> #include <linux/clkdev.h> +#include <mach/clock.h> #include <mach/common.h> #include <mach/r8a7740.h> @@ -97,42 +98,13 @@ static struct clk dv_clk = { .rate = 27000000, }; -static unsigned long div_recalc(struct clk *clk) -{ - return clk->parent->rate / (int)(clk->priv); -} - -static struct sh_clk_ops div_clk_ops = { - .recalc = div_recalc, -}; - -/* extal1 / 2 */ -static struct clk extal1_div2_clk = { - .ops = &div_clk_ops, - .priv = (void *)2, - .parent = &extal1_clk, -}; - -/* extal1 / 1024 */ -static struct clk extal1_div1024_clk = { - .ops = &div_clk_ops, - .priv = (void *)1024, - .parent = &extal1_clk, -}; - -/* extal1 / 2 / 1024 */ -static struct clk extal1_div2048_clk = { - .ops = &div_clk_ops, - .priv = (void *)1024, - .parent = &extal1_div2_clk, -}; +SH_CLK_RATIO(div2, 1, 2); +SH_CLK_RATIO(div1k, 1, 1024); -/* extal2 / 2 */ -static struct clk extal2_div2_clk = { - .ops = &div_clk_ops, - .priv = (void *)2, - .parent = &extal2_clk, -}; +SH_FIXED_RATIO_CLK(extal1_div2_clk, extal1_clk, div2); +SH_FIXED_RATIO_CLK(extal1_div1024_clk, extal1_clk, div1k); +SH_FIXED_RATIO_CLK(extal1_div2048_clk, extal1_div2_clk, div1k); +SH_FIXED_RATIO_CLK(extal2_div2_clk, extal2_clk, div2); static struct sh_clk_ops followparent_clk_ops = { .recalc = followparent_recalc, @@ -143,11 +115,7 @@ static struct clk system_clk = { .ops = &followparent_clk_ops, }; -static struct clk system_div2_clk = { - .ops = &div_clk_ops, - .priv = (void *)2, - .parent = &system_clk, -}; +SH_FIXED_RATIO_CLK(system_div2_clk, system_clk, div2); /* r_clk */ static struct clk r_clk = { @@ -184,11 +152,7 @@ static struct clk pllc1_clk = { }; /* PLLC1 / 2 */ -static struct clk pllc1_div2_clk = { - .ops = &div_clk_ops, - .priv = (void *)2, - .parent = &pllc1_clk, -}; +SH_FIXED_RATIO_CLK(pllc1_div2_clk, pllc1_clk, div2); /* USB clock */ /* @@ -323,6 +287,7 @@ struct clk *main_clks[] = { &fsibck_clk, }; +/* DIV4 clocks */ static void div4_kick(struct clk *clk) { unsigned long value; @@ -346,6 +311,26 @@ static struct clk_div4_table div4_table = { .kick = div4_kick, }; +enum { + DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, + DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, + DIV4_NR +}; + +struct clk div4_clks[DIV4_NR] = { + [DIV4_I] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT), + [DIV4_ZG] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT), + [DIV4_B] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT), + [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), + [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), + [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), + [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), + [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), + [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), + [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), + [DIV4_CP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 0, 0x6fff, 0), +}; + /* DIV6 reparent */ enum { DIV6_HDMI, @@ -391,6 +376,16 @@ static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2), }; +/* DIV6 clocks */ +enum { + DIV6_SUB, + DIV6_NR +}; + +static struct clk div6_clks[DIV6_NR] = { + [DIV6_SUB] = SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0), +}; + /* HDMI1/2 clock */ static unsigned long hdmi12_recalc(struct clk *clk) { @@ -456,35 +451,6 @@ static struct clk fsidivs[] = { /* MSTP */ enum { - DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, - DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, - DIV4_NR -}; - -struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_ZG] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_B] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), - [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), - [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), - [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), - [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), - [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), - [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), - [DIV4_CP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 0, 0x6fff, 0), -}; - -enum { - DIV6_SUB, - DIV6_NR -}; - -static struct clk div6_clks[DIV6_NR] = { - [DIV6_SUB] = SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0), -}; - -enum { MSTP128, MSTP127, MSTP125, MSTP116, MSTP111, MSTP100, MSTP117, diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c new file mode 100644 index 000000000000..cd6855290b1f --- /dev/null +++ b/arch/arm/mach-shmobile/clock-r8a7778.c @@ -0,0 +1,107 @@ +/* + * r8a7778 clock framework support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * based on r8a7779 + * + * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2011 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * 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/io.h> +#include <linux/sh_clk.h> +#include <linux/clkdev.h> +#include <mach/common.h> + +#define MSTPCR0 IOMEM(0xffc80030) +#define MSTPCR1 IOMEM(0xffc80034) +#define MSTPCR3 IOMEM(0xffc8003c) +#define MSTPSR1 IOMEM(0xffc80044) +#define MSTPSR4 IOMEM(0xffc80048) +#define MSTPSR6 IOMEM(0xffc8004c) +#define MSTPCR4 IOMEM(0xffc80050) +#define MSTPCR5 IOMEM(0xffc80054) +#define MSTPCR6 IOMEM(0xffc80058) + +/* ioremap() through clock mapping mandatory to avoid + * collision with ARM coherent DMA virtual memory range. + */ + +static struct clk_mapping cpg_mapping = { + .phys = 0xffc80000, + .len = 0x80, +}; + +static struct clk clkp = { + .rate = 62500000, /* FIXME: shortcut */ + .flags = CLK_ENABLE_ON_INIT, + .mapping = &cpg_mapping, +}; + +static struct clk *main_clks[] = { + &clkp, +}; + +enum { + MSTP114, + MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, + MSTP016, MSTP015, + MSTP_NR }; + +static struct clk mstp_clks[MSTP_NR] = { + [MSTP114] = SH_CLK_MSTP32(&clkp, MSTPCR1, 14, 0), /* Ether */ + [MSTP026] = SH_CLK_MSTP32(&clkp, MSTPCR0, 26, 0), /* SCIF0 */ + [MSTP025] = SH_CLK_MSTP32(&clkp, MSTPCR0, 25, 0), /* SCIF1 */ + [MSTP024] = SH_CLK_MSTP32(&clkp, MSTPCR0, 24, 0), /* SCIF2 */ + [MSTP023] = SH_CLK_MSTP32(&clkp, MSTPCR0, 23, 0), /* SCIF3 */ + [MSTP022] = SH_CLK_MSTP32(&clkp, MSTPCR0, 22, 0), /* SCIF4 */ + [MSTP021] = SH_CLK_MSTP32(&clkp, MSTPCR0, 21, 0), /* SCIF5 */ + [MSTP016] = SH_CLK_MSTP32(&clkp, MSTPCR0, 16, 0), /* TMU0 */ + [MSTP015] = SH_CLK_MSTP32(&clkp, MSTPCR0, 15, 0), /* TMU1 */ +}; + +static struct clk_lookup lookups[] = { + /* MSTP32 clocks */ + CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP114]), /* Ether */ + CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */ + CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */ + CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */ + CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */ + CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */ + CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */ + CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */ + CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */ +}; + +void __init r8a7778_clock_init(void) +{ + int k, ret = 0; + + for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) + ret = clk_register(main_clks[k]); + + if (!ret) + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + if (!ret) + shmobile_clk_init(); + else + panic("failed to setup r8a7778 clocks\n"); +} diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index d9edeaf66007..31d5cd4d9787 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c @@ -17,13 +17,36 @@ * 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/bitops.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/io.h> #include <linux/sh_clk.h> #include <linux/clkdev.h> +#include <mach/clock.h> #include <mach/common.h> +/* + * MD1 = 1 MD1 = 0 + * (PLLA = 1500) (PLLA = 1600) + * (MHz) (MHz) + *------------------------------------------------+-------------------- + * clkz 1000 (2/3) 800 (1/2) + * clkzs 250 (1/6) 200 (1/8) + * clki 750 (1/2) 800 (1/2) + * clks 250 (1/6) 200 (1/8) + * clks1 125 (1/12) 100 (1/16) + * clks3 187.5 (1/8) 200 (1/8) + * clks4 93.7 (1/16) 100 (1/16) + * clkp 62.5 (1/24) 50 (1/32) + * clkg 62.5 (1/24) 66.6 (1/24) + * clkb, CLKOUT + * (MD2 = 0) 62.5 (1/24) 66.6 (1/24) + * (MD2 = 1) 41.6 (1/36) 50 (1/32) +*/ + +#define MD(nr) BIT(nr) + #define FRQMR IOMEM(0xffc80014) #define MSTPCR0 IOMEM(0xffc80030) #define MSTPCR1 IOMEM(0xffc80034) @@ -36,6 +59,9 @@ #define MSTPCR6 IOMEM(0xffc80058) #define MSTPCR7 IOMEM(0xffc80040) +#define MODEMR 0xffcc0020 + + /* ioremap() through clock mapping mandatory to avoid * collision with ARM coherent DMA virtual memory range. */ @@ -50,44 +76,43 @@ static struct clk_mapping cpg_mapping = { * from the platform code. */ static struct clk plla_clk = { - .rate = 1500000000, + /* .rate will be updated on r8a7779_clock_init() */ .mapping = &cpg_mapping, }; +/* + * clock ratio of these clock will be updated + * on r8a7779_clock_init() + */ +SH_FIXED_RATIO_CLK_SET(clkz_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clkzs_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clki_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clks_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clks1_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clks3_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clks4_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clkb_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clkout_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clkp_clk, plla_clk, 1, 1); +SH_FIXED_RATIO_CLK_SET(clkg_clk, plla_clk, 1, 1); + static struct clk *main_clks[] = { &plla_clk, -}; - -static int divisors[] = { 0, 0, 0, 6, 8, 12, 16, 0, 24, 32, 36, 0, 0, 0, 0, 0 }; - -static struct clk_div_mult_table div4_div_mult_table = { - .divisors = divisors, - .nr_divisors = ARRAY_SIZE(divisors), -}; - -static struct clk_div4_table div4_table = { - .div_mult_table = &div4_div_mult_table, -}; - -enum { DIV4_S, DIV4_OUT, DIV4_S4, DIV4_S3, DIV4_S1, DIV4_P, DIV4_NR }; - -static struct clk div4_clks[DIV4_NR] = { - [DIV4_S] = SH_CLK_DIV4(&plla_clk, FRQMR, 20, - 0x0018, CLK_ENABLE_ON_INIT), - [DIV4_OUT] = SH_CLK_DIV4(&plla_clk, FRQMR, 16, - 0x0700, CLK_ENABLE_ON_INIT), - [DIV4_S4] = SH_CLK_DIV4(&plla_clk, FRQMR, 12, - 0x0040, CLK_ENABLE_ON_INIT), - [DIV4_S3] = SH_CLK_DIV4(&plla_clk, FRQMR, 8, - 0x0010, CLK_ENABLE_ON_INIT), - [DIV4_S1] = SH_CLK_DIV4(&plla_clk, FRQMR, 4, - 0x0060, CLK_ENABLE_ON_INIT), - [DIV4_P] = SH_CLK_DIV4(&plla_clk, FRQMR, 0, - 0x0300, CLK_ENABLE_ON_INIT), + &clkz_clk, + &clkzs_clk, + &clki_clk, + &clks_clk, + &clks1_clk, + &clks3_clk, + &clks4_clk, + &clkb_clk, + &clkout_clk, + &clkp_clk, + &clkg_clk, }; enum { MSTP323, MSTP322, MSTP321, MSTP320, - MSTP115, + MSTP115, MSTP114, MSTP103, MSTP101, MSTP100, MSTP030, MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021, @@ -96,52 +121,29 @@ enum { MSTP323, MSTP322, MSTP321, MSTP320, MSTP_NR }; static struct clk mstp_clks[MSTP_NR] = { - [MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 23, 0), /* SDHI0 */ - [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */ - [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */ - [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */ - [MSTP115] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 15, 0), /* SATA */ - [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR1, 3, 0), /* DU */ - [MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 1, 0), /* USB2 */ - [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 0, 0), /* USB0/1 */ - [MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */ - [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0), /* I2C1 */ - [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0), /* I2C2 */ - [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0), /* I2C3 */ - [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */ - [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */ - [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */ - [MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0), /* SCIF3 */ - [MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0), /* SCIF4 */ - [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0), /* SCIF5 */ - [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), /* TMU0 */ - [MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), /* TMU1 */ - [MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), /* TMU2 */ - [MSTP007] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR0, 7, 0), /* HSPI */ -}; - -static unsigned long mul4_recalc(struct clk *clk) -{ - return clk->parent->rate * 4; -} - -static struct sh_clk_ops mul4_clk_ops = { - .recalc = mul4_recalc, -}; - -struct clk clkz_clk = { - .ops = &mul4_clk_ops, - .parent = &div4_clks[DIV4_S], -}; - -struct clk clkzs_clk = { - /* clks x 4 / 4 = clks */ - .parent = &div4_clks[DIV4_S], -}; - -static struct clk *late_main_clks[] = { - &clkz_clk, - &clkzs_clk, + [MSTP323] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 23, 0), /* SDHI0 */ + [MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */ + [MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */ + [MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */ + [MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */ + [MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */ + [MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 3, 0), /* DU */ + [MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 1, 0), /* USB2 */ + [MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 0, 0), /* USB0/1 */ + [MSTP030] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 30, 0), /* I2C0 */ + [MSTP029] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 29, 0), /* I2C1 */ + [MSTP028] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 28, 0), /* I2C2 */ + [MSTP027] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 27, 0), /* I2C3 */ + [MSTP026] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 26, 0), /* SCIF0 */ + [MSTP025] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 25, 0), /* SCIF1 */ + [MSTP024] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 24, 0), /* SCIF2 */ + [MSTP023] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 23, 0), /* SCIF3 */ + [MSTP022] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 22, 0), /* SCIF4 */ + [MSTP021] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 21, 0), /* SCIF5 */ + [MSTP016] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 16, 0), /* TMU0 */ + [MSTP015] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 15, 0), /* TMU1 */ + [MSTP014] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 14, 0), /* TMU2 */ + [MSTP007] = SH_CLK_MSTP32(&clks_clk, MSTPCR0, 7, 0), /* HSPI */ }; static struct clk_lookup lookups[] = { @@ -151,16 +153,17 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("clkzs_clk", &clkzs_clk), /* DIV4 clocks */ - CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_S]), - CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_OUT]), - CLKDEV_CON_ID("shyway4_clk", &div4_clks[DIV4_S4]), - CLKDEV_CON_ID("shyway3_clk", &div4_clks[DIV4_S3]), - CLKDEV_CON_ID("shyway1_clk", &div4_clks[DIV4_S1]), - CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("shyway_clk", &clks_clk), + CLKDEV_CON_ID("bus_clk", &clkout_clk), + CLKDEV_CON_ID("shyway4_clk", &clks4_clk), + CLKDEV_CON_ID("shyway3_clk", &clks3_clk), + CLKDEV_CON_ID("shyway1_clk", &clks1_clk), + CLKDEV_CON_ID("peripheral_clk", &clkp_clk), /* MSTP32 clocks */ CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */ CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */ + CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP114]), /* Ether */ CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */ CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */ CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ @@ -190,20 +193,60 @@ static struct clk_lookup lookups[] = { void __init r8a7779_clock_init(void) { + void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE); + u32 mode; int k, ret = 0; + BUG_ON(!modemr); + mode = ioread32(modemr); + iounmap(modemr); + + if (mode & MD(1)) { + plla_clk.rate = 1500000000; + + SH_CLK_SET_RATIO(&clkz_clk_ratio, 2, 3); + SH_CLK_SET_RATIO(&clkzs_clk_ratio, 1, 6); + SH_CLK_SET_RATIO(&clki_clk_ratio, 1, 2); + SH_CLK_SET_RATIO(&clks_clk_ratio, 1, 6); + SH_CLK_SET_RATIO(&clks1_clk_ratio, 1, 12); + SH_CLK_SET_RATIO(&clks3_clk_ratio, 1, 8); + SH_CLK_SET_RATIO(&clks4_clk_ratio, 1, 16); + SH_CLK_SET_RATIO(&clkp_clk_ratio, 1, 24); + SH_CLK_SET_RATIO(&clkg_clk_ratio, 1, 24); + if (mode & MD(2)) { + SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 36); + SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 36); + } else { + SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 24); + SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 24); + } + } else { + plla_clk.rate = 1600000000; + + SH_CLK_SET_RATIO(&clkz_clk_ratio, 1, 2); + SH_CLK_SET_RATIO(&clkzs_clk_ratio, 1, 8); + SH_CLK_SET_RATIO(&clki_clk_ratio, 1, 2); + SH_CLK_SET_RATIO(&clks_clk_ratio, 1, 8); + SH_CLK_SET_RATIO(&clks1_clk_ratio, 1, 16); + SH_CLK_SET_RATIO(&clks3_clk_ratio, 1, 8); + SH_CLK_SET_RATIO(&clks4_clk_ratio, 1, 16); + SH_CLK_SET_RATIO(&clkp_clk_ratio, 1, 32); + SH_CLK_SET_RATIO(&clkg_clk_ratio, 1, 24); + if (mode & MD(2)) { + SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 32); + SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 32); + } else { + SH_CLK_SET_RATIO(&clkb_clk_ratio, 1, 24); + SH_CLK_SET_RATIO(&clkout_clk_ratio, 1, 24); + } + } + for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) ret = clk_register(main_clks[k]); if (!ret) - ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); - - if (!ret) ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); - for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) - ret = clk_register(late_main_clks[k]); - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); if (!ret) diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c new file mode 100644 index 000000000000..bad9bf2e34d6 --- /dev/null +++ b/arch/arm/mach-shmobile/clock-r8a7790.c @@ -0,0 +1,93 @@ +/* + * r8a7790 clock framework support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/sh_clk.h> +#include <linux/clkdev.h> +#include <mach/common.h> + +#define CPG_BASE 0xe6150000 +#define CPG_LEN 0x1000 + +#define SMSTPCR2 0xe6150138 +#define SMSTPCR7 0xe615014c + +static struct clk_mapping cpg_mapping = { + .phys = CPG_BASE, + .len = CPG_LEN, +}; + +static struct clk p_clk = { + .rate = 65000000, /* shortcut for now */ + .mapping = &cpg_mapping, +}; + +static struct clk mp_clk = { + .rate = 52000000, /* shortcut for now */ + .mapping = &cpg_mapping, +}; + +static struct clk *main_clks[] = { + &p_clk, + &mp_clk, +}; + +enum { MSTP721, MSTP720, + MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP_NR }; +static struct clk mstp_clks[MSTP_NR] = { + [MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */ + [MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */ + [MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */ + [MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */ + [MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */ + [MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */ + [MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */ + [MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */ +}; + +static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), + CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), + CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]), + CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]), + CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]), + CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]), + CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]), + CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), +}; + +void __init r8a7790_clock_init(void) +{ + int k, ret = 0; + + for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) + ret = clk_register(main_clks[k]); + + if (!ret) + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + if (!ret) + shmobile_clk_init(); + else + panic("failed to setup r8a7790 clocks\n"); +} diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 45d21fe317f4..7e105932c09d 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <linux/sh_clk.h> #include <linux/clkdev.h> +#include <mach/clock.h> #include <mach/common.h> /* SH7372 registers */ @@ -83,39 +84,12 @@ struct clk sh7372_extal2_clk = { .rate = 48000000, }; -/* A fixed divide-by-2 block */ -static unsigned long div2_recalc(struct clk *clk) -{ - return clk->parent->rate / 2; -} - -static struct sh_clk_ops div2_clk_ops = { - .recalc = div2_recalc, -}; +SH_CLK_RATIO(div2, 1, 2); -/* Divide dv_clki by two */ -struct clk sh7372_dv_clki_div2_clk = { - .ops = &div2_clk_ops, - .parent = &sh7372_dv_clki_clk, -}; - -/* Divide extal1 by two */ -static struct clk extal1_div2_clk = { - .ops = &div2_clk_ops, - .parent = &sh7372_extal1_clk, -}; - -/* Divide extal2 by two */ -static struct clk extal2_div2_clk = { - .ops = &div2_clk_ops, - .parent = &sh7372_extal2_clk, -}; - -/* Divide extal2 by four */ -static struct clk extal2_div4_clk = { - .ops = &div2_clk_ops, - .parent = &extal2_div2_clk, -}; +SH_FIXED_RATIO_CLKg(sh7372_dv_clki_div2_clk, sh7372_dv_clki_clk, div2); +SH_FIXED_RATIO_CLK(extal1_div2_clk, sh7372_extal1_clk, div2); +SH_FIXED_RATIO_CLK(extal2_div2_clk, sh7372_extal2_clk, div2); +SH_FIXED_RATIO_CLK(extal2_div4_clk, extal2_div2_clk, div2); /* PLLC0 and PLLC1 */ static unsigned long pllc01_recalc(struct clk *clk) @@ -147,10 +121,7 @@ static struct clk pllc1_clk = { }; /* Divide PLLC1 by two */ -static struct clk pllc1_div2_clk = { - .ops = &div2_clk_ops, - .parent = &pllc1_clk, -}; +SH_FIXED_RATIO_CLK(pllc1_div2_clk, pllc1_clk, div2); /* PLLC2 */ @@ -342,7 +313,7 @@ static struct clk_div4_table div4_table = { }; enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_CSIR, - DIV4_ZTR, DIV4_ZT, DIV4_ZX, DIV4_HP, + DIV4_ZX, DIV4_HP, DIV4_ISPB, DIV4_S, DIV4_ZB, DIV4_ZB3, DIV4_CP, DIV4_DDRP, DIV4_NR }; @@ -355,8 +326,6 @@ static struct clk div4_clks[DIV4_NR] = { [DIV4_B] = DIV4(FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT), [DIV4_M1] = DIV4(FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), [DIV4_CSIR] = DIV4(FRQCRA, 0, 0x6fff, 0), - [DIV4_ZTR] = DIV4(FRQCRB, 20, 0x6fff, 0), - [DIV4_ZT] = DIV4(FRQCRB, 16, 0x6fff, 0), [DIV4_ZX] = DIV4(FRQCRB, 12, 0x6fff, 0), [DIV4_HP] = DIV4(FRQCRB, 4, 0x6fff, 0), [DIV4_ISPB] = DIV4(FRQCRC, 20, 0x6fff, 0), @@ -516,8 +485,6 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]), CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]), CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]), - CLKDEV_CON_ID("ztr_clk", &div4_clks[DIV4_ZTR]), - CLKDEV_CON_ID("zt_clk", &div4_clks[DIV4_ZT]), CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]), CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]), CLKDEV_CON_ID("ispb_clk", &div4_clks[DIV4_ISPB]), @@ -654,5 +621,4 @@ void __init sh7372_clock_init(void) shmobile_clk_init(); else panic("failed to setup sh7372 clocks\n"); - } diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 71843dd39e16..784fbaa4cc55 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -21,6 +21,8 @@ #include <linux/io.h> #include <linux/sh_clk.h> #include <linux/clkdev.h> +#include <asm/processor.h> +#include <mach/clock.h> #include <mach/common.h> #define FRQCRA IOMEM(0xe6150000) @@ -82,61 +84,16 @@ struct clk sh73a0_extal2_clk = { .rate = 48000000, }; -/* A fixed divide-by-2 block */ -static unsigned long div2_recalc(struct clk *clk) -{ - return clk->parent->rate / 2; -} - -static struct sh_clk_ops div2_clk_ops = { - .recalc = div2_recalc, -}; - -static unsigned long div7_recalc(struct clk *clk) -{ - return clk->parent->rate / 7; -} - -static struct sh_clk_ops div7_clk_ops = { - .recalc = div7_recalc, -}; - -static unsigned long div13_recalc(struct clk *clk) -{ - return clk->parent->rate / 13; -} - -static struct sh_clk_ops div13_clk_ops = { - .recalc = div13_recalc, -}; - -/* Divide extal1 by two */ -static struct clk extal1_div2_clk = { - .ops = &div2_clk_ops, - .parent = &sh73a0_extal1_clk, -}; - -/* Divide extal2 by two */ -static struct clk extal2_div2_clk = { - .ops = &div2_clk_ops, - .parent = &sh73a0_extal2_clk, -}; - static struct sh_clk_ops main_clk_ops = { .recalc = followparent_recalc, }; /* Main clock */ static struct clk main_clk = { + /* .parent wll be set on sh73a0_clock_init() */ .ops = &main_clk_ops, }; -/* Divide Main clock by two */ -static struct clk main_div2_clk = { - .ops = &div2_clk_ops, - .parent = &main_clk, -}; - /* PLL0, PLL1, PLL2, PLL3 */ static unsigned long pll_recalc(struct clk *clk) { @@ -192,21 +149,17 @@ static struct clk pll3_clk = { .enable_bit = 3, }; -/* Divide PLL */ -static struct clk pll1_div2_clk = { - .ops = &div2_clk_ops, - .parent = &pll1_clk, -}; - -static struct clk pll1_div7_clk = { - .ops = &div7_clk_ops, - .parent = &pll1_clk, -}; +/* A fixed divide block */ +SH_CLK_RATIO(div2, 1, 2); +SH_CLK_RATIO(div7, 1, 7); +SH_CLK_RATIO(div13, 1, 13); -static struct clk pll1_div13_clk = { - .ops = &div13_clk_ops, - .parent = &pll1_clk, -}; +SH_FIXED_RATIO_CLK(extal1_div2_clk, sh73a0_extal1_clk, div2); +SH_FIXED_RATIO_CLK(extal2_div2_clk, sh73a0_extal2_clk, div2); +SH_FIXED_RATIO_CLK(main_div2_clk, main_clk, div2); +SH_FIXED_RATIO_CLK(pll1_div2_clk, pll1_clk, div2); +SH_FIXED_RATIO_CLK(pll1_div7_clk, pll1_clk, div7); +SH_FIXED_RATIO_CLK(pll1_div13_clk, pll1_clk, div13); /* External input clock */ struct clk sh73a0_extcki_clk = { @@ -234,14 +187,24 @@ static struct clk *main_clks[] = { &sh73a0_extalr_clk, }; -static void div4_kick(struct clk *clk) +static int frqcr_kick(void) { - unsigned long value; + int i; + + /* set KICK bit in FRQCRB to update hardware setting, check success */ + __raw_writel(__raw_readl(FRQCRB) | (1 << 31), FRQCRB); + for (i = 1000; i; i--) + if (__raw_readl(FRQCRB) & (1 << 31)) + cpu_relax(); + else + return i; - /* set KICK bit in FRQCRB to update hardware setting */ - value = __raw_readl(FRQCRB); - value |= (1 << 31); - __raw_writel(value, FRQCRB); + return -ETIMEDOUT; +} + +static void div4_kick(struct clk *clk) +{ + frqcr_kick(); } static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, @@ -258,7 +221,7 @@ static struct clk_div4_table div4_table = { }; enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2, - DIV4_Z, DIV4_ZTR, DIV4_ZT, DIV4_ZX, DIV4_HP, DIV4_NR }; + DIV4_Z, DIV4_ZX, DIV4_HP, DIV4_NR }; #define DIV4(_reg, _bit, _mask, _flags) \ SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags) @@ -271,12 +234,24 @@ static struct clk div4_clks[DIV4_NR] = { [DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0), [DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0), [DIV4_Z] = SH_CLK_DIV4(&pll0_clk, FRQCRB, 24, 0x97f, 0), - [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0), - [DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0), [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0), [DIV4_HP] = DIV4(FRQCRB, 4, 0xdff, 0), }; +static unsigned long twd_recalc(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 4; +} + +static struct sh_clk_ops twd_clk_ops = { + .recalc = twd_recalc, +}; + +static struct clk twd_clk = { + .parent = &div4_clks[DIV4_Z], + .ops = &twd_clk_ops, +}; + enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1, DIV6_FLCTL, DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2, DIV6_FSIA, DIV6_FSIB, DIV6_SUB, @@ -471,6 +446,7 @@ static struct clk dsi1phy_clk = { static struct clk *late_main_clks[] = { &dsi0phy_clk, &dsi1phy_clk, + &twd_clk, }; enum { MSTP001, @@ -535,6 +511,7 @@ static struct clk mstp_clks[MSTP_NR] = { static struct clk_lookup lookups[] = { /* main clocks */ CLKDEV_CON_ID("r_clk", &r_clk), + CLKDEV_DEV_ID("smp_twd", &twd_clk), /* smp_twd */ /* DIV6 clocks */ CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]), diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c index e816ca9bd213..ad7df629d995 100644 --- a/arch/arm/mach-shmobile/clock.c +++ b/arch/arm/mach-shmobile/clock.c @@ -23,6 +23,19 @@ #include <linux/init.h> #include <linux/sh_clk.h> #include <linux/export.h> +#include <mach/clock.h> +#include <mach/common.h> + +unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk) +{ + struct clk_ratio *p = clk->priv; + + return clk->parent->rate / p->div * p->mul; +}; + +struct sh_clk_ops shmobile_fixed_ratio_clk_ops = { + .recalc = shmobile_fixed_ratio_clk_recalc, +}; int __init shmobile_clk_init(void) { diff --git a/arch/arm/mach-shmobile/include/mach/clock.h b/arch/arm/mach-shmobile/include/mach/clock.h new file mode 100644 index 000000000000..76ac61292e48 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/clock.h @@ -0,0 +1,39 @@ +#ifndef CLOCK_H +#define CLOCK_H + +unsigned long shmobile_fixed_ratio_clk_recalc(struct clk *clk); +extern struct sh_clk_ops shmobile_fixed_ratio_clk_ops; + +/* clock ratio */ +struct clk_ratio { + int mul; + int div; +}; + +#define SH_CLK_RATIO(name, m, d) \ +static struct clk_ratio name ##_ratio = { \ + .mul = m, \ + .div = d, \ +} + +#define SH_FIXED_RATIO_CLKg(name, p, r) \ +struct clk name = { \ + .parent = &p, \ + .ops = &shmobile_fixed_ratio_clk_ops,\ + .priv = &r ## _ratio, \ +} + +#define SH_FIXED_RATIO_CLK(name, p, r) \ +static SH_FIXED_RATIO_CLKg(name, p, r); + +#define SH_FIXED_RATIO_CLK_SET(name, p, m, d) \ + SH_CLK_RATIO(name, m, d); \ + SH_FIXED_RATIO_CLK(name, p, name); + +#define SH_CLK_SET_RATIO(p, m, d) \ +{ \ + (p)->mul = m; \ + (p)->div = d; \ +} + +#endif diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 1fef737a4c1a..4634a5d4b63f 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -16,60 +16,6 @@ extern struct platform_suspend_ops shmobile_suspend_ops; struct cpuidle_driver; extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv); -extern void sh7372_init_irq(void); -extern void sh7372_map_io(void); -extern void sh7372_earlytimer_init(void); -extern void sh7372_add_early_devices(void); -extern void sh7372_add_standard_devices(void); -extern void sh7372_add_early_devices_dt(void); -extern void sh7372_add_standard_devices_dt(void); -extern void sh7372_clock_init(void); -extern void sh7372_pinmux_init(void); -extern void sh7372_pm_init(void); -extern void sh7372_resume_core_standby_sysc(void); -extern int sh7372_do_idle_sysc(unsigned long sleep_mode); -extern struct clk sh7372_extal1_clk; -extern struct clk sh7372_extal2_clk; - -extern void sh73a0_init_delay(void); -extern void sh73a0_init_irq(void); -extern void sh73a0_init_irq_dt(void); -extern void sh73a0_map_io(void); -extern void sh73a0_earlytimer_init(void); -extern void sh73a0_add_early_devices(void); -extern void sh73a0_add_standard_devices(void); -extern void sh73a0_add_standard_devices_dt(void); -extern void sh73a0_clock_init(void); -extern void sh73a0_pinmux_init(void); -extern void sh73a0_pm_init(void); -extern struct clk sh73a0_extal1_clk; -extern struct clk sh73a0_extal2_clk; -extern struct clk sh73a0_extcki_clk; -extern struct clk sh73a0_extalr_clk; - -extern void r8a7740_meram_workaround(void); -extern void r8a7740_init_irq(void); -extern void r8a7740_map_io(void); -extern void r8a7740_add_early_devices(void); -extern void r8a7740_add_standard_devices(void); -extern void r8a7740_clock_init(u8 md_ck); -extern void r8a7740_pinmux_init(void); -extern void r8a7740_pm_init(void); - -extern void r8a7779_init_delay(void); -extern void r8a7779_init_irq(void); -extern void r8a7779_init_irq_extpin(int irlm); -extern void r8a7779_init_irq_dt(void); -extern void r8a7779_map_io(void); -extern void r8a7779_earlytimer_init(void); -extern void r8a7779_add_early_devices(void); -extern void r8a7779_add_standard_devices(void); -extern void r8a7779_add_standard_devices_dt(void); -extern void r8a7779_clock_init(void); -extern void r8a7779_pinmux_init(void); -extern void r8a7779_pm_init(void); -extern void r8a7779_register_twd(void); - #ifdef CONFIG_SUSPEND int shmobile_suspend_init(void); #else diff --git a/arch/arm/mach-shmobile/include/mach/r8a73a4.h b/arch/arm/mach-shmobile/include/mach/r8a73a4.h new file mode 100644 index 000000000000..f043103e32c9 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/r8a73a4.h @@ -0,0 +1,8 @@ +#ifndef __ASM_R8A73A4_H__ +#define __ASM_R8A73A4_H__ + +void r8a73a4_add_standard_devices(void); +void r8a73a4_clock_init(void); +void r8a73a4_pinmux_init(void); + +#endif /* __ASM_R8A73A4_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index c2583610ad36..abdc4d4efa28 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -532,6 +532,15 @@ enum { SHDMA_SLAVE_USBHS_RX, }; +extern void r8a7740_meram_workaround(void); +extern void r8a7740_init_irq(void); +extern void r8a7740_map_io(void); +extern void r8a7740_add_early_devices(void); +extern void r8a7740_add_standard_devices(void); +extern void r8a7740_clock_init(u8 md_ck); +extern void r8a7740_pinmux_init(void); +extern void r8a7740_pm_init(void); + #ifdef CONFIG_PM extern void __init r8a7740_init_pm_domains(void); #else diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h new file mode 100644 index 000000000000..951149e6bcca --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __ASM_R8A7778_H__ +#define __ASM_R8A7778_H__ + +#include <linux/sh_eth.h> + +extern void r8a7778_add_standard_devices(void); +extern void r8a7778_add_standard_devices_dt(void); +extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata); +extern void r8a7778_init_delay(void); +extern void r8a7778_init_irq(void); +extern void r8a7778_init_irq_dt(void); +extern void r8a7778_clock_init(void); +extern void r8a7778_init_irq_extpin(int irlm); + +#endif /* __ASM_R8A7778_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h index 8ea0ad18cdff..188b295938a5 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7779.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h @@ -3,323 +3,7 @@ #include <linux/sh_clk.h> #include <linux/pm_domain.h> - -/* Pin Function Controller: - * GPIO_FN_xx - GPIO used to select pin function - * GPIO_GP_x_x - GPIO mapped to real I/O pin on CPU - */ -enum { - GPIO_GP_0_0, GPIO_GP_0_1, GPIO_GP_0_2, GPIO_GP_0_3, - GPIO_GP_0_4, GPIO_GP_0_5, GPIO_GP_0_6, GPIO_GP_0_7, - GPIO_GP_0_8, GPIO_GP_0_9, GPIO_GP_0_10, GPIO_GP_0_11, - GPIO_GP_0_12, GPIO_GP_0_13, GPIO_GP_0_14, GPIO_GP_0_15, - GPIO_GP_0_16, GPIO_GP_0_17, GPIO_GP_0_18, GPIO_GP_0_19, - GPIO_GP_0_20, GPIO_GP_0_21, GPIO_GP_0_22, GPIO_GP_0_23, - GPIO_GP_0_24, GPIO_GP_0_25, GPIO_GP_0_26, GPIO_GP_0_27, - GPIO_GP_0_28, GPIO_GP_0_29, GPIO_GP_0_30, GPIO_GP_0_31, - - GPIO_GP_1_0, GPIO_GP_1_1, GPIO_GP_1_2, GPIO_GP_1_3, - GPIO_GP_1_4, GPIO_GP_1_5, GPIO_GP_1_6, GPIO_GP_1_7, - GPIO_GP_1_8, GPIO_GP_1_9, GPIO_GP_1_10, GPIO_GP_1_11, - GPIO_GP_1_12, GPIO_GP_1_13, GPIO_GP_1_14, GPIO_GP_1_15, - GPIO_GP_1_16, GPIO_GP_1_17, GPIO_GP_1_18, GPIO_GP_1_19, - GPIO_GP_1_20, GPIO_GP_1_21, GPIO_GP_1_22, GPIO_GP_1_23, - GPIO_GP_1_24, GPIO_GP_1_25, GPIO_GP_1_26, GPIO_GP_1_27, - GPIO_GP_1_28, GPIO_GP_1_29, GPIO_GP_1_30, GPIO_GP_1_31, - - GPIO_GP_2_0, GPIO_GP_2_1, GPIO_GP_2_2, GPIO_GP_2_3, - GPIO_GP_2_4, GPIO_GP_2_5, GPIO_GP_2_6, GPIO_GP_2_7, - GPIO_GP_2_8, GPIO_GP_2_9, GPIO_GP_2_10, GPIO_GP_2_11, - GPIO_GP_2_12, GPIO_GP_2_13, GPIO_GP_2_14, GPIO_GP_2_15, - GPIO_GP_2_16, GPIO_GP_2_17, GPIO_GP_2_18, GPIO_GP_2_19, - GPIO_GP_2_20, GPIO_GP_2_21, GPIO_GP_2_22, GPIO_GP_2_23, - GPIO_GP_2_24, GPIO_GP_2_25, GPIO_GP_2_26, GPIO_GP_2_27, - GPIO_GP_2_28, GPIO_GP_2_29, GPIO_GP_2_30, GPIO_GP_2_31, - - GPIO_GP_3_0, GPIO_GP_3_1, GPIO_GP_3_2, GPIO_GP_3_3, - GPIO_GP_3_4, GPIO_GP_3_5, GPIO_GP_3_6, GPIO_GP_3_7, - GPIO_GP_3_8, GPIO_GP_3_9, GPIO_GP_3_10, GPIO_GP_3_11, - GPIO_GP_3_12, GPIO_GP_3_13, GPIO_GP_3_14, GPIO_GP_3_15, - GPIO_GP_3_16, GPIO_GP_3_17, GPIO_GP_3_18, GPIO_GP_3_19, - GPIO_GP_3_20, GPIO_GP_3_21, GPIO_GP_3_22, GPIO_GP_3_23, - GPIO_GP_3_24, GPIO_GP_3_25, GPIO_GP_3_26, GPIO_GP_3_27, - GPIO_GP_3_28, GPIO_GP_3_29, GPIO_GP_3_30, GPIO_GP_3_31, - - GPIO_GP_4_0, GPIO_GP_4_1, GPIO_GP_4_2, GPIO_GP_4_3, - GPIO_GP_4_4, GPIO_GP_4_5, GPIO_GP_4_6, GPIO_GP_4_7, - GPIO_GP_4_8, GPIO_GP_4_9, GPIO_GP_4_10, GPIO_GP_4_11, - GPIO_GP_4_12, GPIO_GP_4_13, GPIO_GP_4_14, GPIO_GP_4_15, - GPIO_GP_4_16, GPIO_GP_4_17, GPIO_GP_4_18, GPIO_GP_4_19, - GPIO_GP_4_20, GPIO_GP_4_21, GPIO_GP_4_22, GPIO_GP_4_23, - GPIO_GP_4_24, GPIO_GP_4_25, GPIO_GP_4_26, GPIO_GP_4_27, - GPIO_GP_4_28, GPIO_GP_4_29, GPIO_GP_4_30, GPIO_GP_4_31, - - GPIO_GP_5_0, GPIO_GP_5_1, GPIO_GP_5_2, GPIO_GP_5_3, - GPIO_GP_5_4, GPIO_GP_5_5, GPIO_GP_5_6, GPIO_GP_5_7, - GPIO_GP_5_8, GPIO_GP_5_9, GPIO_GP_5_10, GPIO_GP_5_11, - GPIO_GP_5_12, GPIO_GP_5_13, GPIO_GP_5_14, GPIO_GP_5_15, - GPIO_GP_5_16, GPIO_GP_5_17, GPIO_GP_5_18, GPIO_GP_5_19, - GPIO_GP_5_20, GPIO_GP_5_21, GPIO_GP_5_22, GPIO_GP_5_23, - GPIO_GP_5_24, GPIO_GP_5_25, GPIO_GP_5_26, GPIO_GP_5_27, - GPIO_GP_5_28, GPIO_GP_5_29, GPIO_GP_5_30, GPIO_GP_5_31, - - GPIO_GP_6_0, GPIO_GP_6_1, GPIO_GP_6_2, GPIO_GP_6_3, - GPIO_GP_6_4, GPIO_GP_6_5, GPIO_GP_6_6, GPIO_GP_6_7, - GPIO_GP_6_8, - - GPIO_FN_AVS1, GPIO_FN_AVS2, GPIO_FN_A17, GPIO_FN_A18, - GPIO_FN_A19, - - /* IPSR0 */ - GPIO_FN_PWM1, GPIO_FN_PWMFSW0, - GPIO_FN_SCIF_CLK, GPIO_FN_TCLK0_C, GPIO_FN_BS, - GPIO_FN_FD2, GPIO_FN_ATADIR0, GPIO_FN_SDSELF, - GPIO_FN_HCTS1, GPIO_FN_A0, - GPIO_FN_FD3, GPIO_FN_A20, - GPIO_FN_A21, - GPIO_FN_A22, GPIO_FN_VI1_R0, - GPIO_FN_A23, GPIO_FN_FCLE, GPIO_FN_VI1_R1, - GPIO_FN_A24, GPIO_FN_FD4, - GPIO_FN_VI1_R2, GPIO_FN_SSI_WS78_B, GPIO_FN_A25, - GPIO_FN_FD5, - GPIO_FN_VI1_R3, GPIO_FN_SSI_SDATA7_B, - GPIO_FN_CLKOUT, GPIO_FN_PWM0_B, - GPIO_FN_SDSELF_B, GPIO_FN_RD_WR, GPIO_FN_FWE, GPIO_FN_ATAG0, - GPIO_FN_VI1_R7, GPIO_FN_HRTS1, - - /* IPSR1 */ - GPIO_FN_FD6, GPIO_FN_FD7, - GPIO_FN_FALE, - GPIO_FN_ATACS00, - GPIO_FN_FRE, GPIO_FN_ATACS10, GPIO_FN_VI1_R4, - GPIO_FN_HSCK1, GPIO_FN_SSI_SDATA8_B, - GPIO_FN_SSI_SDATA9, - GPIO_FN_FD0, GPIO_FN_ATARD0, GPIO_FN_VI1_R5, - GPIO_FN_HTX1, GPIO_FN_SSI_SCK9, - GPIO_FN_FD1, - GPIO_FN_ATAWR0, GPIO_FN_VI1_R6, GPIO_FN_HRX1, - GPIO_FN_SSI_WS9, GPIO_FN_MLB_CLK, GPIO_FN_PWM2, - GPIO_FN_MLB_SIG, GPIO_FN_PWM3, - GPIO_FN_MLB_DAT, GPIO_FN_PWM4, GPIO_FN_HTX0, - GPIO_FN_SDATA, GPIO_FN_SUB_TCK, - GPIO_FN_CC5_STATE2, GPIO_FN_CC5_STATE10, GPIO_FN_CC5_STATE18, - GPIO_FN_CC5_STATE26, GPIO_FN_CC5_STATE34, - - /* IPSR2 */ - GPIO_FN_HRX0, GPIO_FN_SCKZ, - GPIO_FN_SUB_TDI, GPIO_FN_CC5_STATE3, GPIO_FN_CC5_STATE11, - GPIO_FN_CC5_STATE19, GPIO_FN_CC5_STATE27, GPIO_FN_CC5_STATE35, - GPIO_FN_HSCK0, GPIO_FN_MTS, GPIO_FN_PWM5, - GPIO_FN_SSI_SDATA9_B, GPIO_FN_SUB_TDO, - GPIO_FN_CC5_STATE0, GPIO_FN_CC5_STATE8, GPIO_FN_CC5_STATE16, - GPIO_FN_CC5_STATE24, GPIO_FN_CC5_STATE32, GPIO_FN_HCTS0, - GPIO_FN_STM, GPIO_FN_PWM0_D, GPIO_FN_SCIF_CLK_C, - GPIO_FN_SUB_TRST, GPIO_FN_TCLK1_B, GPIO_FN_CC5_OSCOUT, GPIO_FN_HRTS0, - GPIO_FN_MDATA, GPIO_FN_SUB_TMS, - GPIO_FN_CC5_STATE1, GPIO_FN_CC5_STATE9, GPIO_FN_CC5_STATE17, - GPIO_FN_CC5_STATE25, GPIO_FN_CC5_STATE33, - GPIO_FN_LCDOUT0, GPIO_FN_DREQ0, GPIO_FN_GPS_CLK_B, GPIO_FN_AUDATA0, - GPIO_FN_LCDOUT1, GPIO_FN_DACK0, - GPIO_FN_DRACK0, GPIO_FN_GPS_SIGN_B, GPIO_FN_AUDATA1, - GPIO_FN_LCDOUT2, GPIO_FN_LCDOUT3, - GPIO_FN_LCDOUT4, GPIO_FN_LCDOUT5, - GPIO_FN_LCDOUT6, GPIO_FN_LCDOUT7, - GPIO_FN_LCDOUT8, GPIO_FN_DREQ1, GPIO_FN_SCL2, - GPIO_FN_AUDATA2, - - /* IPSR3 */ - GPIO_FN_LCDOUT9, GPIO_FN_DACK1, GPIO_FN_SDA2, - GPIO_FN_AUDATA3, GPIO_FN_LCDOUT10, - GPIO_FN_LCDOUT11, GPIO_FN_LCDOUT12, - GPIO_FN_LCDOUT13, GPIO_FN_LCDOUT14, - GPIO_FN_LCDOUT15, GPIO_FN_LCDOUT16, GPIO_FN_EX_WAIT1, - GPIO_FN_SCL1, GPIO_FN_TCLK1, GPIO_FN_AUDATA4, - GPIO_FN_LCDOUT17, GPIO_FN_EX_WAIT2, GPIO_FN_SDA1, GPIO_FN_GPS_MAG_B, - GPIO_FN_AUDATA5, GPIO_FN_LCDOUT18, - GPIO_FN_LCDOUT19, GPIO_FN_LCDOUT20, - GPIO_FN_LCDOUT21, GPIO_FN_LCDOUT22, - GPIO_FN_LCDOUT23, - GPIO_FN_QSTVA_QVS, GPIO_FN_SCL3_B, - GPIO_FN_QCLK, - GPIO_FN_QSTVB_QVE, GPIO_FN_SDA3_B, - GPIO_FN_SDA2_C, GPIO_FN_DACK0_B, GPIO_FN_DRACK0_B, - GPIO_FN_QSTH_QHS, - GPIO_FN_QSTB_QHE, - GPIO_FN_QCPV_QDE, - GPIO_FN_CAN1_TX, GPIO_FN_SCL2_C, GPIO_FN_REMOCON, - - /* IPSR4 */ - GPIO_FN_QPOLA, GPIO_FN_CAN_CLK_C, - GPIO_FN_QPOLB, GPIO_FN_CAN1_RX, - GPIO_FN_DREQ0_B, GPIO_FN_SSI_SCK78_B, - GPIO_FN_VI2_DATA0_VI2_B0, GPIO_FN_PWM6, - GPIO_FN_AUDCK, GPIO_FN_PWMFSW0_B, - GPIO_FN_VI2_DATA1_VI2_B1, GPIO_FN_PWM0, - GPIO_FN_AUDSYNC, - GPIO_FN_VI2_G0, - GPIO_FN_VI2_G1, GPIO_FN_VI2_G2, - GPIO_FN_VI2_G3, GPIO_FN_VI2_G4, - GPIO_FN_VI2_G5, GPIO_FN_VI2_DATA2_VI2_B2, - GPIO_FN_SCL1_B, GPIO_FN_AUDATA6, - GPIO_FN_VI2_DATA3_VI2_B3, - GPIO_FN_SDA1_B, GPIO_FN_AUDATA7, - GPIO_FN_VI2_G6, - GPIO_FN_VI2_G7, GPIO_FN_VI2_R0, - GPIO_FN_VI2_R1, GPIO_FN_VI2_R2, - GPIO_FN_VI2_R3, GPIO_FN_VI2_DATA4_VI2_B4, - GPIO_FN_SCL2_B, - - /* IPSR5 */ - GPIO_FN_VI2_DATA5_VI2_B5, GPIO_FN_SDA2_B, - GPIO_FN_VI2_R4, GPIO_FN_VI2_R5, - GPIO_FN_VI2_R6, GPIO_FN_VI2_R7, - GPIO_FN_SCL2_D, GPIO_FN_SDA2_D, - GPIO_FN_VI2_CLKENB, - GPIO_FN_SCL1_D, GPIO_FN_VI2_FIELD, - GPIO_FN_SDA1_D, GPIO_FN_VI2_HSYNC, - GPIO_FN_VI3_HSYNC, GPIO_FN_VI2_VSYNC, - GPIO_FN_VI3_VSYNC, - GPIO_FN_VI2_CLK, - GPIO_FN_VI1_CLKENB, GPIO_FN_VI3_CLKENB, - GPIO_FN_AUDIO_CLKC, GPIO_FN_SPEEDIN, - GPIO_FN_GPS_SIGN_D, GPIO_FN_VI2_DATA6_VI2_B6, - GPIO_FN_TCLK0, GPIO_FN_QSTVA_B_QVS_B, - GPIO_FN_AUDIO_CLKOUT_B, GPIO_FN_GPS_MAG_D, - GPIO_FN_VI2_DATA7_VI2_B7, - GPIO_FN_VI1_FIELD, GPIO_FN_VI3_FIELD, - GPIO_FN_AUDIO_CLKOUT, GPIO_FN_GPS_CLK_C, - GPIO_FN_GPS_CLK_D, GPIO_FN_AUDIO_CLKA, GPIO_FN_CAN_TXCLK, - GPIO_FN_AUDIO_CLKB, GPIO_FN_CAN_DEBUGOUT0, - GPIO_FN_MOUT0, - - /* IPSR6 */ - GPIO_FN_SSI_SCK0129, GPIO_FN_CAN_DEBUGOUT1, GPIO_FN_MOUT1, - GPIO_FN_SSI_WS0129, GPIO_FN_CAN_DEBUGOUT2, GPIO_FN_MOUT2, - GPIO_FN_SSI_SDATA0, GPIO_FN_CAN_DEBUGOUT3, GPIO_FN_MOUT5, - GPIO_FN_SSI_SDATA1, GPIO_FN_CAN_DEBUGOUT4, GPIO_FN_MOUT6, - GPIO_FN_SSI_SDATA2, GPIO_FN_CAN_DEBUGOUT5, GPIO_FN_SSI_SCK34, - GPIO_FN_CAN_DEBUGOUT6, GPIO_FN_CAN0_TX_B, GPIO_FN_IERX, - GPIO_FN_SSI_SCK9_C, GPIO_FN_SSI_WS34, GPIO_FN_CAN_DEBUGOUT7, - GPIO_FN_CAN0_RX_B, GPIO_FN_IETX, GPIO_FN_SSI_WS9_C, - GPIO_FN_SSI_SDATA3, GPIO_FN_PWM0_C, GPIO_FN_CAN_DEBUGOUT8, - GPIO_FN_CAN_CLK_B, GPIO_FN_IECLK, GPIO_FN_SCIF_CLK_B, GPIO_FN_TCLK0_B, - GPIO_FN_SSI_SDATA4, GPIO_FN_CAN_DEBUGOUT9, GPIO_FN_SSI_SDATA9_C, - GPIO_FN_SSI_SCK5, GPIO_FN_ADICLK, GPIO_FN_CAN_DEBUGOUT10, - GPIO_FN_TCLK0_D, GPIO_FN_SSI_WS5, GPIO_FN_ADICS_SAMP, - GPIO_FN_CAN_DEBUGOUT11, GPIO_FN_SSI_SDATA5, - GPIO_FN_ADIDATA, GPIO_FN_CAN_DEBUGOUT12, - GPIO_FN_SSI_SCK6, GPIO_FN_ADICHS0, GPIO_FN_CAN0_TX, GPIO_FN_IERX_B, - - /* IPSR7 */ - GPIO_FN_SSI_WS6, GPIO_FN_ADICHS1, GPIO_FN_CAN0_RX, GPIO_FN_IETX_B, - GPIO_FN_SSI_SDATA6, GPIO_FN_ADICHS2, GPIO_FN_CAN_CLK, GPIO_FN_IECLK_B, - GPIO_FN_SSI_SCK78, GPIO_FN_CAN_DEBUGOUT13, - GPIO_FN_SSI_SCK9_B, GPIO_FN_SSI_WS78, - GPIO_FN_CAN_DEBUGOUT14, GPIO_FN_SSI_WS9_B, - GPIO_FN_SSI_SDATA7, GPIO_FN_CAN_DEBUGOUT15, - GPIO_FN_TCLK1_C, - GPIO_FN_SSI_SDATA8, GPIO_FN_VSP, - GPIO_FN_ATACS01, - GPIO_FN_ATACS11, GPIO_FN_CC5_TDO, - GPIO_FN_ATADIR1, GPIO_FN_CC5_TRST, - GPIO_FN_ATAG1, GPIO_FN_CC5_TMS, - GPIO_FN_ATARD1, GPIO_FN_CC5_TCK, - GPIO_FN_ATAWR1, GPIO_FN_CC5_TDI, - GPIO_FN_DREQ2, GPIO_FN_DACK2, - - /* IPSR8 */ - GPIO_FN_AD_CLK, - GPIO_FN_CC5_STATE4, GPIO_FN_CC5_STATE12, GPIO_FN_CC5_STATE20, - GPIO_FN_CC5_STATE28, GPIO_FN_CC5_STATE36, - GPIO_FN_AD_DI, - GPIO_FN_CC5_STATE5, GPIO_FN_CC5_STATE13, GPIO_FN_CC5_STATE21, - GPIO_FN_CC5_STATE29, GPIO_FN_CC5_STATE37, - GPIO_FN_CAN_DEBUG_HW_TRIGGER, GPIO_FN_AD_DO, - GPIO_FN_CC5_STATE6, GPIO_FN_CC5_STATE14, GPIO_FN_CC5_STATE22, - GPIO_FN_CC5_STATE30, GPIO_FN_CC5_STATE38, - GPIO_FN_CAN_STEP0, GPIO_FN_AD_NCS, GPIO_FN_CC5_STATE7, - GPIO_FN_CC5_STATE15, GPIO_FN_CC5_STATE23, GPIO_FN_CC5_STATE31, - GPIO_FN_CC5_STATE39, GPIO_FN_FMCLK, GPIO_FN_RDS_CLK, GPIO_FN_PCMOE, - GPIO_FN_BPFCLK, GPIO_FN_PCMWE, GPIO_FN_FMIN, GPIO_FN_RDS_DATA, - GPIO_FN_VI0_CLK, GPIO_FN_VI0_CLKENB, - GPIO_FN_HTX1_B, GPIO_FN_MT1_SYNC, GPIO_FN_VI0_FIELD, - GPIO_FN_HRX1_B, GPIO_FN_VI0_HSYNC, GPIO_FN_VI0_DATA0_B_VI0_B0_B, - GPIO_FN_HSCK1_B, - GPIO_FN_VI0_VSYNC, GPIO_FN_VI0_DATA1_B_VI0_B1_B, - GPIO_FN_PWMFSW0_C, - - /* IPSR9 */ - GPIO_FN_VI0_DATA0_VI0_B0, GPIO_FN_HRTS1_B, GPIO_FN_MT1_VCXO, - GPIO_FN_VI0_DATA1_VI0_B1, GPIO_FN_HCTS1_B, GPIO_FN_MT1_PWM, - GPIO_FN_VI0_DATA2_VI0_B2, GPIO_FN_VI0_DATA3_VI0_B3, - GPIO_FN_VI0_DATA4_VI0_B4, - GPIO_FN_VI0_DATA5_VI0_B5, GPIO_FN_VI0_DATA6_VI0_B6, - GPIO_FN_ARM_TRACEDATA_0, GPIO_FN_VI0_DATA7_VI0_B7, - GPIO_FN_ARM_TRACEDATA_1, GPIO_FN_VI0_G0, - GPIO_FN_SSI_SCK78_C, GPIO_FN_ARM_TRACEDATA_2, - GPIO_FN_VI0_G1, GPIO_FN_SSI_WS78_C, - GPIO_FN_ARM_TRACEDATA_3, GPIO_FN_VI0_G2, GPIO_FN_ETH_TXD1, - GPIO_FN_ARM_TRACEDATA_4, GPIO_FN_TS_SPSYNC0, - GPIO_FN_VI0_G3, GPIO_FN_ETH_CRS_DV, - GPIO_FN_ARM_TRACEDATA_5, GPIO_FN_TS_SDAT0, GPIO_FN_VI0_G4, - GPIO_FN_ETH_TX_EN, GPIO_FN_ARM_TRACEDATA_6, - GPIO_FN_VI0_G5, GPIO_FN_ETH_RX_ER, - GPIO_FN_ARM_TRACEDATA_7, GPIO_FN_VI0_G6, GPIO_FN_ETH_RXD0, - GPIO_FN_ARM_TRACEDATA_8, GPIO_FN_VI0_G7, - GPIO_FN_ETH_RXD1, GPIO_FN_ARM_TRACEDATA_9, - - /* IPSR10 */ - GPIO_FN_VI0_R0, GPIO_FN_SSI_SDATA7_C, GPIO_FN_DREQ1_B, - GPIO_FN_ARM_TRACEDATA_10, GPIO_FN_DREQ0_C, GPIO_FN_VI0_R1, - GPIO_FN_SSI_SDATA8_C, GPIO_FN_DACK1_B, GPIO_FN_ARM_TRACEDATA_11, - GPIO_FN_DACK0_C, GPIO_FN_DRACK0_C, GPIO_FN_VI0_R2, GPIO_FN_ETH_LINK, - GPIO_FN_ARM_TRACEDATA_12, - GPIO_FN_VI0_R3, GPIO_FN_ETH_MAGIC, - GPIO_FN_ARM_TRACEDATA_13, GPIO_FN_VI0_R4, GPIO_FN_ETH_REFCLK, - GPIO_FN_ARM_TRACEDATA_14, - GPIO_FN_MT1_CLK, GPIO_FN_TS_SCK0, GPIO_FN_VI0_R5, GPIO_FN_ETH_TXD0, - GPIO_FN_ARM_TRACEDATA_15, - GPIO_FN_MT1_D, GPIO_FN_TS_SDEN0, GPIO_FN_VI0_R6, GPIO_FN_ETH_MDC, - GPIO_FN_DREQ2_C, GPIO_FN_TRACECLK, - GPIO_FN_MT1_BEN, GPIO_FN_PWMFSW0_D, GPIO_FN_VI0_R7, GPIO_FN_ETH_MDIO, - GPIO_FN_DACK2_C, GPIO_FN_SCIF_CLK_D, - GPIO_FN_TRACECTL, GPIO_FN_MT1_PEN, GPIO_FN_VI1_CLK, GPIO_FN_SIM_D, - GPIO_FN_SDA3, GPIO_FN_VI1_HSYNC, GPIO_FN_VI3_CLK, GPIO_FN_SSI_SCK4, - GPIO_FN_GPS_SIGN_C, GPIO_FN_PWMFSW0_E, GPIO_FN_VI1_VSYNC, - GPIO_FN_AUDIO_CLKOUT_C, GPIO_FN_SSI_WS4, GPIO_FN_SIM_CLK, - GPIO_FN_GPS_MAG_C, GPIO_FN_SPV_TRST, GPIO_FN_SCL3, - - /* IPSR11 */ - GPIO_FN_VI1_DATA0_VI1_B0, GPIO_FN_SIM_RST, - GPIO_FN_SPV_TCK, GPIO_FN_ADICLK_B, GPIO_FN_VI1_DATA1_VI1_B1, - GPIO_FN_MT0_CLK, GPIO_FN_SPV_TMS, - GPIO_FN_ADICS_B_SAMP_B, GPIO_FN_VI1_DATA2_VI1_B2, - GPIO_FN_MT0_D, GPIO_FN_SPVTDI, GPIO_FN_ADIDATA_B, - GPIO_FN_VI1_DATA3_VI1_B3, GPIO_FN_MT0_BEN, - GPIO_FN_SPV_TDO, GPIO_FN_ADICHS0_B, GPIO_FN_VI1_DATA4_VI1_B4, - GPIO_FN_MT0_PEN, GPIO_FN_SPA_TRST, - GPIO_FN_ADICHS1_B, GPIO_FN_VI1_DATA5_VI1_B5, - GPIO_FN_MT0_SYNC, GPIO_FN_SPA_TCK, - GPIO_FN_ADICHS2_B, GPIO_FN_VI1_DATA6_VI1_B6, - GPIO_FN_MT0_VCXO, GPIO_FN_SPA_TMS, - GPIO_FN_VI1_DATA7_VI1_B7, GPIO_FN_MT0_PWM, - GPIO_FN_SPA_TDI, GPIO_FN_VI1_G0, GPIO_FN_VI3_DATA0, - GPIO_FN_TS_SCK1, GPIO_FN_DREQ2_B, - GPIO_FN_SPA_TDO, GPIO_FN_HCTS0_B, GPIO_FN_VI1_G1, GPIO_FN_VI3_DATA1, - GPIO_FN_SSI_SCK1, GPIO_FN_TS_SDEN1, GPIO_FN_DACK2_B, - GPIO_FN_HRTS0_B, - - /* IPSR12 */ - GPIO_FN_VI1_G2, GPIO_FN_VI3_DATA2, GPIO_FN_SSI_WS1, GPIO_FN_TS_SPSYNC1, - GPIO_FN_HSCK0_B, GPIO_FN_VI1_G3, GPIO_FN_VI3_DATA3, - GPIO_FN_SSI_SCK2, GPIO_FN_TS_SDAT1, GPIO_FN_SCL1_C, GPIO_FN_HTX0_B, - GPIO_FN_VI1_G4, GPIO_FN_VI3_DATA4, GPIO_FN_SSI_WS2, GPIO_FN_SDA1_C, - GPIO_FN_SIM_RST_B, GPIO_FN_HRX0_B, GPIO_FN_VI1_G5, GPIO_FN_VI3_DATA5, - GPIO_FN_GPS_CLK, GPIO_FN_FSE, GPIO_FN_SIM_D_B, - GPIO_FN_VI1_G6, GPIO_FN_VI3_DATA6, GPIO_FN_GPS_SIGN, GPIO_FN_FRB, - GPIO_FN_SIM_CLK_B, GPIO_FN_VI1_G7, GPIO_FN_VI3_DATA7, - GPIO_FN_GPS_MAG, GPIO_FN_FCE, -}; +#include <linux/sh_eth.h> struct platform_device; @@ -339,6 +23,20 @@ static inline struct r8a7779_pm_ch *to_r8a7779_ch(struct generic_pm_domain *d) return &container_of(d, struct r8a7779_pm_domain, genpd)->ch; } +extern void r8a7779_init_delay(void); +extern void r8a7779_init_irq(void); +extern void r8a7779_init_irq_extpin(int irlm); +extern void r8a7779_init_irq_dt(void); +extern void r8a7779_map_io(void); +extern void r8a7779_earlytimer_init(void); +extern void r8a7779_add_early_devices(void); +extern void r8a7779_add_standard_devices(void); +extern void r8a7779_add_standard_devices_dt(void); +extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata); +extern void r8a7779_clock_init(void); +extern void r8a7779_pinmux_init(void); +extern void r8a7779_pm_init(void); +extern void r8a7779_register_twd(void); extern int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch); extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch); diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h new file mode 100644 index 000000000000..2e919e61fa0d --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h @@ -0,0 +1,9 @@ +#ifndef __ASM_R8A7790_H__ +#define __ASM_R8A7790_H__ + +void r8a7790_add_standard_devices(void); +void r8a7790_clock_init(void); +void r8a7790_pinmux_init(void); +void r8a7790_timer_init(void); + +#endif /* __ASM_R8A7790_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 7ded4ebaf5cc..fd7cba024c39 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -449,6 +449,18 @@ extern struct clk sh7372_dv_clki_clk; extern struct clk sh7372_dv_clki_div2_clk; extern struct clk sh7372_pllc2_clk; +extern void sh7372_init_irq(void); +extern void sh7372_map_io(void); +extern void sh7372_earlytimer_init(void); +extern void sh7372_add_early_devices(void); +extern void sh7372_add_standard_devices(void); +extern void sh7372_add_early_devices_dt(void); +extern void sh7372_add_standard_devices_dt(void); +extern void sh7372_clock_init(void); +extern void sh7372_pinmux_init(void); +extern void sh7372_pm_init(void); +extern void sh7372_resume_core_standby_sysc(void); +extern int sh7372_do_idle_sysc(unsigned long sleep_mode); extern void sh7372_intcs_suspend(void); extern void sh7372_intcs_resume(void); extern void sh7372_intca_suspend(void); diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h index fbc1584d6712..eb7a4320d487 100644 --- a/arch/arm/mach-shmobile/include/mach/sh73a0.h +++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h @@ -444,6 +444,21 @@ enum { #define SH73A0_PINT0_IRQ(irq) ((irq) + 700) #define SH73A0_PINT1_IRQ(irq) ((irq) + 732) +extern void sh73a0_init_delay(void); +extern void sh73a0_init_irq(void); +extern void sh73a0_init_irq_dt(void); +extern void sh73a0_map_io(void); +extern void sh73a0_earlytimer_init(void); +extern void sh73a0_add_early_devices(void); +extern void sh73a0_add_standard_devices(void); +extern void sh73a0_add_standard_devices_dt(void); +extern void sh73a0_clock_init(void); +extern void sh73a0_pinmux_init(void); +extern void sh73a0_pm_init(void); +extern struct clk sh73a0_extal1_clk; +extern struct clk sh73a0_extal2_clk; +extern struct clk sh73a0_extcki_clk; +extern struct clk sh73a0_extalr_clk; extern struct smp_operations sh73a0_smp_ops; #endif /* __ASM_SH73A0_H__ */ diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c index 9a69a31918ba..b741c8409a5a 100644 --- a/arch/arm/mach-shmobile/intc-r8a7740.c +++ b/arch/arm/mach-shmobile/intc-r8a7740.c @@ -18,620 +18,39 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <linux/kernel.h> #include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/io.h> -#include <linux/sh_intc.h> -#include <mach/intc.h> -#include <mach/irqs.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> - -/* - * INTCA - */ -enum { - UNUSED_INTCA = 0, - - /* interrupt sources INTCA */ - DIRC, - ATAPI, - IIC1_ALI, IIC1_TACKI, IIC1_WAITI, IIC1_DTEI, - AP_ARM_COMMTX, AP_ARM_COMMRX, - MFI, MFIS, - BBIF1, BBIF2, - USBHSDMAC, - USBF_OUL_SOF, USBF_IXL_INT, - SGX540, - CMT1_0, CMT1_1, CMT1_2, CMT1_3, - CMT2, - CMT3, - KEYSC, - SCIFA0, SCIFA1, SCIFA2, SCIFA3, - MSIOF2, MSIOF1, - SCIFA4, SCIFA5, SCIFB, - FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, - SDHI0_0, SDHI0_1, SDHI0_2, SDHI0_3, - SDHI1_0, SDHI1_1, SDHI1_2, SDHI1_3, - AP_ARM_L2CINT, - IRDA, - TPU0, - SCIFA6, SCIFA7, - GbEther, - ICBS0, - DDM, - SDHI2_0, SDHI2_1, SDHI2_2, SDHI2_3, - RWDT0, - DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3, - DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR, - DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3, - DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR, - DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3, - DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR, - SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, - HDMI, - USBH_INT, USBH_OHCI, USBH_EHCI, USBH_PME, USBH_BIND, - RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, - SPU2_0, SPU2_1, - FSI, FMSI, - HDMI_SSS, HDMI_KEY, - IPMMU, - AP_ARM_CTIIRQ, AP_ARM_PMURQ, - MFIS2, - CPORTR2S, - CMT14, CMT15, - MMCIF_0, MMCIF_1, MMCIF_2, - SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI, - STPRO_0, STPRO_1, STPRO_2, STPRO_3, STPRO_4, - - /* interrupt groups INTCA */ - DMAC1_1, DMAC1_2, - DMAC2_1, DMAC2_2, - DMAC3_1, DMAC3_2, - AP_ARM1, AP_ARM2, - SDHI0, SDHI1, SDHI2, - SHWYSTAT, - USBF, USBH1, USBH2, - RSPI, SPU2, FLCTL, IIC1, -}; - -static struct intc_vect intca_vectors[] __initdata = { - INTC_VECT(DIRC, 0x0560), - INTC_VECT(ATAPI, 0x05E0), - INTC_VECT(IIC1_ALI, 0x0780), - INTC_VECT(IIC1_TACKI, 0x07A0), - INTC_VECT(IIC1_WAITI, 0x07C0), - INTC_VECT(IIC1_DTEI, 0x07E0), - INTC_VECT(AP_ARM_COMMTX, 0x0840), - INTC_VECT(AP_ARM_COMMRX, 0x0860), - INTC_VECT(MFI, 0x0900), - INTC_VECT(MFIS, 0x0920), - INTC_VECT(BBIF1, 0x0940), - INTC_VECT(BBIF2, 0x0960), - INTC_VECT(USBHSDMAC, 0x0A00), - INTC_VECT(USBF_OUL_SOF, 0x0A20), - INTC_VECT(USBF_IXL_INT, 0x0A40), - INTC_VECT(SGX540, 0x0A60), - INTC_VECT(CMT1_0, 0x0B00), - INTC_VECT(CMT1_1, 0x0B20), - INTC_VECT(CMT1_2, 0x0B40), - INTC_VECT(CMT1_3, 0x0B60), - INTC_VECT(CMT2, 0x0B80), - INTC_VECT(CMT3, 0x0BA0), - INTC_VECT(KEYSC, 0x0BE0), - INTC_VECT(SCIFA0, 0x0C00), - INTC_VECT(SCIFA1, 0x0C20), - INTC_VECT(SCIFA2, 0x0C40), - INTC_VECT(SCIFA3, 0x0C60), - INTC_VECT(MSIOF2, 0x0C80), - INTC_VECT(MSIOF1, 0x0D00), - INTC_VECT(SCIFA4, 0x0D20), - INTC_VECT(SCIFA5, 0x0D40), - INTC_VECT(SCIFB, 0x0D60), - INTC_VECT(FLCTL_FLSTEI, 0x0D80), - INTC_VECT(FLCTL_FLTENDI, 0x0DA0), - INTC_VECT(FLCTL_FLTREQ0I, 0x0DC0), - INTC_VECT(FLCTL_FLTREQ1I, 0x0DE0), - INTC_VECT(SDHI0_0, 0x0E00), - INTC_VECT(SDHI0_1, 0x0E20), - INTC_VECT(SDHI0_2, 0x0E40), - INTC_VECT(SDHI0_3, 0x0E60), - INTC_VECT(SDHI1_0, 0x0E80), - INTC_VECT(SDHI1_1, 0x0EA0), - INTC_VECT(SDHI1_2, 0x0EC0), - INTC_VECT(SDHI1_3, 0x0EE0), - INTC_VECT(AP_ARM_L2CINT, 0x0FA0), - INTC_VECT(IRDA, 0x0480), - INTC_VECT(TPU0, 0x04A0), - INTC_VECT(SCIFA6, 0x04C0), - INTC_VECT(SCIFA7, 0x04E0), - INTC_VECT(GbEther, 0x0500), - INTC_VECT(ICBS0, 0x0540), - INTC_VECT(DDM, 0x1140), - INTC_VECT(SDHI2_0, 0x1200), - INTC_VECT(SDHI2_1, 0x1220), - INTC_VECT(SDHI2_2, 0x1240), - INTC_VECT(SDHI2_3, 0x1260), - INTC_VECT(RWDT0, 0x1280), - INTC_VECT(DMAC1_1_DEI0, 0x2000), - INTC_VECT(DMAC1_1_DEI1, 0x2020), - INTC_VECT(DMAC1_1_DEI2, 0x2040), - INTC_VECT(DMAC1_1_DEI3, 0x2060), - INTC_VECT(DMAC1_2_DEI4, 0x2080), - INTC_VECT(DMAC1_2_DEI5, 0x20A0), - INTC_VECT(DMAC1_2_DADERR, 0x20C0), - INTC_VECT(DMAC2_1_DEI0, 0x2100), - INTC_VECT(DMAC2_1_DEI1, 0x2120), - INTC_VECT(DMAC2_1_DEI2, 0x2140), - INTC_VECT(DMAC2_1_DEI3, 0x2160), - INTC_VECT(DMAC2_2_DEI4, 0x2180), - INTC_VECT(DMAC2_2_DEI5, 0x21A0), - INTC_VECT(DMAC2_2_DADERR, 0x21C0), - INTC_VECT(DMAC3_1_DEI0, 0x2200), - INTC_VECT(DMAC3_1_DEI1, 0x2220), - INTC_VECT(DMAC3_1_DEI2, 0x2240), - INTC_VECT(DMAC3_1_DEI3, 0x2260), - INTC_VECT(DMAC3_2_DEI4, 0x2280), - INTC_VECT(DMAC3_2_DEI5, 0x22A0), - INTC_VECT(DMAC3_2_DADERR, 0x22C0), - INTC_VECT(SHWYSTAT_RT, 0x1300), - INTC_VECT(SHWYSTAT_HS, 0x1320), - INTC_VECT(SHWYSTAT_COM, 0x1340), - INTC_VECT(USBH_INT, 0x1540), - INTC_VECT(USBH_OHCI, 0x1560), - INTC_VECT(USBH_EHCI, 0x1580), - INTC_VECT(USBH_PME, 0x15A0), - INTC_VECT(USBH_BIND, 0x15C0), - INTC_VECT(HDMI, 0x1700), - INTC_VECT(RSPI_OVRF, 0x1780), - INTC_VECT(RSPI_SPTEF, 0x17A0), - INTC_VECT(RSPI_SPRF, 0x17C0), - INTC_VECT(SPU2_0, 0x1800), - INTC_VECT(SPU2_1, 0x1820), - INTC_VECT(FSI, 0x1840), - INTC_VECT(FMSI, 0x1860), - INTC_VECT(HDMI_SSS, 0x18A0), - INTC_VECT(HDMI_KEY, 0x18C0), - INTC_VECT(IPMMU, 0x1920), - INTC_VECT(AP_ARM_CTIIRQ, 0x1980), - INTC_VECT(AP_ARM_PMURQ, 0x19A0), - INTC_VECT(MFIS2, 0x1A00), - INTC_VECT(CPORTR2S, 0x1A20), - INTC_VECT(CMT14, 0x1A40), - INTC_VECT(CMT15, 0x1A60), - INTC_VECT(MMCIF_0, 0x1AA0), - INTC_VECT(MMCIF_1, 0x1AC0), - INTC_VECT(MMCIF_2, 0x1AE0), - INTC_VECT(SIM_ERI, 0x1C00), - INTC_VECT(SIM_RXI, 0x1C20), - INTC_VECT(SIM_TXI, 0x1C40), - INTC_VECT(SIM_TEI, 0x1C60), - INTC_VECT(STPRO_0, 0x1C80), - INTC_VECT(STPRO_1, 0x1CA0), - INTC_VECT(STPRO_2, 0x1CC0), - INTC_VECT(STPRO_3, 0x1CE0), - INTC_VECT(STPRO_4, 0x1D00), -}; - -static struct intc_group intca_groups[] __initdata = { - INTC_GROUP(DMAC1_1, - DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3), - INTC_GROUP(DMAC1_2, - DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR), - INTC_GROUP(DMAC2_1, - DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3), - INTC_GROUP(DMAC2_2, - DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR), - INTC_GROUP(DMAC3_1, - DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3), - INTC_GROUP(DMAC3_2, - DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR), - INTC_GROUP(AP_ARM1, - AP_ARM_COMMTX, AP_ARM_COMMRX), - INTC_GROUP(AP_ARM2, - AP_ARM_CTIIRQ, AP_ARM_PMURQ), - INTC_GROUP(USBF, - USBF_OUL_SOF, USBF_IXL_INT), - INTC_GROUP(SDHI0, - SDHI0_0, SDHI0_1, SDHI0_2, SDHI0_3), - INTC_GROUP(SDHI1, - SDHI1_0, SDHI1_1, SDHI1_2, SDHI1_3), - INTC_GROUP(SDHI2, - SDHI2_0, SDHI2_1, SDHI2_2, SDHI2_3), - INTC_GROUP(SHWYSTAT, - SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM), - INTC_GROUP(USBH1, /* FIXME */ - USBH_INT, USBH_OHCI), - INTC_GROUP(USBH2, /* FIXME */ - USBH_EHCI, - USBH_PME, USBH_BIND), - INTC_GROUP(RSPI, - RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF), - INTC_GROUP(SPU2, - SPU2_0, SPU2_1), - INTC_GROUP(FLCTL, - FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), - INTC_GROUP(IIC1, - IIC1_ALI, IIC1_TACKI, IIC1_WAITI, IIC1_DTEI), -}; - -static struct intc_mask_reg intca_mask_registers[] __initdata = { - { /* IMR0A / IMCR0A */ 0xe6940080, 0xe69400c0, 8, - { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0, - 0, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } }, - { /* IMR1A / IMCR1A */ 0xe6940084, 0xe69400c4, 8, - { ATAPI, 0, DIRC, 0, - DMAC1_1_DEI3, DMAC1_1_DEI2, DMAC1_1_DEI1, DMAC1_1_DEI0 } }, - { /* IMR2A / IMCR2A */ 0xe6940088, 0xe69400c8, 8, - { 0, 0, 0, 0, - BBIF1, BBIF2, MFIS, MFI } }, - { /* IMR3A / IMCR3A */ 0xe694008c, 0xe69400cc, 8, - { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0, - DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } }, - { /* IMR4A / IMCR4A */ 0xe6940090, 0xe69400d0, 8, - { DDM, 0, 0, 0, - 0, 0, 0, 0 } }, - { /* IMR5A / IMCR5A */ 0xe6940094, 0xe69400d4, 8, - { KEYSC, DMAC1_2_DADERR, DMAC1_2_DEI5, DMAC1_2_DEI4, - SCIFA3, SCIFA2, SCIFA1, SCIFA0 } }, - { /* IMR6A / IMCR6A */ 0xe6940098, 0xe69400d8, 8, - { SCIFB, SCIFA5, SCIFA4, MSIOF1, - 0, 0, MSIOF2, 0 } }, - { /* IMR7A / IMCR7A */ 0xe694009c, 0xe69400dc, 8, - { SDHI0_3, SDHI0_2, SDHI0_1, SDHI0_0, - FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } }, - { /* IMR8A / IMCR8A */ 0xe69400a0, 0xe69400e0, 8, - { SDHI1_3, SDHI1_2, SDHI1_1, SDHI1_0, - 0, USBHSDMAC, 0, AP_ARM_L2CINT } }, - { /* IMR9A / IMCR9A */ 0xe69400a4, 0xe69400e4, 8, - { CMT1_3, CMT1_2, CMT1_1, CMT1_0, - CMT2, USBF_IXL_INT, USBF_OUL_SOF, SGX540 } }, - { /* IMR10A / IMCR10A */ 0xe69400a8, 0xe69400e8, 8, - { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4, - 0, 0, 0, 0 } }, - { /* IMR11A / IMCR11A */ 0xe69400ac, 0xe69400ec, 8, - { IIC1_DTEI, IIC1_WAITI, IIC1_TACKI, IIC1_ALI, - ICBS0, 0, 0, 0 } }, - { /* IMR12A / IMCR12A */ 0xe69400b0, 0xe69400f0, 8, - { 0, 0, TPU0, SCIFA6, - SCIFA7, GbEther, 0, 0 } }, - { /* IMR13A / IMCR13A */ 0xe69400b4, 0xe69400f4, 8, - { SDHI2_3, SDHI2_2, SDHI2_1, SDHI2_0, - 0, CMT3, 0, RWDT0 } }, - { /* IMR0A3 / IMCR0A3 */ 0xe6950080, 0xe69500c0, 8, - { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0, - 0, 0, 0, 0 } }, - /* IMR1A3 / IMCR1A3 */ - { /* IMR2A3 / IMCR2A3 */ 0xe6950088, 0xe69500c8, 8, - { 0, 0, USBH_INT, USBH_OHCI, - USBH_EHCI, USBH_PME, USBH_BIND, 0 } }, - /* IMR3A3 / IMCR3A3 */ - { /* IMR4A3 / IMCR4A3 */ 0xe6950090, 0xe69500d0, 8, - { HDMI, 0, 0, 0, - RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, 0 } }, - { /* IMR5A3 / IMCR5A3 */ 0xe6950094, 0xe69500d4, 8, - { SPU2_0, SPU2_1, FSI, FMSI, - 0, HDMI_SSS, HDMI_KEY, 0 } }, - { /* IMR6A3 / IMCR6A3 */ 0xe6950098, 0xe69500d8, 8, - { 0, IPMMU, 0, 0, - AP_ARM_CTIIRQ, AP_ARM_PMURQ, 0, 0 } }, - { /* IMR7A3 / IMCR7A3 */ 0xe695009c, 0xe69500dc, 8, - { MFIS2, CPORTR2S, CMT14, CMT15, - 0, MMCIF_0, MMCIF_1, MMCIF_2 } }, - /* IMR8A3 / IMCR8A3 */ - { /* IMR9A3 / IMCR9A3 */ 0xe69500a4, 0xe69500e4, 8, - { SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI, - STPRO_0, STPRO_1, STPRO_2, STPRO_3 } }, - { /* IMR10A3 / IMCR10A3 */ 0xe69500a8, 0xe69500e8, 8, - { STPRO_4, 0, 0, 0, - 0, 0, 0, 0 } }, -}; - -static struct intc_prio_reg intca_prio_registers[] __initdata = { - { 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, ICBS0 } }, - { 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } }, - { 0xe6940008, 0, 16, 4, /* IPRCA */ { ATAPI, 0, CMT1_1, AP_ARM1 } }, - { 0xe694000c, 0, 16, 4, /* IPRDA */ { 0, 0, CMT1_2, 0 } }, - { 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC1_1, MFIS, MFI, USBF } }, - { 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC, DMAC1_2, - SGX540, CMT1_0 } }, - { 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1, - SCIFA2, SCIFA3 } }, - { 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBHSDMAC, - FLCTL, SDHI0 } }, - { 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4, 0, IIC1 } }, - { 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2, - AP_ARM_L2CINT, 0 } }, - { 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_3, 0, SDHI1 } }, - { 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, SCIFA6, - SCIFA7, GbEther } }, - { 0xe6940030, 0, 16, 4, /* IPRMA */ { 0, CMT3, 0, RWDT0 } }, - { 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, 0, DDM } }, - { 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } }, - { 0xe6950000, 0, 16, 4, /* IPRAA3 */ { SHWYSTAT, 0, 0, 0 } }, - /* IPRBA3 */ - /* IPRCA3 */ - /* IPRDA3 */ - { 0xe6950010, 0, 16, 4, /* IPREA3 */ { USBH1, 0, 0, 0 } }, - { 0xe6950014, 0, 16, 4, /* IPRFA3 */ { USBH2, 0, 0, 0 } }, - /* IPRGA3 */ - /* IPRHA3 */ - { 0xe6950020, 0, 16, 4, /* IPRIA3 */ { HDMI, 0, 0, 0 } }, - { 0xe6950024, 0, 16, 4, /* IPRJA3 */ { RSPI, 0, 0, 0 } }, - { 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } }, - { 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, HDMI_SSS, HDMI_KEY, 0 } }, - { 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU, 0, 0, 0 } }, - { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } }, - { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S, - CMT14, CMT15 } }, - { 0xe695003c, 0, 16, 4, /* IPRPA3 */ { 0, MMCIF_0, MMCIF_1, MMCIF_2 } }, - /* IPRQA3 */ - /* IPRRA3 */ - { 0xe6950048, 0, 16, 4, /* IPRSA3 */ { SIM_ERI, SIM_RXI, - SIM_TXI, SIM_TEI } }, - { 0xe695004c, 0, 16, 4, /* IPRTA3 */ { STPRO_0, STPRO_1, - STPRO_2, STPRO_3 } }, - { 0xe6950050, 0, 16, 4, /* IPRUA3 */ { STPRO_4, 0, 0, 0 } }, -}; - -static DECLARE_INTC_DESC(intca_desc, "r8a7740-intca", - intca_vectors, intca_groups, - intca_mask_registers, intca_prio_registers, - NULL); - -INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000, - INTC_VECT, "r8a7740-intca-irq-pins"); - - -/* - * INTCS - */ -enum { - UNUSED_INTCS = 0, - - INTCS, - - /* interrupt sources INTCS */ - - /* HUDI */ - /* STPRO */ - /* RTDMAC(1) */ - VPU5HA2, - _2DG_TRAP, _2DG_GPM_INT, _2DG_CER_INT, - /* MFI */ - /* BBIF2 */ - VPU5F, - _2DG_BRK_INT, - /* SGX540 */ - /* 2DDMAC */ - /* IPMMU */ - /* RTDMAC 2 */ - /* KEYSC */ - /* MSIOF */ - IIC0_ALI, IIC0_TACKI, IIC0_WAITI, IIC0_DTEI, - TMU0_0, TMU0_1, TMU0_2, - CMT0, - /* CMT2 */ - LMB, - CTI, - VOU, - /* RWDT0 */ - ICB, - VIO6C, - CEU20, CEU21, - JPU, - LCDC0, - LCRC, - /* RTDMAC2(1) */ - /* RTDMAC2(2) */ - LCDC1, - /* SPU2 */ - /* FSI */ - /* FMSI */ - TMU1_0, TMU1_1, TMU1_2, - CMT4, - DISP, - DSRV, - /* MFIS2 */ - CPORTS2R, - - /* interrupt groups INTCS */ - _2DG1, - IIC0, TMU1, -}; - -static struct intc_vect intcs_vectors[] = { - /* HUDI */ - /* STPRO */ - /* RTDMAC(1) */ - INTCS_VECT(VPU5HA2, 0x0880), - INTCS_VECT(_2DG_TRAP, 0x08A0), - INTCS_VECT(_2DG_GPM_INT, 0x08C0), - INTCS_VECT(_2DG_CER_INT, 0x08E0), - /* MFI */ - /* BBIF2 */ - INTCS_VECT(VPU5F, 0x0980), - INTCS_VECT(_2DG_BRK_INT, 0x09A0), - /* SGX540 */ - /* 2DDMAC */ - /* IPMMU */ - /* RTDMAC(2) */ - /* KEYSC */ - /* MSIOF */ - INTCS_VECT(IIC0_ALI, 0x0E00), - INTCS_VECT(IIC0_TACKI, 0x0E20), - INTCS_VECT(IIC0_WAITI, 0x0E40), - INTCS_VECT(IIC0_DTEI, 0x0E60), - INTCS_VECT(TMU0_0, 0x0E80), - INTCS_VECT(TMU0_1, 0x0EA0), - INTCS_VECT(TMU0_2, 0x0EC0), - INTCS_VECT(CMT0, 0x0F00), - /* CMT2 */ - INTCS_VECT(LMB, 0x0F60), - INTCS_VECT(CTI, 0x0400), - INTCS_VECT(VOU, 0x0420), - /* RWDT0 */ - INTCS_VECT(ICB, 0x0480), - INTCS_VECT(VIO6C, 0x04E0), - INTCS_VECT(CEU20, 0x0500), - INTCS_VECT(CEU21, 0x0520), - INTCS_VECT(JPU, 0x0560), - INTCS_VECT(LCDC0, 0x0580), - INTCS_VECT(LCRC, 0x05A0), - /* RTDMAC2(1) */ - /* RTDMAC2(2) */ - INTCS_VECT(LCDC1, 0x1780), - /* SPU2 */ - /* FSI */ - /* FMSI */ - INTCS_VECT(TMU1_0, 0x1900), - INTCS_VECT(TMU1_1, 0x1920), - INTCS_VECT(TMU1_2, 0x1940), - INTCS_VECT(CMT4, 0x1980), - INTCS_VECT(DISP, 0x19A0), - INTCS_VECT(DSRV, 0x19C0), - /* MFIS2 */ - INTCS_VECT(CPORTS2R, 0x1A20), - - INTC_VECT(INTCS, 0xf80), -}; - -static struct intc_group intcs_groups[] __initdata = { - INTC_GROUP(_2DG1, /*FIXME*/ - _2DG_CER_INT, _2DG_GPM_INT, _2DG_TRAP), - INTC_GROUP(IIC0, - IIC0_DTEI, IIC0_WAITI, IIC0_TACKI, IIC0_ALI), - INTC_GROUP(TMU1, - TMU1_0, TMU1_1, TMU1_2), -}; - -static struct intc_mask_reg intcs_mask_registers[] = { - /* IMR0SA / IMCR0SA */ /* all 0 */ - { /* IMR1SA / IMCR1SA */ 0xffd20184, 0xffd201c4, 8, - { _2DG_CER_INT, _2DG_GPM_INT, _2DG_TRAP, VPU5HA2, - 0, 0, 0, 0 /*STPRO*/ } }, - { /* IMR2SA / IMCR2SA */ 0xffd20188, 0xffd201c8, 8, - { 0/*STPRO*/, 0, CEU21, VPU5F, - 0/*BBIF2*/, 0, 0, 0/*MFI*/ } }, - { /* IMR3SA / IMCR3SA */ 0xffd2018c, 0xffd201cc, 8, - { 0, 0, 0, 0, /*2DDMAC*/ - VIO6C, 0, 0, ICB } }, - { /* IMR4SA / IMCR4SA */ 0xffd20190, 0xffd201d0, 8, - { 0, 0, VOU, CTI, - JPU, 0, LCRC, LCDC0 } }, - /* IMR5SA / IMCR5SA */ /*KEYSC/RTDMAC2/RTDMAC1*/ - /* IMR6SA / IMCR6SA */ /*MSIOF/SGX540*/ - { /* IMR7SA / IMCR7SA */ 0xffd2019c, 0xffd201dc, 8, - { 0, TMU0_2, TMU0_1, TMU0_0, - 0, 0, 0, 0 } }, - { /* IMR8SA / IMCR8SA */ 0xffd201a0, 0xffd201e0, 8, - { 0, 0, 0, 0, - CEU20, 0, 0, 0 } }, - { /* IMR9SA / IMCR9SA */ 0xffd201a4, 0xffd201e4, 8, - { 0, 0/*RWDT0*/, 0/*CMT2*/, CMT0, - 0, 0, 0, 0 } }, - /* IMR10SA / IMCR10SA */ /*IPMMU*/ - { /* IMR11SA / IMCR11SA */ 0xffd201ac, 0xffd201ec, 8, - { IIC0_DTEI, IIC0_WAITI, IIC0_TACKI, IIC0_ALI, - 0, _2DG_BRK_INT, LMB, 0 } }, - /* IMR12SA / IMCR12SA */ - /* IMR13SA / IMCR13SA */ - /* IMR0SA3 / IMCR0SA3 */ /*RTDMAC2(1)/RTDMAC2(2)*/ - /* IMR1SA3 / IMCR1SA3 */ - /* IMR2SA3 / IMCR2SA3 */ - /* IMR3SA3 / IMCR3SA3 */ - { /* IMR4SA3 / IMCR4SA3 */ 0xffd50190, 0xffd501d0, 8, - { 0, 0, 0, 0, - LCDC1, 0, 0, 0 } }, - /* IMR5SA3 / IMCR5SA3 */ /* SPU2/FSI/FMSI */ - { /* IMR6SA3 / IMCR6SA3 */ 0xffd50198, 0xffd501d8, 8, - { TMU1_0, TMU1_1, TMU1_2, 0, - CMT4, DISP, DSRV, 0 } }, - { /* IMR7SA3 / IMCR7SA3 */ 0xffd5019c, 0xffd501dc, 8, - { 0/*MFIS2*/, CPORTS2R, 0, 0, - 0, 0, 0, 0 } }, - { /* INTAMASK */ 0xffd20104, 0, 16, - { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, INTCS } }, -}; - -/* Priority is needed for INTCA to receive the INTCS interrupt */ -static struct intc_prio_reg intcs_prio_registers[] = { - { 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, VOU, 0/*2DDMAC*/, ICB } }, - { 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU, LCDC0, 0, LCRC } }, - /* IPRCS */ /*BBIF2*/ - /* IPRDS */ - { 0xffd20010, 0, 16, 4, /* IPRES */ { 0/*RTDMAC(1)*/, VPU5HA2, - 0/*MFI*/, VPU5F } }, - { 0xffd20014, 0, 16, 4, /* IPRFS */ { 0/*KEYSC*/, 0/*RTDMAC(2)*/, - 0/*CMT2*/, CMT0 } }, - { 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU0_0, TMU0_1, - TMU0_2, _2DG1 } }, - { 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, 0/*STPRO*/, 0/*STPRO*/, - _2DG_BRK_INT/*FIXME*/ } }, - { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, 0/*MSIOF*/, 0, IIC0 } }, - { 0xffd20024, 0, 16, 4, /* IPRJS */ { CEU20, 0/*SGX540*/, 0, 0 } }, - { 0xffd20028, 0, 16, 4, /* IPRKS */ { VIO6C, 0, LMB, 0 } }, - { 0xffd2002c, 0, 16, 4, /* IPRLS */ { 0/*IPMMU*/, 0, CEU21, 0 } }, - /* IPRMS */ /*RWDT0*/ - /* IPRAS3 */ /*RTDMAC2(1)*/ - /* IPRBS3 */ /*RTDMAC2(2)*/ - /* IPRCS3 */ - /* IPRDS3 */ - /* IPRES3 */ - /* IPRFS3 */ - /* IPRGS3 */ - /* IPRHS3 */ - /* IPRIS3 */ - { 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, 0, 0, 0 } }, - /* IPRKS3 */ /*SPU2/FSI/FMSi*/ - /* IPRLS3 */ - { 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, 0 } }, - { 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, DISP, DSRV, 0 } }, - { 0xffd50038, 0, 16, 4, /* IPROS3 */ { 0/*MFIS2*/, CPORTS2R, 0, 0 } }, - /* IPRPS3 */ -}; - -static struct resource intcs_resources[] __initdata = { - [0] = { - .start = 0xffd20000, - .end = 0xffd201ff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = 0xffd50000, - .end = 0xffd501ff, - .flags = IORESOURCE_MEM, - } -}; - -static struct intc_desc intcs_desc __initdata = { - .name = "r8a7740-intcs", - .resource = intcs_resources, - .num_resources = ARRAY_SIZE(intcs_resources), - .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers, - intcs_prio_registers, NULL, NULL), -}; - -static void intcs_demux(unsigned int irq, struct irq_desc *desc) -{ - void __iomem *reg = (void *)irq_get_handler_data(irq); - unsigned int evtcodeas = ioread32(reg); - - generic_handle_irq(intcs_evt2irq(evtcodeas)); -} +#include <linux/irqchip/arm-gic.h> void __init r8a7740_init_irq(void) { - void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); - - register_intc_controller(&intca_desc); - register_intc_controller(&intca_irq_pins_desc); - register_intc_controller(&intcs_desc); - - /* demux using INTEVTSA */ - irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa); - irq_set_chained_handler(evt2irq(0xf80), intcs_demux); + void __iomem *gic_dist_base = ioremap_nocache(0xc2800000, 0x1000); + void __iomem *gic_cpu_base = ioremap_nocache(0xc2000000, 0x1000); + void __iomem *intc_prio_base = ioremap_nocache(0xe6900010, 0x10); + void __iomem *intc_msk_base = ioremap_nocache(0xe6900040, 0x10); + void __iomem *pfc_inta_ctrl = ioremap_nocache(0xe605807c, 0x4); + + /* initialize the Generic Interrupt Controller PL390 r0p0 */ + gic_init(0, 29, gic_dist_base, gic_cpu_base); + + /* route signals to GIC */ + iowrite32(0x0, pfc_inta_ctrl); + + /* + * To mask the shared interrupt to SPI 149 we must ensure to set + * PRIO *and* MASK. Else we run into IRQ floods when registering + * the intc_irqpin devices + */ + iowrite32(0x0, intc_prio_base + 0x0); + iowrite32(0x0, intc_prio_base + 0x4); + iowrite32(0x0, intc_prio_base + 0x8); + iowrite32(0x0, intc_prio_base + 0xc); + iowrite8(0xff, intc_msk_base + 0x0); + iowrite8(0xff, intc_msk_base + 0x4); + iowrite8(0xff, intc_msk_base + 0x8); + iowrite8(0xff, intc_msk_base + 0xc); + + iounmap(intc_prio_base); + iounmap(intc_msk_base); + iounmap(pfc_inta_ctrl); } diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c index e4545c152722..899a86c31ec9 100644 --- a/arch/arm/mach-shmobile/setup-emev2.c +++ b/arch/arm/mach-shmobile/setup-emev2.c @@ -456,7 +456,6 @@ DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)") .nr_irqs = NR_IRQS_LEGACY, .init_irq = irqchip_init, .init_machine = emev2_add_standard_devices_dt, - .init_time = shmobile_timer_init, .dt_compat = emev2_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c new file mode 100644 index 000000000000..c5a75a7a508f --- /dev/null +++ b/arch/arm/mach-shmobile/setup-r8a73a4.c @@ -0,0 +1,202 @@ +/* + * r8a73a4 processor support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/kernel.h> +#include <linux/of_platform.h> +#include <linux/platform_data/irq-renesas-irqc.h> +#include <linux/serial_sci.h> +#include <mach/common.h> +#include <mach/irqs.h> +#include <mach/r8a73a4.h> +#include <asm/mach/arch.h> + +static const struct resource pfc_resources[] = { + DEFINE_RES_MEM(0xe6050000, 0x9000), +}; + +void __init r8a73a4_pinmux_init(void) +{ + platform_device_register_simple("pfc-r8a73a4", -1, pfc_resources, + ARRAY_SIZE(pfc_resources)); +} + +#define SCIF_COMMON(scif_type, baseaddr, irq) \ + .type = scif_type, \ + .mapbase = baseaddr, \ + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \ + .scbrr_algo_id = SCBRR_ALGO_4, \ + .irqs = SCIx_IRQ_MUXED(irq) + +#define SCIFA_DATA(index, baseaddr, irq) \ +[index] = { \ + SCIF_COMMON(PORT_SCIFA, baseaddr, irq), \ + .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE0, \ +} + +#define SCIFB_DATA(index, baseaddr, irq) \ +[index] = { \ + SCIF_COMMON(PORT_SCIFB, baseaddr, irq), \ + .scscr = SCSCR_RE | SCSCR_TE, \ +} + +enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFB3 }; + +static const struct plat_sci_port scif[] = { + SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */ + SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */ + SCIFB_DATA(SCIFB0, 0xe6c50000, gic_spi(145)), /* SCIFB0 */ + SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */ + SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */ + SCIFB_DATA(SCIFB3, 0xe6cf0000, gic_spi(151)), /* SCIFB3 */ +}; + +static inline void r8a73a4_register_scif(int idx) +{ + platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx], + sizeof(struct plat_sci_port)); +} + +static const struct renesas_irqc_config irqc0_data = { + .irq_base = irq_pin(0), /* IRQ0 -> IRQ31 */ +}; + +static const struct resource irqc0_resources[] = { + DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */ + DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */ + DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */ + DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */ + DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */ + DEFINE_RES_IRQ(gic_spi(4)), /* IRQ4 */ + DEFINE_RES_IRQ(gic_spi(5)), /* IRQ5 */ + DEFINE_RES_IRQ(gic_spi(6)), /* IRQ6 */ + DEFINE_RES_IRQ(gic_spi(7)), /* IRQ7 */ + DEFINE_RES_IRQ(gic_spi(8)), /* IRQ8 */ + DEFINE_RES_IRQ(gic_spi(9)), /* IRQ9 */ + DEFINE_RES_IRQ(gic_spi(10)), /* IRQ10 */ + DEFINE_RES_IRQ(gic_spi(11)), /* IRQ11 */ + DEFINE_RES_IRQ(gic_spi(12)), /* IRQ12 */ + DEFINE_RES_IRQ(gic_spi(13)), /* IRQ13 */ + DEFINE_RES_IRQ(gic_spi(14)), /* IRQ14 */ + DEFINE_RES_IRQ(gic_spi(15)), /* IRQ15 */ + DEFINE_RES_IRQ(gic_spi(16)), /* IRQ16 */ + DEFINE_RES_IRQ(gic_spi(17)), /* IRQ17 */ + DEFINE_RES_IRQ(gic_spi(18)), /* IRQ18 */ + DEFINE_RES_IRQ(gic_spi(19)), /* IRQ19 */ + DEFINE_RES_IRQ(gic_spi(20)), /* IRQ20 */ + DEFINE_RES_IRQ(gic_spi(21)), /* IRQ21 */ + DEFINE_RES_IRQ(gic_spi(22)), /* IRQ22 */ + DEFINE_RES_IRQ(gic_spi(23)), /* IRQ23 */ + DEFINE_RES_IRQ(gic_spi(24)), /* IRQ24 */ + DEFINE_RES_IRQ(gic_spi(25)), /* IRQ25 */ + DEFINE_RES_IRQ(gic_spi(26)), /* IRQ26 */ + DEFINE_RES_IRQ(gic_spi(27)), /* IRQ27 */ + DEFINE_RES_IRQ(gic_spi(28)), /* IRQ28 */ + DEFINE_RES_IRQ(gic_spi(29)), /* IRQ29 */ + DEFINE_RES_IRQ(gic_spi(30)), /* IRQ30 */ + DEFINE_RES_IRQ(gic_spi(31)), /* IRQ31 */ +}; + +static const struct renesas_irqc_config irqc1_data = { + .irq_base = irq_pin(32), /* IRQ32 -> IRQ57 */ +}; + +static const struct resource irqc1_resources[] = { + DEFINE_RES_MEM(0xe61c0200, 0x200), /* IRQC Event Detector Block_1 */ + DEFINE_RES_IRQ(gic_spi(32)), /* IRQ32 */ + DEFINE_RES_IRQ(gic_spi(33)), /* IRQ33 */ + DEFINE_RES_IRQ(gic_spi(34)), /* IRQ34 */ + DEFINE_RES_IRQ(gic_spi(35)), /* IRQ35 */ + DEFINE_RES_IRQ(gic_spi(36)), /* IRQ36 */ + DEFINE_RES_IRQ(gic_spi(37)), /* IRQ37 */ + DEFINE_RES_IRQ(gic_spi(38)), /* IRQ38 */ + DEFINE_RES_IRQ(gic_spi(39)), /* IRQ39 */ + DEFINE_RES_IRQ(gic_spi(40)), /* IRQ40 */ + DEFINE_RES_IRQ(gic_spi(41)), /* IRQ41 */ + DEFINE_RES_IRQ(gic_spi(42)), /* IRQ42 */ + DEFINE_RES_IRQ(gic_spi(43)), /* IRQ43 */ + DEFINE_RES_IRQ(gic_spi(44)), /* IRQ44 */ + DEFINE_RES_IRQ(gic_spi(45)), /* IRQ45 */ + DEFINE_RES_IRQ(gic_spi(46)), /* IRQ46 */ + DEFINE_RES_IRQ(gic_spi(47)), /* IRQ47 */ + DEFINE_RES_IRQ(gic_spi(48)), /* IRQ48 */ + DEFINE_RES_IRQ(gic_spi(49)), /* IRQ49 */ + DEFINE_RES_IRQ(gic_spi(50)), /* IRQ50 */ + DEFINE_RES_IRQ(gic_spi(51)), /* IRQ51 */ + DEFINE_RES_IRQ(gic_spi(52)), /* IRQ52 */ + DEFINE_RES_IRQ(gic_spi(53)), /* IRQ53 */ + DEFINE_RES_IRQ(gic_spi(54)), /* IRQ54 */ + DEFINE_RES_IRQ(gic_spi(55)), /* IRQ55 */ + DEFINE_RES_IRQ(gic_spi(56)), /* IRQ56 */ + DEFINE_RES_IRQ(gic_spi(57)), /* IRQ57 */ +}; + +#define r8a73a4_register_irqc(idx) \ + platform_device_register_resndata(&platform_bus, "renesas_irqc", \ + idx, irqc##idx##_resources, \ + ARRAY_SIZE(irqc##idx##_resources), \ + &irqc##idx##_data, \ + sizeof(struct renesas_irqc_config)) + +/* Thermal0 -> Thermal2 */ +static const struct resource thermal0_resources[] = { + DEFINE_RES_MEM(0xe61f0000, 0x14), + DEFINE_RES_MEM(0xe61f0100, 0x38), + DEFINE_RES_MEM(0xe61f0200, 0x38), + DEFINE_RES_MEM(0xe61f0300, 0x38), + DEFINE_RES_IRQ(gic_spi(69)), +}; + +#define r8a73a4_register_thermal() \ + platform_device_register_simple("rcar_thermal", -1, \ + thermal0_resources, \ + ARRAY_SIZE(thermal0_resources)) + +void __init r8a73a4_add_standard_devices(void) +{ + r8a73a4_register_scif(SCIFA0); + r8a73a4_register_scif(SCIFA1); + r8a73a4_register_scif(SCIFB0); + r8a73a4_register_scif(SCIFB1); + r8a73a4_register_scif(SCIFB2); + r8a73a4_register_scif(SCIFB3); + r8a73a4_register_irqc(0); + r8a73a4_register_irqc(1); + r8a73a4_register_thermal(); +} + +#ifdef CONFIG_USE_OF +void __init r8a73a4_add_standard_devices_dt(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static const char *r8a73a4_boards_compat_dt[] __initdata = { + "renesas,r8a73a4", + NULL, +}; + +DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)") + .init_irq = irqchip_init, + .init_machine = r8a73a4_add_standard_devices_dt, + .init_time = shmobile_timer_init, + .dt_compat = r8a73a4_boards_compat_dt, +MACHINE_END +#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 8b85d4d8fab6..326a4ab0bd5f 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -22,6 +22,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/platform_data/irq-renesas-intc-irqpin.h> #include <linux/platform_device.h> #include <linux/of_platform.h> #include <linux/serial_sci.h> @@ -94,6 +95,126 @@ void __init r8a7740_pinmux_init(void) platform_device_register(&r8a7740_pfc_device); } +static struct renesas_intc_irqpin_config irqpin0_platform_data = { + .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */ +}; + +static struct resource irqpin0_resources[] = { + DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */ + DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */ + DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */ + DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */ + DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ0 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ1 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ2 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ3 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ4 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ5 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ6 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ7 */ +}; + +static struct platform_device irqpin0_device = { + .name = "renesas_intc_irqpin", + .id = 0, + .resource = irqpin0_resources, + .num_resources = ARRAY_SIZE(irqpin0_resources), + .dev = { + .platform_data = &irqpin0_platform_data, + }, +}; + +static struct renesas_intc_irqpin_config irqpin1_platform_data = { + .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */ +}; + +static struct resource irqpin1_resources[] = { + DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */ + DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */ + DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */ + DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */ + DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ8 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ9 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ10 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ11 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ12 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ13 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ14 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ15 */ +}; + +static struct platform_device irqpin1_device = { + .name = "renesas_intc_irqpin", + .id = 1, + .resource = irqpin1_resources, + .num_resources = ARRAY_SIZE(irqpin1_resources), + .dev = { + .platform_data = &irqpin1_platform_data, + }, +}; + +static struct renesas_intc_irqpin_config irqpin2_platform_data = { + .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */ +}; + +static struct resource irqpin2_resources[] = { + DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */ + DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI30A */ + DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ30A */ + DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK30A */ + DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR30A */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ16 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ17 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ18 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ19 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ20 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ21 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ22 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ23 */ +}; + +static struct platform_device irqpin2_device = { + .name = "renesas_intc_irqpin", + .id = 2, + .resource = irqpin2_resources, + .num_resources = ARRAY_SIZE(irqpin2_resources), + .dev = { + .platform_data = &irqpin2_platform_data, + }, +}; + +static struct renesas_intc_irqpin_config irqpin3_platform_data = { + .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */ +}; + +static struct resource irqpin3_resources[] = { + DEFINE_RES_MEM(0xe690000c, 4), /* ICR3A */ + DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */ + DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */ + DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */ + DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ24 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ25 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ26 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ27 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ28 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ29 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ30 */ + DEFINE_RES_IRQ(gic_spi(149)), /* IRQ31 */ +}; + +static struct platform_device irqpin3_device = { + .name = "renesas_intc_irqpin", + .id = 3, + .resource = irqpin3_resources, + .num_resources = ARRAY_SIZE(irqpin3_resources), + .dev = { + .platform_data = &irqpin3_platform_data, + }, +}; + /* SCIFA0 */ static struct plat_sci_port scif0_platform_data = { .mapbase = 0xe6c40000, @@ -101,7 +222,7 @@ static struct plat_sci_port scif0_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c00)), + .irqs = SCIx_IRQ_MUXED(gic_spi(100)), }; static struct platform_device scif0_device = { @@ -119,7 +240,7 @@ static struct plat_sci_port scif1_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c20)), + .irqs = SCIx_IRQ_MUXED(gic_spi(101)), }; static struct platform_device scif1_device = { @@ -137,7 +258,7 @@ static struct plat_sci_port scif2_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c40)), + .irqs = SCIx_IRQ_MUXED(gic_spi(102)), }; static struct platform_device scif2_device = { @@ -155,7 +276,7 @@ static struct plat_sci_port scif3_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x0c60)), + .irqs = SCIx_IRQ_MUXED(gic_spi(103)), }; static struct platform_device scif3_device = { @@ -173,7 +294,7 @@ static struct plat_sci_port scif4_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d20)), + .irqs = SCIx_IRQ_MUXED(gic_spi(104)), }; static struct platform_device scif4_device = { @@ -191,7 +312,7 @@ static struct plat_sci_port scif5_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d40)), + .irqs = SCIx_IRQ_MUXED(gic_spi(105)), }; static struct platform_device scif5_device = { @@ -209,7 +330,7 @@ static struct plat_sci_port scif6_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x04c0)), + .irqs = SCIx_IRQ_MUXED(gic_spi(106)), }; static struct platform_device scif6_device = { @@ -227,7 +348,7 @@ static struct plat_sci_port scif7_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFA, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x04e0)), + .irqs = SCIx_IRQ_MUXED(gic_spi(107)), }; static struct platform_device scif7_device = { @@ -245,7 +366,7 @@ static struct plat_sci_port scifb_platform_data = { .scscr = SCSCR_RE | SCSCR_TE, .scbrr_algo_id = SCBRR_ALGO_4, .type = PORT_SCIFB, - .irqs = SCIx_IRQ_MUXED(evt2irq(0x0d60)), + .irqs = SCIx_IRQ_MUXED(gic_spi(108)), }; static struct platform_device scifb_device = { @@ -273,7 +394,7 @@ static struct resource cmt10_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x0b00), + .start = gic_spi(58), .flags = IORESOURCE_IRQ, }, }; @@ -304,7 +425,7 @@ static struct resource tmu00_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = intcs_evt2irq(0xe80), + .start = gic_spi(198), .flags = IORESOURCE_IRQ, }, }; @@ -334,7 +455,7 @@ static struct resource tmu01_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = intcs_evt2irq(0xea0), + .start = gic_spi(199), .flags = IORESOURCE_IRQ, }, }; @@ -364,7 +485,7 @@ static struct resource tmu02_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = intcs_evt2irq(0xec0), + .start = gic_spi(200), .flags = IORESOURCE_IRQ, }, }; @@ -411,6 +532,10 @@ static struct platform_device ipmmu_device = { }; static struct platform_device *r8a7740_early_devices[] __initdata = { + &irqpin0_device, + &irqpin1_device, + &irqpin2_device, + &irqpin3_device, &scif0_device, &scif1_device, &scif2_device, @@ -525,14 +650,14 @@ static struct resource r8a7740_dmae0_resources[] = { }, { .name = "error_irq", - .start = evt2irq(0x20c0), - .end = evt2irq(0x20c0), + .start = gic_spi(34), + .end = gic_spi(34), .flags = IORESOURCE_IRQ, }, { /* IRQ for channels 0-5 */ - .start = evt2irq(0x2000), - .end = evt2irq(0x20a0), + .start = gic_spi(28), + .end = gic_spi(33), .flags = IORESOURCE_IRQ, }, }; @@ -553,14 +678,14 @@ static struct resource r8a7740_dmae1_resources[] = { }, { .name = "error_irq", - .start = evt2irq(0x21c0), - .end = evt2irq(0x21c0), + .start = gic_spi(41), + .end = gic_spi(41), .flags = IORESOURCE_IRQ, }, { /* IRQ for channels 0-5 */ - .start = evt2irq(0x2100), - .end = evt2irq(0x21a0), + .start = gic_spi(35), + .end = gic_spi(40), .flags = IORESOURCE_IRQ, }, }; @@ -581,14 +706,14 @@ static struct resource r8a7740_dmae2_resources[] = { }, { .name = "error_irq", - .start = evt2irq(0x22c0), - .end = evt2irq(0x22c0), + .start = gic_spi(48), + .end = gic_spi(48), .flags = IORESOURCE_IRQ, }, { /* IRQ for channels 0-5 */ - .start = evt2irq(0x2200), - .end = evt2irq(0x22a0), + .start = gic_spi(42), + .end = gic_spi(47), .flags = IORESOURCE_IRQ, }, }; @@ -677,8 +802,8 @@ static struct resource r8a7740_usb_dma_resources[] = { }, { /* IRQ for channels */ - .start = evt2irq(0x0a00), - .end = evt2irq(0x0a00), + .start = gic_spi(49), + .end = gic_spi(49), .flags = IORESOURCE_IRQ, }, }; @@ -702,8 +827,8 @@ static struct resource i2c0_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = intcs_evt2irq(0xe00), - .end = intcs_evt2irq(0xe60), + .start = gic_spi(201), + .end = gic_spi(204), .flags = IORESOURCE_IRQ, }, }; @@ -716,8 +841,8 @@ static struct resource i2c1_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = evt2irq(0x780), /* IIC1_ALI1 */ - .end = evt2irq(0x7e0), /* IIC1_DTEI1 */ + .start = gic_spi(70), /* IIC1_ALI1 */ + .end = gic_spi(73), /* IIC1_DTEI1 */ .flags = IORESOURCE_IRQ, }, }; @@ -738,8 +863,8 @@ static struct platform_device i2c1_device = { static struct resource pmu_resources[] = { [0] = { - .start = evt2irq(0x19a0), - .end = evt2irq(0x19a0), + .start = gic_spi(83), + .end = gic_spi(83), .flags = IORESOURCE_IRQ, }, }; @@ -904,9 +1029,7 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)") .map_io = r8a7740_map_io, .init_early = r8a7740_add_early_devices_dt, .init_irq = r8a7740_init_irq, - .handle_irq = shmobile_handle_irq_intc, .init_machine = r8a7740_add_standard_devices_dt, - .init_time = shmobile_timer_init, .dt_compat = r8a7740_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c new file mode 100644 index 000000000000..30b4a336308f --- /dev/null +++ b/arch/arm/mach-shmobile/setup-r8a7778.c @@ -0,0 +1,244 @@ +/* + * r8a7778 processor support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * Copyright (C) 2013 Cogent Embedded, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/irqchip/arm-gic.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_data/irq-renesas-intc-irqpin.h> +#include <linux/platform_device.h> +#include <linux/irqchip.h> +#include <linux/serial_sci.h> +#include <linux/sh_timer.h> +#include <mach/irqs.h> +#include <mach/r8a7778.h> +#include <mach/common.h> +#include <asm/mach/arch.h> +#include <asm/hardware/cache-l2x0.h> + +/* SCIF */ +#define SCIF_INFO(baseaddr, irq) \ +{ \ + .mapbase = baseaddr, \ + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \ + .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, \ + .scbrr_algo_id = SCBRR_ALGO_2, \ + .type = PORT_SCIF, \ + .irqs = SCIx_IRQ_MUXED(irq), \ +} + +static struct plat_sci_port scif_platform_data[] = { + SCIF_INFO(0xffe40000, gic_iid(0x66)), + SCIF_INFO(0xffe41000, gic_iid(0x67)), + SCIF_INFO(0xffe42000, gic_iid(0x68)), + SCIF_INFO(0xffe43000, gic_iid(0x69)), + SCIF_INFO(0xffe44000, gic_iid(0x6a)), + SCIF_INFO(0xffe45000, gic_iid(0x6b)), +}; + +/* TMU */ +static struct resource sh_tmu0_resources[] = { + DEFINE_RES_MEM(0xffd80008, 12), + DEFINE_RES_IRQ(gic_iid(0x40)), +}; + +static struct sh_timer_config sh_tmu0_platform_data = { + .name = "TMU00", + .channel_offset = 0x4, + .timer_bit = 0, + .clockevent_rating = 200, +}; + +static struct resource sh_tmu1_resources[] = { + DEFINE_RES_MEM(0xffd80014, 12), + DEFINE_RES_IRQ(gic_iid(0x41)), +}; + +static struct sh_timer_config sh_tmu1_platform_data = { + .name = "TMU01", + .channel_offset = 0x10, + .timer_bit = 1, + .clocksource_rating = 200, +}; + +/* Ether */ +static struct resource ether_resources[] = { + DEFINE_RES_MEM(0xfde00000, 0x400), + DEFINE_RES_IRQ(gic_iid(0x89)), +}; + +#define r8a7778_register_tmu(idx) \ + platform_device_register_resndata( \ + &platform_bus, "sh_tmu", idx, \ + sh_tmu##idx##_resources, \ + ARRAY_SIZE(sh_tmu##idx##_resources), \ + &sh_tmu##idx##_platform_data, \ + sizeof(sh_tmu##idx##_platform_data)) + +void __init r8a7778_add_standard_devices(void) +{ + int i; + +#ifdef CONFIG_CACHE_L2X0 + void __iomem *base = ioremap_nocache(0xf0100000, 0x1000); + if (base) { + /* + * Early BRESP enable, Shared attribute override enable, 64K*16way + * don't call iounmap(base) + */ + l2x0_init(base, 0x40470000, 0x82000fff); + } +#endif + + for (i = 0; i < ARRAY_SIZE(scif_platform_data); i++) + platform_device_register_data(&platform_bus, "sh-sci", i, + &scif_platform_data[i], + sizeof(struct plat_sci_port)); + + r8a7778_register_tmu(0); + r8a7778_register_tmu(1); +} + +void __init r8a7778_add_ether_device(struct sh_eth_plat_data *pdata) +{ + platform_device_register_resndata(&platform_bus, "sh_eth", -1, + ether_resources, + ARRAY_SIZE(ether_resources), + pdata, sizeof(*pdata)); +} + +static struct renesas_intc_irqpin_config irqpin_platform_data = { + .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ + .sense_bitfield_width = 2, +}; + +static struct resource irqpin_resources[] = { + DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */ + DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */ + DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */ + DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */ + DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */ + DEFINE_RES_IRQ(gic_iid(0x3b)), /* IRQ0 */ + DEFINE_RES_IRQ(gic_iid(0x3c)), /* IRQ1 */ + DEFINE_RES_IRQ(gic_iid(0x3d)), /* IRQ2 */ + DEFINE_RES_IRQ(gic_iid(0x3e)), /* IRQ3 */ +}; + +void __init r8a7778_init_irq_extpin(int irlm) +{ + void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE); + unsigned long tmp; + + if (!icr0) { + pr_warn("r8a7778: unable to setup external irq pin mode\n"); + return; + } + + tmp = ioread32(icr0); + if (irlm) + tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */ + else + tmp &= ~(1 << 23); /* IRL mode - not supported */ + tmp |= (1 << 21); /* LVLMODE = 1 */ + iowrite32(tmp, icr0); + iounmap(icr0); + + if (irlm) + platform_device_register_resndata( + &platform_bus, "renesas_intc_irqpin", -1, + irqpin_resources, ARRAY_SIZE(irqpin_resources), + &irqpin_platform_data, sizeof(irqpin_platform_data)); +} + +#define INT2SMSKCR0 0x82288 /* 0xfe782288 */ +#define INT2SMSKCR1 0x8228c /* 0xfe78228c */ + +#define INT2NTSR0 0x00018 /* 0xfe700018 */ +#define INT2NTSR1 0x0002c /* 0xfe70002c */ +static void __init r8a7778_init_irq_common(void) +{ + void __iomem *base = ioremap_nocache(0xfe700000, 0x00100000); + + BUG_ON(!base); + + /* route all interrupts to ARM */ + __raw_writel(0x73ffffff, base + INT2NTSR0); + __raw_writel(0xffffffff, base + INT2NTSR1); + + /* unmask all known interrupts in INTCS2 */ + __raw_writel(0x08330773, base + INT2SMSKCR0); + __raw_writel(0x00311110, base + INT2SMSKCR1); + + iounmap(base); +} + +void __init r8a7778_init_irq(void) +{ + void __iomem *gic_dist_base; + void __iomem *gic_cpu_base; + + gic_dist_base = ioremap_nocache(0xfe438000, PAGE_SIZE); + gic_cpu_base = ioremap_nocache(0xfe430000, PAGE_SIZE); + BUG_ON(!gic_dist_base || !gic_cpu_base); + + /* use GIC to handle interrupts */ + gic_init(0, 29, gic_dist_base, gic_cpu_base); + + r8a7778_init_irq_common(); +} + +void __init r8a7778_init_delay(void) +{ + shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */ +} + +#ifdef CONFIG_USE_OF +void __init r8a7778_init_irq_dt(void) +{ + irqchip_init(); + r8a7778_init_irq_common(); +} + +static const struct of_dev_auxdata r8a7778_auxdata_lookup[] __initconst = { + {}, +}; + +void __init r8a7778_add_standard_devices_dt(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, + r8a7778_auxdata_lookup, NULL); +} + +static const char *r8a7778_compat_dt[] __initdata = { + "renesas,r8a7778", + NULL, +}; + +DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)") + .init_early = r8a7778_init_delay, + .init_irq = r8a7778_init_irq_dt, + .init_machine = r8a7778_add_standard_devices_dt, + .init_time = shmobile_timer_init, + .dt_compat = r8a7778_compat_dt, +MACHINE_END + +#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 042df35e71a0..b0b394842ea5 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -1,8 +1,9 @@ /* * r8a7779 processor support * - * Copyright (C) 2011 Renesas Solutions Corp. + * Copyright (C) 2011, 2013 Renesas Solutions Corp. * Copyright (C) 2011 Magnus Damm + * Copyright (C) 2013 Cogent Embedded, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/of_platform.h> +#include <linux/platform_data/gpio-rcar.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/input.h> @@ -68,11 +70,6 @@ static struct resource r8a7779_pfc_resources[] = { .end = 0xfffc023b, .flags = IORESOURCE_MEM, }, - [1] = { - .start = 0xffc40000, - .end = 0xffc46fff, - .flags = IORESOURCE_MEM, - } }; static struct platform_device r8a7779_pfc_device = { @@ -82,9 +79,59 @@ static struct platform_device r8a7779_pfc_device = { .num_resources = ARRAY_SIZE(r8a7779_pfc_resources), }; +#define R8A7779_GPIO(idx, npins) \ +static struct resource r8a7779_gpio##idx##_resources[] = { \ + [0] = { \ + .start = 0xffc40000 + 0x1000 * (idx), \ + .end = 0xffc4002b + 0x1000 * (idx), \ + .flags = IORESOURCE_MEM, \ + }, \ + [1] = { \ + .start = gic_iid(0xad + (idx)), \ + .flags = IORESOURCE_IRQ, \ + } \ +}; \ + \ +static struct gpio_rcar_config r8a7779_gpio##idx##_platform_data = { \ + .gpio_base = 32 * (idx), \ + .irq_base = 0, \ + .number_of_pins = npins, \ + .pctl_name = "pfc-r8a7779", \ +}; \ + \ +static struct platform_device r8a7779_gpio##idx##_device = { \ + .name = "gpio_rcar", \ + .id = idx, \ + .resource = r8a7779_gpio##idx##_resources, \ + .num_resources = ARRAY_SIZE(r8a7779_gpio##idx##_resources), \ + .dev = { \ + .platform_data = &r8a7779_gpio##idx##_platform_data, \ + }, \ +} + +R8A7779_GPIO(0, 32); +R8A7779_GPIO(1, 32); +R8A7779_GPIO(2, 32); +R8A7779_GPIO(3, 32); +R8A7779_GPIO(4, 32); +R8A7779_GPIO(5, 32); +R8A7779_GPIO(6, 9); + +static struct platform_device *r8a7779_pinctrl_devices[] __initdata = { + &r8a7779_pfc_device, + &r8a7779_gpio0_device, + &r8a7779_gpio1_device, + &r8a7779_gpio2_device, + &r8a7779_gpio3_device, + &r8a7779_gpio4_device, + &r8a7779_gpio5_device, + &r8a7779_gpio6_device, +}; + void __init r8a7779_pinmux_init(void) { - platform_device_register(&r8a7779_pfc_device); + platform_add_devices(r8a7779_pinctrl_devices, + ARRAY_SIZE(r8a7779_pinctrl_devices)); } static struct plat_sci_port scif0_platform_data = { @@ -347,6 +394,18 @@ static struct platform_device sata_device = { }, }; +/* Ether */ +static struct resource ether_resources[] = { + { + .start = 0xfde00000, + .end = 0xfde003ff, + .flags = IORESOURCE_MEM, + }, { + .start = gic_iid(0xb4), + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device *r8a7779_devices_dt[] __initdata = { &scif0_device, &scif1_device, @@ -382,6 +441,14 @@ void __init r8a7779_add_standard_devices(void) ARRAY_SIZE(r8a7779_late_devices)); } +void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata) +{ + platform_device_register_resndata(&platform_bus, "sh_eth", -1, + ether_resources, + ARRAY_SIZE(ether_resources), + pdata, sizeof(*pdata)); +} + /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */ void __init __weak r8a7779_register_twd(void) { } diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c new file mode 100644 index 000000000000..49de2d56f86d --- /dev/null +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -0,0 +1,150 @@ +/* + * r8a7790 processor support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/kernel.h> +#include <linux/of_platform.h> +#include <linux/serial_sci.h> +#include <linux/platform_data/irq-renesas-irqc.h> +#include <mach/common.h> +#include <mach/irqs.h> +#include <mach/r8a7790.h> +#include <asm/mach/arch.h> + +static const struct resource pfc_resources[] = { + DEFINE_RES_MEM(0xe6060000, 0x250), + DEFINE_RES_MEM(0xe6050000, 0x5050), +}; + +void __init r8a7790_pinmux_init(void) +{ + platform_device_register_simple("pfc-r8a7790", -1, pfc_resources, + ARRAY_SIZE(pfc_resources)); +} + +#define SCIF_COMMON(scif_type, baseaddr, irq) \ + .type = scif_type, \ + .mapbase = baseaddr, \ + .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \ + .irqs = SCIx_IRQ_MUXED(irq) + +#define SCIFA_DATA(index, baseaddr, irq) \ +[index] = { \ + SCIF_COMMON(PORT_SCIFA, baseaddr, irq), \ + .scbrr_algo_id = SCBRR_ALGO_4, \ + .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE0, \ +} + +#define SCIFB_DATA(index, baseaddr, irq) \ +[index] = { \ + SCIF_COMMON(PORT_SCIFB, baseaddr, irq), \ + .scbrr_algo_id = SCBRR_ALGO_4, \ + .scscr = SCSCR_RE | SCSCR_TE, \ +} + +#define SCIF_DATA(index, baseaddr, irq) \ +[index] = { \ + SCIF_COMMON(PORT_SCIF, baseaddr, irq), \ + .scbrr_algo_id = SCBRR_ALGO_2, \ + .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1, \ +} + +enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1 }; + +static const struct plat_sci_port scif[] = { + SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */ + SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */ + SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */ + SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */ + SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */ + SCIFA_DATA(SCIFA2, 0xe6c60000, gic_spi(151)), /* SCIFA2 */ + SCIF_DATA(SCIF0, 0xe6e60000, gic_spi(152)), /* SCIF0 */ + SCIF_DATA(SCIF1, 0xe6e68000, gic_spi(153)), /* SCIF1 */ +}; + +static inline void r8a7790_register_scif(int idx) +{ + platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx], + sizeof(struct plat_sci_port)); +} + +static struct renesas_irqc_config irqc0_data = { + .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ +}; + +static struct resource irqc0_resources[] = { + DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */ + DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */ + DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */ + DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */ + DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */ +}; + +#define r8a7790_register_irqc(idx) \ + platform_device_register_resndata(&platform_bus, "renesas_irqc", \ + idx, irqc##idx##_resources, \ + ARRAY_SIZE(irqc##idx##_resources), \ + &irqc##idx##_data, \ + sizeof(struct renesas_irqc_config)) + +void __init r8a7790_add_standard_devices(void) +{ + r8a7790_register_scif(SCIFA0); + r8a7790_register_scif(SCIFA1); + r8a7790_register_scif(SCIFB0); + r8a7790_register_scif(SCIFB1); + r8a7790_register_scif(SCIFB2); + r8a7790_register_scif(SCIFA2); + r8a7790_register_scif(SCIF0); + r8a7790_register_scif(SCIF1); + r8a7790_register_irqc(0); +} + +void __init r8a7790_timer_init(void) +{ + void __iomem *cntcr; + + /* make sure arch timer is started by setting bit 0 of CNTCT */ + cntcr = ioremap(0xe6080000, PAGE_SIZE); + iowrite32(1, cntcr); + iounmap(cntcr); + + shmobile_timer_init(); +} + +#ifdef CONFIG_USE_OF +void __init r8a7790_add_standard_devices_dt(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static const char *r8a7790_boards_compat_dt[] __initdata = { + "renesas,r8a7790", + NULL, +}; + +DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)") + .init_irq = irqchip_init, + .init_machine = r8a7790_add_standard_devices_dt, + .init_time = r8a7790_timer_init, + .dt_compat = r8a7790_boards_compat_dt, +MACHINE_END +#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 59c7146bf66f..5502d624aca6 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -1175,7 +1175,6 @@ DT_MACHINE_START(SH7372_DT, "Generic SH7372 (Flattened Device Tree)") .init_irq = sh7372_init_irq, .handle_irq = shmobile_handle_irq_intc, .init_machine = sh7372_add_standard_devices_dt, - .init_time = shmobile_timer_init, .dt_compat = sh7372_boards_compat_dt, MACHINE_END diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index e8cd93a5c550..fdf3894b1cc3 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -1037,7 +1037,6 @@ DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)") .nr_irqs = NR_IRQS_LEGACY, .init_irq = irqchip_init, .init_machine = sh73a0_add_standard_devices_dt, - .init_time = shmobile_timer_init, .dt_compat = sh73a0_boards_compat_dt, MACHINE_END #endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index 3d16d4dff01b..f321dbeb2379 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c @@ -19,10 +19,8 @@ * */ #include <linux/platform_device.h> +#include <linux/clocksource.h> #include <linux/delay.h> -#include <asm/arch_timer.h> -#include <asm/mach/time.h> -#include <asm/smp_twd.h> void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz, unsigned int mult, unsigned int div) @@ -63,6 +61,5 @@ void __init shmobile_earlytimer_init(void) void __init shmobile_timer_init(void) { - arch_timer_of_register(); - arch_timer_sched_clock_init(); + clocksource_of_init(); } diff --git a/arch/arm/mach-spear/Makefile b/arch/arm/mach-spear/Makefile index af9bffb94f1c..a946c19ab31a 100644 --- a/arch/arm/mach-spear/Makefile +++ b/arch/arm/mach-spear/Makefile @@ -7,10 +7,10 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include # Common support obj-y := restart.o time.o -obj-$(CONFIG_SMP) += headsmp.o platsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +smp-$(CONFIG_SMP) += headsmp.o platsmp.o +smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_ARCH_SPEAR13XX) += spear13xx.o +obj-$(CONFIG_ARCH_SPEAR13XX) += spear13xx.o $(smp-y) obj-$(CONFIG_MACH_SPEAR1310) += spear1310.o obj-$(CONFIG_MACH_SPEAR1340) += spear1340.o diff --git a/arch/arm/mach-spear/generic.h b/arch/arm/mach-spear/generic.h index 8ba7e75b648d..a9fd45362fee 100644 --- a/arch/arm/mach-spear/generic.h +++ b/arch/arm/mach-spear/generic.h @@ -22,11 +22,6 @@ extern void spear13xx_timer_init(void); extern void spear3xx_timer_init(void); extern struct pl022_ssp_controller pl022_plat_data; extern struct pl08x_platform_data pl080_plat_data; -extern struct dw_dma_platform_data dmac_plat_data; -extern struct dw_dma_slave cf_dma_priv; -extern struct dw_dma_slave nand_read_dma_priv; -extern struct dw_dma_slave nand_write_dma_priv; -bool dw_dma_filter(struct dma_chan *chan, void *slave); void __init spear_setup_of_timer(void); void __init spear3xx_clk_init(void __iomem *misc_base, diff --git a/arch/arm/mach-spear/include/mach/spear.h b/arch/arm/mach-spear/include/mach/spear.h index 374ddc393df1..cf3a5369eeca 100644 --- a/arch/arm/mach-spear/include/mach/spear.h +++ b/arch/arm/mach-spear/include/mach/spear.h @@ -82,8 +82,6 @@ #define VA_L2CC_BASE IOMEM(UL(0xFB000000)) /* others */ -#define DMAC0_BASE UL(0xEA800000) -#define DMAC1_BASE UL(0xEB000000) #define MCIF_CF_BASE UL(0xB2800000) /* Debug uart for linux, will be used for debug and uncompress messages */ diff --git a/arch/arm/mach-spear/spear1310.c b/arch/arm/mach-spear/spear1310.c index ed3b5c287a7b..9eaac2c881ea 100644 --- a/arch/arm/mach-spear/spear1310.c +++ b/arch/arm/mach-spear/spear1310.c @@ -23,40 +23,12 @@ #include <mach/spear.h> /* Base addresses */ -#define SPEAR1310_SSP1_BASE UL(0x5D400000) -#define SPEAR1310_SATA0_BASE UL(0xB1000000) -#define SPEAR1310_SATA1_BASE UL(0xB1800000) -#define SPEAR1310_SATA2_BASE UL(0xB4000000) - #define SPEAR1310_RAS_GRP1_BASE UL(0xD8000000) #define VA_SPEAR1310_RAS_GRP1_BASE UL(0xFA000000) -static struct arasan_cf_pdata cf_pdata = { - .cf_if_clk = CF_IF_CLK_166M, - .quirk = CF_BROKEN_UDMA, - .dma_priv = &cf_dma_priv, -}; - -/* ssp device registration */ -static struct pl022_ssp_controller ssp1_plat_data = { - .enable_dma = 0, -}; - -/* Add SPEAr1310 auxdata to pass platform data */ -static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata), - OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data), - OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data), - OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data), - - OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data), - {} -}; - static void __init spear1310_dt_init(void) { - of_platform_populate(NULL, of_default_bus_match_table, - spear1310_auxdata_lookup, NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } static const char * const spear1310_dt_board_compat[] = { diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c index 75e38644bbfb..a04a7fe76f71 100644 --- a/arch/arm/mach-spear/spear1340.c +++ b/arch/arm/mach-spear/spear1340.c @@ -16,18 +16,16 @@ #include <linux/ahci_platform.h> #include <linux/amba/serial.h> #include <linux/delay.h> -#include <linux/dw_dmac.h> #include <linux/of_platform.h> #include <linux/irqchip.h> #include <asm/mach/arch.h> #include "generic.h" #include <mach/spear.h> -#include "spear13xx-dma.h" +/* FIXME: Move SATA PHY code into a standalone driver */ /* Base addresses */ #define SPEAR1340_SATA_BASE UL(0xB1000000) -#define SPEAR1340_UART1_BASE UL(0xB4100000) /* Power Management Registers */ #define SPEAR1340_PCM_CFG (VA_MISC_BASE + 0x100) @@ -79,28 +77,6 @@ (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \ SPEAR1340_MIPHY_PLL_RATIO_TOP(25)) -static struct dw_dma_slave uart1_dma_param[] = { - { - /* Tx */ - .cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX), - .cfg_lo = 0, - .src_master = DMA_MASTER_MEMORY, - .dst_master = SPEAR1340_DMA_MASTER_UART1, - }, { - /* Rx */ - .cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX), - .cfg_lo = 0, - .src_master = SPEAR1340_DMA_MASTER_UART1, - .dst_master = DMA_MASTER_MEMORY, - } -}; - -static struct amba_pl011_data uart1_data = { - .dma_filter = dw_dma_filter, - .dma_tx_param = &uart1_dma_param[0], - .dma_rx_param = &uart1_dma_param[1], -}; - /* SATA device registration */ static int sata_miphy_init(struct device *dev, void __iomem *addr) { @@ -159,14 +135,8 @@ static struct ahci_platform_data sata_pdata = { /* Add SPEAr1340 auxdata to pass platform data */ static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv), - OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data), - OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data), - OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data), - OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL, &sata_pdata), - OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data), {} }; diff --git a/arch/arm/mach-spear/spear13xx-dma.h b/arch/arm/mach-spear/spear13xx-dma.h deleted file mode 100644 index d50bdb605925..000000000000 --- a/arch/arm/mach-spear/spear13xx-dma.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * arch/arm/mach-spear13xx/include/mach/dma.h - * - * DMA information for SPEAr13xx machine family - * - * Copyright (C) 2012 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#ifndef __MACH_DMA_H -#define __MACH_DMA_H - -/* request id of all the peripherals */ -enum dma_master_info { - /* Accessible from only one master */ - DMA_MASTER_MCIF = 0, - DMA_MASTER_FSMC = 1, - /* Accessible from both 0 & 1 */ - DMA_MASTER_MEMORY = 0, - DMA_MASTER_ADC = 0, - DMA_MASTER_UART0 = 0, - DMA_MASTER_SSP0 = 0, - DMA_MASTER_I2C0 = 0, - -#ifdef CONFIG_MACH_SPEAR1310 - /* Accessible from only one master */ - SPEAR1310_DMA_MASTER_JPEG = 1, - - /* Accessible from both 0 & 1 */ - SPEAR1310_DMA_MASTER_I2S = 0, - SPEAR1310_DMA_MASTER_UART1 = 0, - SPEAR1310_DMA_MASTER_UART2 = 0, - SPEAR1310_DMA_MASTER_UART3 = 0, - SPEAR1310_DMA_MASTER_UART4 = 0, - SPEAR1310_DMA_MASTER_UART5 = 0, - SPEAR1310_DMA_MASTER_I2C1 = 0, - SPEAR1310_DMA_MASTER_I2C2 = 0, - SPEAR1310_DMA_MASTER_I2C3 = 0, - SPEAR1310_DMA_MASTER_I2C4 = 0, - SPEAR1310_DMA_MASTER_I2C5 = 0, - SPEAR1310_DMA_MASTER_I2C6 = 0, - SPEAR1310_DMA_MASTER_I2C7 = 0, - SPEAR1310_DMA_MASTER_SSP1 = 0, -#endif - -#ifdef CONFIG_MACH_SPEAR1340 - /* Accessible from only one master */ - SPEAR1340_DMA_MASTER_I2S_PLAY = 1, - SPEAR1340_DMA_MASTER_I2S_REC = 1, - SPEAR1340_DMA_MASTER_I2C1 = 1, - SPEAR1340_DMA_MASTER_UART1 = 1, - - /* following are accessible from both master 0 & 1 */ - SPEAR1340_DMA_MASTER_SPDIF = 0, - SPEAR1340_DMA_MASTER_CAM = 1, - SPEAR1340_DMA_MASTER_VIDEO_IN = 0, - SPEAR1340_DMA_MASTER_MALI = 0, -#endif -}; - -enum request_id { - DMA_REQ_ADC = 0, - DMA_REQ_SSP0_TX = 4, - DMA_REQ_SSP0_RX = 5, - DMA_REQ_UART0_TX = 6, - DMA_REQ_UART0_RX = 7, - DMA_REQ_I2C0_TX = 8, - DMA_REQ_I2C0_RX = 9, - -#ifdef CONFIG_MACH_SPEAR1310 - SPEAR1310_DMA_REQ_FROM_JPEG = 2, - SPEAR1310_DMA_REQ_TO_JPEG = 3, - SPEAR1310_DMA_REQ_I2S_TX = 10, - SPEAR1310_DMA_REQ_I2S_RX = 11, - - SPEAR1310_DMA_REQ_I2C1_RX = 0, - SPEAR1310_DMA_REQ_I2C1_TX = 1, - SPEAR1310_DMA_REQ_I2C2_RX = 2, - SPEAR1310_DMA_REQ_I2C2_TX = 3, - SPEAR1310_DMA_REQ_I2C3_RX = 4, - SPEAR1310_DMA_REQ_I2C3_TX = 5, - SPEAR1310_DMA_REQ_I2C4_RX = 6, - SPEAR1310_DMA_REQ_I2C4_TX = 7, - SPEAR1310_DMA_REQ_I2C5_RX = 8, - SPEAR1310_DMA_REQ_I2C5_TX = 9, - SPEAR1310_DMA_REQ_I2C6_RX = 10, - SPEAR1310_DMA_REQ_I2C6_TX = 11, - SPEAR1310_DMA_REQ_UART1_RX = 12, - SPEAR1310_DMA_REQ_UART1_TX = 13, - SPEAR1310_DMA_REQ_UART2_RX = 14, - SPEAR1310_DMA_REQ_UART2_TX = 15, - SPEAR1310_DMA_REQ_UART5_RX = 16, - SPEAR1310_DMA_REQ_UART5_TX = 17, - SPEAR1310_DMA_REQ_SSP1_RX = 18, - SPEAR1310_DMA_REQ_SSP1_TX = 19, - SPEAR1310_DMA_REQ_I2C7_RX = 20, - SPEAR1310_DMA_REQ_I2C7_TX = 21, - SPEAR1310_DMA_REQ_UART3_RX = 28, - SPEAR1310_DMA_REQ_UART3_TX = 29, - SPEAR1310_DMA_REQ_UART4_RX = 30, - SPEAR1310_DMA_REQ_UART4_TX = 31, -#endif - -#ifdef CONFIG_MACH_SPEAR1340 - SPEAR1340_DMA_REQ_SPDIF_TX = 2, - SPEAR1340_DMA_REQ_SPDIF_RX = 3, - SPEAR1340_DMA_REQ_I2S_TX = 10, - SPEAR1340_DMA_REQ_I2S_RX = 11, - SPEAR1340_DMA_REQ_UART1_TX = 12, - SPEAR1340_DMA_REQ_UART1_RX = 13, - SPEAR1340_DMA_REQ_I2C1_TX = 14, - SPEAR1340_DMA_REQ_I2C1_RX = 15, - SPEAR1340_DMA_REQ_CAM0_EVEN = 0, - SPEAR1340_DMA_REQ_CAM0_ODD = 1, - SPEAR1340_DMA_REQ_CAM1_EVEN = 2, - SPEAR1340_DMA_REQ_CAM1_ODD = 3, - SPEAR1340_DMA_REQ_CAM2_EVEN = 4, - SPEAR1340_DMA_REQ_CAM2_ODD = 5, - SPEAR1340_DMA_REQ_CAM3_EVEN = 6, - SPEAR1340_DMA_REQ_CAM3_ODD = 7, -#endif -}; - -#endif /* __MACH_DMA_H */ diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c index 6dd208997176..7aa6e8cf830f 100644 --- a/arch/arm/mach-spear/spear13xx.c +++ b/arch/arm/mach-spear/spear13xx.c @@ -16,70 +16,12 @@ #include <linux/amba/pl022.h> #include <linux/clk.h> #include <linux/clocksource.h> -#include <linux/dw_dmac.h> #include <linux/err.h> #include <linux/of.h> #include <asm/hardware/cache-l2x0.h> #include <asm/mach/map.h> -#include "generic.h" #include <mach/spear.h> - -#include "spear13xx-dma.h" - -/* common dw_dma filter routine to be used by peripherals */ -bool dw_dma_filter(struct dma_chan *chan, void *slave) -{ - struct dw_dma_slave *dws = (struct dw_dma_slave *)slave; - - if (chan->device->dev == dws->dma_dev) { - chan->private = slave; - return true; - } else { - return false; - } -} - -/* ssp device registration */ -static struct dw_dma_slave ssp_dma_param[] = { - { - /* Tx */ - .cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX), - .cfg_lo = 0, - .src_master = DMA_MASTER_MEMORY, - .dst_master = DMA_MASTER_SSP0, - }, { - /* Rx */ - .cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX), - .cfg_lo = 0, - .src_master = DMA_MASTER_SSP0, - .dst_master = DMA_MASTER_MEMORY, - } -}; - -struct pl022_ssp_controller pl022_plat_data = { - .enable_dma = 1, - .dma_filter = dw_dma_filter, - .dma_rx_param = &ssp_dma_param[1], - .dma_tx_param = &ssp_dma_param[0], -}; - -/* CF device registration */ -struct dw_dma_slave cf_dma_priv = { - .cfg_hi = 0, - .cfg_lo = 0, - .src_master = 0, - .dst_master = 0, -}; - -/* dmac device registeration */ -struct dw_dma_platform_data dmac_plat_data = { - .nr_channels = 8, - .chan_allocation_order = CHAN_ALLOCATION_DESCENDING, - .chan_priority = CHAN_PRIORITY_DESCENDING, - .block_size = 4095U, - .nr_masters = 2, - .data_width = { 3, 3, 0, 0 }, -}; +#include "generic.h" void __init spear13xx_l2x0_init(void) { @@ -93,6 +35,8 @@ void __init spear13xx_l2x0_init(void) * write alloc and 'Full line of zero' options * */ + if (!IS_ENABLED(CONFIG_CACHE_L2X0)) + return; writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL); diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 20c3b372cdf5..84d72fc36dfe 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -63,6 +63,7 @@ config ARCH_TEGRA_114_SOC select ARM_ARCH_TIMER select ARM_GIC select ARM_L1_CACHE_SHIFT_6 + select CPU_FREQ_TABLE if CPU_FREQ select CPU_V7 select PINCTRL select PINCTRL_TEGRA114 diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c index 9e8bdfa2b369..31e69a019bdd 100644 --- a/arch/arm/mach-tegra/tegra2_emc.c +++ b/arch/arm/mach-tegra/tegra2_emc.c @@ -307,11 +307,6 @@ static int tegra_emc_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "missing register base\n"); - return -ENOMEM; - } - emc_regbase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(emc_regbase)) return PTR_ERR(emc_regbase); diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index f66d7deae46d..6a4387e39df8 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -19,6 +19,8 @@ if ARCH_U8500 config UX500_SOC_COMMON bool default y + select ABX500_CORE + select AB8500_CORE select ARM_ERRATA_754322 select ARM_ERRATA_764369 if SMP select ARM_GIC diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index a15dd6b63a8f..3cd555ac6d0a 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -403,8 +403,8 @@ static int mop500_prox_activate(struct device *dev) "no regulator\n"); return PTR_ERR(prox_regulator); } - regulator_enable(prox_regulator); - return 0; + + return regulator_enable(prox_regulator); } static void mop500_prox_deactivate(struct device *dev) diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 995928ba22fd..e90b5ab23b6d 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -191,7 +191,7 @@ static const char *db8500_read_soc_id(void) /* Throw these device-specific numbers into the entropy pool */ add_device_randomness(uid, 0x14); return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x", - readl((u32 *)uid+1), + readl((u32 *)uid+0), readl((u32 *)uid+1), readl((u32 *)uid+2), readl((u32 *)uid+3), readl((u32 *)uid+4)); } diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 25160aeaa3b7..54bb80b012ac 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -749,12 +749,25 @@ void versatile_restart(char mode, const char *cmd) /* Early initializations */ void __init versatile_init_early(void) { + u32 val; void __iomem *sys = __io_address(VERSATILE_SYS_BASE); osc4_clk.vcoreg = sys + VERSATILE_SYS_OSCCLCD_OFFSET; clkdev_add_table(lookups, ARRAY_SIZE(lookups)); versatile_sched_clock_init(sys + VERSATILE_SYS_24MHz_OFFSET, 24000000); + + /* + * set clock frequency: + * VERSATILE_REFCLK is 32KHz + * VERSATILE_TIMCLK is 1MHz + */ + val = readl(__io_address(VERSATILE_SCTL_BASE)); + writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | + (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val, + __io_address(VERSATILE_SCTL_BASE)); } void __init versatile_init(void) @@ -785,19 +798,6 @@ void __init versatile_init(void) */ void __init versatile_timer_init(void) { - u32 val; - - /* - * set clock frequency: - * VERSATILE_REFCLK is 32KHz - * VERSATILE_TIMCLK is 1MHz - */ - val = readl(__io_address(VERSATILE_SCTL_BASE)); - writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | - (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | - (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | - (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val, - __io_address(VERSATILE_SCTL_BASE)); /* * Initialise to a known state (all timers off) diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c index 2558f2e957c3..3621b000a0f6 100644 --- a/arch/arm/mach-versatile/versatile_dt.c +++ b/arch/arm/mach-versatile/versatile_dt.c @@ -45,7 +45,6 @@ DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)") .map_io = versatile_map_io, .init_early = versatile_init_early, .init_irq = versatile_init_irq, - .init_time = versatile_timer_init, .init_machine = versatile_dt_init, .dt_compat = versatile_dt_match, .restart = versatile_restart, diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 9366f37902d9..8802030df98d 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -1,6 +1,7 @@ /* * Versatile Express V2M Motherboard Support */ +#include <linux/clocksource.h> #include <linux/device.h> #include <linux/amba/bus.h> #include <linux/amba/mmci.h> @@ -25,7 +26,6 @@ #include <linux/clk-provider.h> #include <linux/clkdev.h> -#include <asm/arch_timer.h> #include <asm/mach-types.h> #include <asm/sizes.h> #include <asm/mach/arch.h> @@ -63,9 +63,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq) if (WARN_ON(!base || irq == NO_IRQ)) return; - writel(0, base + TIMER_1_BASE + TIMER_CTRL); - writel(0, base + TIMER_2_BASE + TIMER_CTRL); - sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1"); sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0"); } @@ -430,29 +427,11 @@ void __init v2m_dt_init_early(void) static void __init v2m_dt_timer_init(void) { - struct device_node *node = NULL; - of_clk_init(NULL); clocksource_of_init(); - do { - node = of_find_compatible_node(node, NULL, "arm,sp804"); - } while (node && vexpress_get_site_by_node(node) != VEXPRESS_SITE_MB); - if (node) { - pr_info("Using SP804 '%s' as a clock & events source\n", - node->full_name); - WARN_ON(clk_register_clkdev(of_clk_get_by_name(node, - "timclken1"), "v2m-timer0", "sp804")); - WARN_ON(clk_register_clkdev(of_clk_get_by_name(node, - "timclken2"), "v2m-timer1", "sp804")); - v2m_sp804_init(of_iomap(node, 0), - irq_of_parse_and_map(node, 0)); - } - - arch_timer_of_register(); - if (arch_timer_sched_clock_init() != 0) - versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), + versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000); } @@ -471,7 +450,6 @@ static void __init v2m_dt_init(void) static const char * const v2m_dt_match[] __initconst = { "arm,vexpress", - "xen,xenvm", NULL, }; diff --git a/arch/arm/mach-virt/virt.c b/arch/arm/mach-virt/virt.c index 31666f6b4373..061f283f579e 100644 --- a/arch/arm/mach-virt/virt.c +++ b/arch/arm/mach-virt/virt.c @@ -23,23 +23,16 @@ #include <linux/of_platform.h> #include <linux/smp.h> -#include <asm/arch_timer.h> #include <asm/mach/arch.h> -#include <asm/mach/time.h> static void __init virt_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static void __init virt_timer_init(void) -{ - WARN_ON(arch_timer_of_register() != 0); - WARN_ON(arch_timer_sched_clock_init() != 0); -} - static const char *virt_dt_match[] = { "linux,dummy-virt", + "xen,xenvm", NULL }; @@ -47,7 +40,6 @@ extern struct smp_operations virt_smp_ops; DT_MACHINE_START(VIRT, "Dummy Virtual Machine") .init_irq = irqchip_init, - .init_time = virt_timer_init, .init_machine = virt_init, .smp = smp_ops(virt_smp_ops), .dt_compat = virt_dt_match, diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index cf3226b041f5..c1d61f281e68 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -10,6 +10,7 @@ config ARCH_ZYNQ select ICST select MIGHT_HAVE_CACHE_L2X0 select USE_OF + select HAVE_SMP select SPARSE_IRQ select CADENCE_TTC_TIMER help diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile index 320faedeb484..1b25d92ebf22 100644 --- a/arch/arm/mach-zynq/Makefile +++ b/arch/arm/mach-zynq/Makefile @@ -3,4 +3,8 @@ # # Common support -obj-y := common.o +obj-y := common.o slcr.o +CFLAGS_REMOVE_hotplug.o =-march=armv6k +CFLAGS_hotplug.o =-Wa,-march=armv7-a -mcpu=cortex-a9 +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 68e0907de5d0..5bfe7035b73d 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -33,20 +33,23 @@ #include <asm/mach-types.h> #include <asm/page.h> #include <asm/pgtable.h> +#include <asm/smp_scu.h> #include <asm/hardware/cache-l2x0.h> #include "common.h" +void __iomem *zynq_scu_base; + static struct of_device_id zynq_of_bus_ids[] __initdata = { { .compatible = "simple-bus", }, {} }; /** - * xilinx_init_machine() - System specific initialization, intended to be - * called from board specific initialization. + * zynq_init_machine - System specific initialization, intended to be + * called from board specific initialization. */ -static void __init xilinx_init_machine(void) +static void __init zynq_init_machine(void) { /* * 64KB way size, 8-way associativity, parity disabled @@ -56,50 +59,56 @@ static void __init xilinx_init_machine(void) of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL); } -#define SCU_PERIPH_PHYS 0xF8F00000 -#define SCU_PERIPH_SIZE SZ_8K -#define SCU_PERIPH_VIRT (VMALLOC_END - SCU_PERIPH_SIZE) +static void __init zynq_timer_init(void) +{ + zynq_slcr_init(); + clocksource_of_init(); +} -static struct map_desc scu_desc __initdata = { - .virtual = SCU_PERIPH_VIRT, - .pfn = __phys_to_pfn(SCU_PERIPH_PHYS), - .length = SCU_PERIPH_SIZE, - .type = MT_DEVICE, +static struct map_desc zynq_cortex_a9_scu_map __initdata = { + .length = SZ_256, + .type = MT_DEVICE, }; -static void __init xilinx_zynq_timer_init(void) +static void __init zynq_scu_map_io(void) { - struct device_node *np; - void __iomem *slcr; - - np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); - slcr = of_iomap(np, 0); - WARN_ON(!slcr); + unsigned long base; - xilinx_zynq_clocks_init(slcr); - - clocksource_of_init(); + base = scu_a9_get_base(); + zynq_cortex_a9_scu_map.pfn = __phys_to_pfn(base); + /* Expected address is in vmalloc area that's why simple assign here */ + zynq_cortex_a9_scu_map.virtual = base; + iotable_init(&zynq_cortex_a9_scu_map, 1); + zynq_scu_base = (void __iomem *)base; + BUG_ON(!zynq_scu_base); } /** - * xilinx_map_io() - Create memory mappings needed for early I/O. + * zynq_map_io - Create memory mappings needed for early I/O. */ -static void __init xilinx_map_io(void) +static void __init zynq_map_io(void) { debug_ll_io_init(); - iotable_init(&scu_desc, 1); + zynq_scu_map_io(); +} + +static void zynq_system_reset(char mode, const char *cmd) +{ + zynq_slcr_system_reset(); } -static const char *xilinx_dt_match[] = { +static const char * const zynq_dt_match[] = { "xlnx,zynq-zc702", "xlnx,zynq-7000", NULL }; MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") - .map_io = xilinx_map_io, + .smp = smp_ops(zynq_smp_ops), + .map_io = zynq_map_io, .init_irq = irqchip_init, - .init_machine = xilinx_init_machine, - .init_time = xilinx_zynq_timer_init, - .dt_compat = xilinx_dt_match, + .init_machine = zynq_init_machine, + .init_time = zynq_timer_init, + .dt_compat = zynq_dt_match, + .restart = zynq_system_reset, MACHINE_END diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index 5050bb10bb12..fbbd0e21c404 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -17,4 +17,24 @@ #ifndef __MACH_ZYNQ_COMMON_H__ #define __MACH_ZYNQ_COMMON_H__ +extern int zynq_slcr_init(void); +extern void zynq_slcr_system_reset(void); +extern void zynq_slcr_cpu_stop(int cpu); +extern void zynq_slcr_cpu_start(int cpu); + +#ifdef CONFIG_SMP +extern void secondary_startup(void); +extern char zynq_secondary_trampoline; +extern char zynq_secondary_trampoline_jump; +extern char zynq_secondary_trampoline_end; +extern int __cpuinit zynq_cpun_start(u32 address, int cpu); +extern struct smp_operations zynq_smp_ops __initdata; +#endif + +extern void __iomem *zynq_slcr_base; +extern void __iomem *zynq_scu_base; + +/* Hotplug */ +extern void zynq_platform_cpu_die(unsigned int cpu); + #endif diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S new file mode 100644 index 000000000000..d183cd234a9b --- /dev/null +++ b/arch/arm/mach-zynq/headsmp.S @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de> + * Copyright (c) 2012-2013 Xilinx + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/linkage.h> +#include <linux/init.h> + + __CPUINIT + +ENTRY(zynq_secondary_trampoline) + ldr r0, [pc] + bx r0 +.globl zynq_secondary_trampoline_jump +zynq_secondary_trampoline_jump: + /* Space for jumping address */ + .word /* cpu 1 */ +.globl zynq_secondary_trampoline_end +zynq_secondary_trampoline_end: + +ENDPROC(zynq_secondary_trampoline) diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c new file mode 100644 index 000000000000..c89672bd1de2 --- /dev/null +++ b/arch/arm/mach-zynq/hotplug.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012-2013 Xilinx + * + * based on linux/arch/arm/mach-realview/hotplug.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/smp.h> + +#include <asm/cacheflush.h> +#include <asm/cp15.h> +#include "common.h" + +static inline void zynq_cpu_enter_lowpower(void) +{ + unsigned int v; + + flush_cache_all(); + asm volatile( + " mcr p15, 0, %1, c7, c5, 0\n" + " dsb\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x40\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0), "Ir" (CR_C) + : "cc"); +} + +static inline void zynq_cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( + " mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, #0x40\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C) + : "cc"); +} + +static inline void zynq_platform_do_lowpower(unsigned int cpu, int *spurious) +{ + /* + * there is no power-control hardware on this platform, so all + * we can do is put the core into WFI; this is safe as the calling + * code will have already disabled interrupts + */ + for (;;) { + dsb(); + wfi(); + + /* + * Getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * Just note it happening - when we're woken, we can report + * its occurrence. + */ + (*spurious)++; + } +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void zynq_platform_cpu_die(unsigned int cpu) +{ + int spurious = 0; + + /* + * we're ready for shutdown now, so do it + */ + zynq_cpu_enter_lowpower(); + zynq_platform_do_lowpower(cpu, &spurious); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + zynq_cpu_leave_lowpower(); + + if (spurious) + pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); +} diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c new file mode 100644 index 000000000000..5fc167e07619 --- /dev/null +++ b/arch/arm/mach-zynq/platsmp.c @@ -0,0 +1,136 @@ +/* + * This file contains Xilinx specific SMP code, used to start up + * the second processor. + * + * Copyright (C) 2011-2013 Xilinx + * + * based on linux/arch/arm/mach-realview/platsmp.c + * + * Copyright (C) 2002 ARM Ltd. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/export.h> +#include <linux/jiffies.h> +#include <linux/init.h> +#include <linux/io.h> +#include <asm/cacheflush.h> +#include <asm/smp_scu.h> +#include <linux/irqchip/arm-gic.h> +#include "common.h" + +/* + * Store number of cores in the system + * Because of scu_get_core_count() must be in __init section and can't + * be called from zynq_cpun_start() because it is in __cpuinit section. + */ +static int ncores; + +int __cpuinit zynq_cpun_start(u32 address, int cpu) +{ + u32 trampoline_code_size = &zynq_secondary_trampoline_end - + &zynq_secondary_trampoline; + + if (cpu > ncores) { + pr_warn("CPU No. is not available in the system\n"); + return -1; + } + + /* MS: Expectation that SLCR are directly map and accessible */ + /* Not possible to jump to non aligned address */ + if (!(address & 3) && (!address || (address >= trampoline_code_size))) { + /* Store pointer to ioremap area which points to address 0x0 */ + static u8 __iomem *zero; + u32 trampoline_size = &zynq_secondary_trampoline_jump - + &zynq_secondary_trampoline; + + zynq_slcr_cpu_stop(cpu); + + if (__pa(PAGE_OFFSET)) { + zero = ioremap(0, trampoline_code_size); + if (!zero) { + pr_warn("BOOTUP jump vectors not accessible\n"); + return -1; + } + } else { + zero = (__force u8 __iomem *)PAGE_OFFSET; + } + + /* + * This is elegant way how to jump to any address + * 0x0: Load address at 0x8 to r0 + * 0x4: Jump by mov instruction + * 0x8: Jumping address + */ + memcpy((__force void *)zero, &zynq_secondary_trampoline, + trampoline_size); + writel(address, zero + trampoline_size); + + flush_cache_all(); + outer_flush_range(0, trampoline_code_size); + smp_wmb(); + + if (__pa(PAGE_OFFSET)) + iounmap(zero); + + zynq_slcr_cpu_start(cpu); + + return 0; + } + + pr_warn("Can't start CPU%d: Wrong starting address %x\n", cpu, address); + + return -1; +} +EXPORT_SYMBOL(zynq_cpun_start); + +static int __cpuinit zynq_boot_secondary(unsigned int cpu, + struct task_struct *idle) +{ + return zynq_cpun_start(virt_to_phys(secondary_startup), cpu); +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. + */ +static void __init zynq_smp_init_cpus(void) +{ + int i; + + ncores = scu_get_core_count(zynq_scu_base); + + for (i = 0; i < ncores && i < CONFIG_NR_CPUS; i++) + set_cpu_possible(i, true); +} + +static void __init zynq_smp_prepare_cpus(unsigned int max_cpus) +{ + int i; + + /* + * Initialise the present map, which describes the set of CPUs + * actually populated at the present time. + */ + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + + scu_enable(zynq_scu_base); +} + +struct smp_operations zynq_smp_ops __initdata = { + .smp_init_cpus = zynq_smp_init_cpus, + .smp_prepare_cpus = zynq_smp_prepare_cpus, + .smp_boot_secondary = zynq_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = zynq_platform_cpu_die, +#endif +}; diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c new file mode 100644 index 000000000000..c70969b9c258 --- /dev/null +++ b/arch/arm/mach-zynq/slcr.c @@ -0,0 +1,125 @@ +/* + * Xilinx SLCR driver + * + * Copyright (c) 2011-2013 Xilinx Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA + * 02139, USA. + */ + +#include <linux/export.h> +#include <linux/io.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/uaccess.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/clk/zynq.h> +#include "common.h" + +#define SLCR_UNLOCK_MAGIC 0xDF0D +#define SLCR_UNLOCK 0x8 /* SCLR unlock register */ + +#define SLCR_PS_RST_CTRL_OFFSET 0x200 /* PS Software Reset Control */ + +#define SLCR_A9_CPU_CLKSTOP 0x10 +#define SLCR_A9_CPU_RST 0x1 + +#define SLCR_A9_CPU_RST_CTRL 0x244 /* CPU Software Reset Control */ +#define SLCR_REBOOT_STATUS 0x258 /* PS Reboot Status */ + +void __iomem *zynq_slcr_base; + +/** + * zynq_slcr_system_reset - Reset the entire system. + */ +void zynq_slcr_system_reset(void) +{ + u32 reboot; + + /* + * Unlock the SLCR then reset the system. + * Note that this seems to require raw i/o + * functions or there's a lockup? + */ + writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK); + + /* + * Clear 0x0F000000 bits of reboot status register to workaround + * the FSBL not loading the bitstream after soft-reboot + * This is a temporary solution until we know more. + */ + reboot = readl(zynq_slcr_base + SLCR_REBOOT_STATUS); + writel(reboot & 0xF0FFFFFF, zynq_slcr_base + SLCR_REBOOT_STATUS); + writel(1, zynq_slcr_base + SLCR_PS_RST_CTRL_OFFSET); +} + +/** + * zynq_slcr_cpu_start - Start cpu + * @cpu: cpu number + */ +void zynq_slcr_cpu_start(int cpu) +{ + /* enable CPUn */ + writel(SLCR_A9_CPU_CLKSTOP << cpu, + zynq_slcr_base + SLCR_A9_CPU_RST_CTRL); + /* enable CLK for CPUn */ + writel(0x0 << cpu, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL); +} + +/** + * zynq_slcr_cpu_stop - Stop cpu + * @cpu: cpu number + */ +void zynq_slcr_cpu_stop(int cpu) +{ + /* stop CLK and reset CPUn */ + writel((SLCR_A9_CPU_CLKSTOP | SLCR_A9_CPU_RST) << cpu, + zynq_slcr_base + SLCR_A9_CPU_RST_CTRL); +} + +/** + * zynq_slcr_init + * Returns 0 on success, negative errno otherwise. + * + * Called early during boot from platform code to remap SLCR area. + */ +int __init zynq_slcr_init(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); + if (!np) { + pr_err("%s: no slcr node found\n", __func__); + BUG(); + } + + zynq_slcr_base = of_iomap(np, 0); + if (!zynq_slcr_base) { + pr_err("%s: Unable to map I/O memory\n", __func__); + BUG(); + } + + /* unlock the SLCR so that registers can be changed */ + writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK); + + pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); + + xilinx_zynq_clocks_init(zynq_slcr_base); + + of_node_put(np); + + return 0; +} diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index e6dbc8dbe6a6..869254cebf84 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -52,6 +52,13 @@ static u32 omap_reserved_systimers; static LIST_HEAD(omap_timer_list); static DEFINE_SPINLOCK(dm_timer_lock); +enum { + REQUEST_ANY = 0, + REQUEST_BY_ID, + REQUEST_BY_CAP, + REQUEST_BY_NODE, +}; + /** * omap_dm_timer_read_reg - read timer registers in posted and non-posted mode * @timer: timer pointer over which read operation to perform @@ -177,29 +184,82 @@ int omap_dm_timer_reserve_systimer(int id) return 0; } -struct omap_dm_timer *omap_dm_timer_request(void) +static struct omap_dm_timer *_omap_dm_timer_request(int req_type, void *data) { struct omap_dm_timer *timer = NULL, *t; + struct device_node *np = NULL; unsigned long flags; - int ret = 0; + u32 cap = 0; + int id = 0; + + switch (req_type) { + case REQUEST_BY_ID: + id = *(int *)data; + break; + case REQUEST_BY_CAP: + cap = *(u32 *)data; + break; + case REQUEST_BY_NODE: + np = (struct device_node *)data; + break; + default: + /* REQUEST_ANY */ + break; + } spin_lock_irqsave(&dm_timer_lock, flags); list_for_each_entry(t, &omap_timer_list, node) { if (t->reserved) continue; - timer = t; - timer->reserved = 1; - break; + switch (req_type) { + case REQUEST_BY_ID: + if (id == t->pdev->id) { + timer = t; + timer->reserved = 1; + goto found; + } + break; + case REQUEST_BY_CAP: + if (cap == (t->capability & cap)) { + /* + * If timer is not NULL, we have already found + * one timer but it was not an exact match + * because it had more capabilites that what + * was required. Therefore, unreserve the last + * timer found and see if this one is a better + * match. + */ + if (timer) + timer->reserved = 0; + timer = t; + timer->reserved = 1; + + /* Exit loop early if we find an exact match */ + if (t->capability == cap) + goto found; + } + break; + case REQUEST_BY_NODE: + if (np == t->pdev->dev.of_node) { + timer = t; + timer->reserved = 1; + goto found; + } + break; + default: + /* REQUEST_ANY */ + timer = t; + timer->reserved = 1; + goto found; + } } +found: spin_unlock_irqrestore(&dm_timer_lock, flags); - if (timer) { - ret = omap_dm_timer_prepare(timer); - if (ret) { - timer->reserved = 0; - timer = NULL; - } + if (timer && omap_dm_timer_prepare(timer)) { + timer->reserved = 0; + timer = NULL; } if (!timer) @@ -207,43 +267,23 @@ struct omap_dm_timer *omap_dm_timer_request(void) return timer; } + +struct omap_dm_timer *omap_dm_timer_request(void) +{ + return _omap_dm_timer_request(REQUEST_ANY, NULL); +} EXPORT_SYMBOL_GPL(omap_dm_timer_request); struct omap_dm_timer *omap_dm_timer_request_specific(int id) { - struct omap_dm_timer *timer = NULL, *t; - unsigned long flags; - int ret = 0; - /* Requesting timer by ID is not supported when device tree is used */ if (of_have_populated_dt()) { - pr_warn("%s: Please use omap_dm_timer_request_by_cap()\n", + pr_warn("%s: Please use omap_dm_timer_request_by_cap/node()\n", __func__); return NULL; } - spin_lock_irqsave(&dm_timer_lock, flags); - list_for_each_entry(t, &omap_timer_list, node) { - if (t->pdev->id == id && !t->reserved) { - timer = t; - timer->reserved = 1; - break; - } - } - spin_unlock_irqrestore(&dm_timer_lock, flags); - - if (timer) { - ret = omap_dm_timer_prepare(timer); - if (ret) { - timer->reserved = 0; - timer = NULL; - } - } - - if (!timer) - pr_debug("%s: timer%d request failed!\n", __func__, id); - - return timer; + return _omap_dm_timer_request(REQUEST_BY_ID, &id); } EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); @@ -258,46 +298,25 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); */ struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap) { - struct omap_dm_timer *timer = NULL, *t; - unsigned long flags; + return _omap_dm_timer_request(REQUEST_BY_CAP, &cap); +} +EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap); - if (!cap) +/** + * omap_dm_timer_request_by_node - Request a timer by device-tree node + * @np: Pointer to device-tree timer node + * + * Request a timer based upon a device node pointer. Returns pointer to + * timer handle on success and a NULL pointer on failure. + */ +struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np) +{ + if (!np) return NULL; - spin_lock_irqsave(&dm_timer_lock, flags); - list_for_each_entry(t, &omap_timer_list, node) { - if ((!t->reserved) && ((t->capability & cap) == cap)) { - /* - * If timer is not NULL, we have already found one timer - * but it was not an exact match because it had more - * capabilites that what was required. Therefore, - * unreserve the last timer found and see if this one - * is a better match. - */ - if (timer) - timer->reserved = 0; - - timer = t; - timer->reserved = 1; - - /* Exit loop early if we find an exact match */ - if (t->capability == cap) - break; - } - } - spin_unlock_irqrestore(&dm_timer_lock, flags); - - if (timer && omap_dm_timer_prepare(timer)) { - timer->reserved = 0; - timer = NULL; - } - - if (!timer) - pr_debug("%s: timer request failed!\n", __func__); - - return timer; + return _omap_dm_timer_request(REQUEST_BY_NODE, np); } -EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_cap); +EXPORT_SYMBOL_GPL(omap_dm_timer_request_by_node); int omap_dm_timer_free(struct omap_dm_timer *timer) { @@ -314,7 +333,21 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_free); void omap_dm_timer_enable(struct omap_dm_timer *timer) { + int c; + pm_runtime_get_sync(&timer->pdev->dev); + + if (!(timer->capability & OMAP_TIMER_ALWON)) { + if (timer->get_context_loss_count) { + c = timer->get_context_loss_count(&timer->pdev->dev); + if (c != timer->ctx_loss_count) { + omap_timer_restore_context(timer); + timer->ctx_loss_count = c; + } + } else { + omap_timer_restore_context(timer); + } + } } EXPORT_SYMBOL_GPL(omap_dm_timer_enable); @@ -409,13 +442,6 @@ int omap_dm_timer_start(struct omap_dm_timer *timer) omap_dm_timer_enable(timer); - if (!(timer->capability & OMAP_TIMER_ALWON)) { - if (timer->get_context_loss_count && - timer->get_context_loss_count(&timer->pdev->dev) != - timer->ctx_loss_count) - omap_timer_restore_context(timer); - } - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); if (!(l & OMAP_TIMER_CTRL_ST)) { l |= OMAP_TIMER_CTRL_ST; @@ -440,12 +466,6 @@ int omap_dm_timer_stop(struct omap_dm_timer *timer) __omap_dm_timer_stop(timer, timer->posted, rate); - if (!(timer->capability & OMAP_TIMER_ALWON)) { - if (timer->get_context_loss_count) - timer->ctx_loss_count = - timer->get_context_loss_count(&timer->pdev->dev); - } - /* * Since the register values are computed and written within * __omap_dm_timer_stop, we need to use read to retrieve the @@ -552,13 +572,6 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, omap_dm_timer_enable(timer); - if (!(timer->capability & OMAP_TIMER_ALWON)) { - if (timer->get_context_loss_count && - timer->get_context_loss_count(&timer->pdev->dev) != - timer->ctx_loss_count) - omap_timer_restore_context(timer); - } - l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); if (autoreload) { l |= OMAP_TIMER_CTRL_AR; @@ -769,6 +782,8 @@ int omap_dm_timers_active(void) } EXPORT_SYMBOL_GPL(omap_dm_timers_active); +static const struct of_device_id omap_timer_match[]; + /** * omap_dm_timer_probe - probe function called for every registered device * @pdev: pointer to current timer platform device @@ -782,7 +797,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev) struct omap_dm_timer *timer; struct resource *mem, *irq; struct device *dev = &pdev->dev; - struct dmtimer_platform_data *pdata = pdev->dev.platform_data; + const struct of_device_id *match; + const struct dmtimer_platform_data *pdata; + + match = of_match_device(of_match_ptr(omap_timer_match), dev); + pdata = match ? match->data : dev->platform_data; if (!pdata && !dev->of_node) { dev_err(dev, "%s: no platform data.\n", __func__); @@ -823,12 +842,14 @@ static int omap_dm_timer_probe(struct platform_device *pdev) timer->capability |= OMAP_TIMER_SECURE; } else { timer->id = pdev->id; - timer->errata = pdata->timer_errata; timer->capability = pdata->timer_capability; timer->reserved = omap_dm_timer_reserved_systimer(timer->id); timer->get_context_loss_count = pdata->get_context_loss_count; } + if (pdata) + timer->errata = pdata->timer_errata; + timer->irq = irq->start; timer->pdev = pdev; @@ -881,8 +902,34 @@ static int omap_dm_timer_remove(struct platform_device *pdev) return ret; } +static const struct dmtimer_platform_data omap3plus_pdata = { + .timer_errata = OMAP_TIMER_ERRATA_I103_I767, +}; + static const struct of_device_id omap_timer_match[] = { - { .compatible = "ti,omap2-timer", }, + { + .compatible = "ti,omap2420-timer", + }, + { + .compatible = "ti,omap3430-timer", + .data = &omap3plus_pdata, + }, + { + .compatible = "ti,omap4430-timer", + .data = &omap3plus_pdata, + }, + { + .compatible = "ti,omap5430-timer", + .data = &omap3plus_pdata, + }, + { + .compatible = "ti,am335x-timer", + .data = &omap3plus_pdata, + }, + { + .compatible = "ti,am335x-timer-1ms", + .data = &omap3plus_pdata, + }, {}, }; MODULE_DEVICE_TABLE(of, omap_timer_match); diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index a3fbc48c332e..fb92abb91628 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h @@ -128,6 +128,7 @@ int omap_dm_timer_reserve_systimer(int id); struct omap_dm_timer *omap_dm_timer_request(void); struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); struct omap_dm_timer *omap_dm_timer_request_by_cap(u32 cap); +struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *np); int omap_dm_timer_free(struct omap_dm_timer *timer); void omap_dm_timer_enable(struct omap_dm_timer *timer); void omap_dm_timer_disable(struct omap_dm_timer *timer); diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile index ad97400ba3ad..9433605cd290 100644 --- a/arch/arm/plat-orion/Makefile +++ b/arch/arm/plat-orion/Makefile @@ -3,12 +3,6 @@ # ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include -obj-$(CONFIG_ARCH_MVEBU) += addr-map.o -obj-$(CONFIG_ARCH_KIRKWOOD) += addr-map.o -obj-$(CONFIG_ARCH_DOVE) += addr-map.o -obj-$(CONFIG_ARCH_ORION5X) += addr-map.o -obj-$(CONFIG_ARCH_MV78XX0) += addr-map.o - -orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o +orion-gpio-$(CONFIG_GPIOLIB) += gpio.o obj-$(CONFIG_PLAT_ORION_LEGACY) += irq.o pcie.o time.o common.o mpp.o obj-$(CONFIG_PLAT_ORION_LEGACY) += $(orion-gpio-y) diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c deleted file mode 100644 index 807ac8e5cbc0..000000000000 --- a/arch/arm/plat-orion/addr-map.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * arch/arm/plat-orion/addr-map.c - * - * Address map functions for Marvell Orion based SoCs - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/mbus.h> -#include <linux/io.h> -#include <plat/addr-map.h> - -struct mbus_dram_target_info orion_mbus_dram_info; - -const struct mbus_dram_target_info *mv_mbus_dram_info(void) -{ - return &orion_mbus_dram_info; -} -EXPORT_SYMBOL_GPL(mv_mbus_dram_info); - -/* - * DDR target is the same on all Orion platforms. - */ -#define TARGET_DDR 0 - -/* - * Helpers to get DDR bank info - */ -#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3)) -#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3)) - -/* - * CPU Address Decode Windows registers - */ -#define WIN_CTRL_OFF 0x0000 -#define WIN_BASE_OFF 0x0004 -#define WIN_REMAP_LO_OFF 0x0008 -#define WIN_REMAP_HI_OFF 0x000c - -#define ATTR_HW_COHERENCY (0x1 << 4) - -/* - * Default implementation - */ -static void __init __iomem * -orion_win_cfg_base(const struct orion_addr_map_cfg *cfg, int win) -{ - return cfg->bridge_virt_base + (win << 4); -} - -/* - * Default implementation - */ -static int __init orion_cpu_win_can_remap(const struct orion_addr_map_cfg *cfg, - const int win) -{ - if (win < cfg->remappable_wins) - return 1; - - return 0; -} - -void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg, - const int win, const u32 base, - const u32 size, const u8 target, - const u8 attr, const int remap) -{ - void __iomem *addr = cfg->win_cfg_base(cfg, win); - u32 ctrl, base_high, remap_addr; - - if (win >= cfg->num_wins) { - printk(KERN_ERR "setup_cpu_win: trying to allocate window " - "%d when only %d allowed\n", win, cfg->num_wins); - } - - base_high = base & 0xffff0000; - ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1; - - writel(base_high, addr + WIN_BASE_OFF); - writel(ctrl, addr + WIN_CTRL_OFF); - if (cfg->cpu_win_can_remap(cfg, win)) { - if (remap < 0) - remap_addr = base; - else - remap_addr = remap; - writel(remap_addr & 0xffff0000, addr + WIN_REMAP_LO_OFF); - writel(0, addr + WIN_REMAP_HI_OFF); - } -} - -/* - * Configure a number of windows. - */ -static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg, - const struct orion_addr_map_info *info) -{ - while (info->win != -1) { - orion_setup_cpu_win(cfg, info->win, info->base, info->size, - info->target, info->attr, info->remap); - info++; - } -} - -static void __init orion_disable_wins(const struct orion_addr_map_cfg * cfg) -{ - void __iomem *addr; - int i; - - for (i = 0; i < cfg->num_wins; i++) { - addr = cfg->win_cfg_base(cfg, i); - - writel(0, addr + WIN_BASE_OFF); - writel(0, addr + WIN_CTRL_OFF); - if (cfg->cpu_win_can_remap(cfg, i)) { - writel(0, addr + WIN_REMAP_LO_OFF); - writel(0, addr + WIN_REMAP_HI_OFF); - } - } -} - -/* - * Disable, clear and configure windows. - */ -void __init orion_config_wins(struct orion_addr_map_cfg * cfg, - const struct orion_addr_map_info *info) -{ - if (!cfg->cpu_win_can_remap) - cfg->cpu_win_can_remap = orion_cpu_win_can_remap; - - if (!cfg->win_cfg_base) - cfg->win_cfg_base = orion_win_cfg_base; - - orion_disable_wins(cfg); - - if (info) - orion_setup_cpu_wins(cfg, info); -} - -/* - * Setup MBUS dram target info. - */ -void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg, - const void __iomem *ddr_window_cpu_base) -{ - int i; - int cs; - - orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; - - for (i = 0, cs = 0; i < 4; i++) { - u32 base = readl(ddr_window_cpu_base + DDR_BASE_CS_OFF(i)); - u32 size = readl(ddr_window_cpu_base + DDR_SIZE_CS_OFF(i)); - - /* - * We only take care of entries for which the chip - * select is enabled, and that don't have high base - * address bits set (devices can only access the first - * 32 bits of the memory). - */ - if ((size & 1) && !(base & 0xF)) { - struct mbus_dram_window *w; - - w = &orion_mbus_dram_info.cs[cs++]; - w->cs_index = i; - w->mbus_attr = 0xf & ~(1 << i); - if (cfg->hw_io_coherency) - w->mbus_attr |= ATTR_HW_COHERENCY; - w->base = base & 0xffff0000; - w->size = (size | 0x0000ffff) + 1; - } - } - orion_mbus_dram_info.num_cs = cs; -} diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index c29ee7ea200b..249fe6333e18 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c @@ -150,7 +150,7 @@ err_out: } /* - * GENERIC_GPIO primitives. + * GPIO primitives. */ static int orion_gpio_request(struct gpio_chip *chip, unsigned pin) { @@ -439,6 +439,64 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) } } +#ifdef CONFIG_DEBUG_FS +#include <linux/seq_file.h> + +static void orion_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + struct orion_gpio_chip *ochip = + container_of(chip, struct orion_gpio_chip, chip); + u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk; + int i; + + out = readl_relaxed(GPIO_OUT(ochip)); + io_conf = readl_relaxed(GPIO_IO_CONF(ochip)); + blink = readl_relaxed(GPIO_BLINK_EN(ochip)); + in_pol = readl_relaxed(GPIO_IN_POL(ochip)); + data_in = readl_relaxed(GPIO_DATA_IN(ochip)); + cause = readl_relaxed(GPIO_EDGE_CAUSE(ochip)); + edg_msk = readl_relaxed(GPIO_EDGE_MASK(ochip)); + lvl_msk = readl_relaxed(GPIO_LEVEL_MASK(ochip)); + + for (i = 0; i < chip->ngpio; i++) { + const char *label; + u32 msk; + bool is_out; + + label = gpiochip_is_requested(chip, i); + if (!label) + continue; + + msk = 1 << i; + is_out = !(io_conf & msk); + + seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label); + + if (is_out) { + seq_printf(s, " out %s %s\n", + out & msk ? "hi" : "lo", + blink & msk ? "(blink )" : ""); + continue; + } + + seq_printf(s, " in %s (act %s) - IRQ", + (data_in ^ in_pol) & msk ? "hi" : "lo", + in_pol & msk ? "lo" : "hi"); + if (!((edg_msk | lvl_msk) & msk)) { + seq_printf(s, " disabled\n"); + continue; + } + if (edg_msk & msk) + seq_printf(s, " edge "); + if (lvl_msk & msk) + seq_printf(s, " level"); + seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear "); + } +} +#else +#define orion_gpio_dbg_show NULL +#endif + void __init orion_gpio_init(struct device_node *np, int gpio_base, int ngpio, void __iomem *base, int mask_offset, @@ -471,6 +529,7 @@ void __init orion_gpio_init(struct device_node *np, #ifdef CONFIG_OF ochip->chip.of_node = np; #endif + ochip->chip.dbg_show = orion_gpio_dbg_show; spin_lock_init(&ochip->lock); ochip->base = (void __iomem *)base; diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 54d186106f9f..f8ed2de0a678 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -93,9 +93,9 @@ config SAMSUNG_IRQ_VIC_TIMER Internal configuration to build the VIC timer interrupt code. config S5P_IRQ - def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) + def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210) help - Support common interrup part for ARCH_S5P and ARCH_EXYNOS SoCs + Support common interrupt part for ARCH_S5P SoCs config S5P_EXT_INT bool diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index ca07cb1b155a..79690f2f6d3f 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -381,11 +381,6 @@ static int s3c_adc_probe(struct platform_device *pdev) } regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_err(dev, "failed to find registers\n"); - return -ENXIO; - } - adc->regs = devm_ioremap_resource(dev, regs); if (IS_ERR(adc->regs)) return PTR_ERR(adc->regs); diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 8dc0605a9ce9..13609e01f4b7 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -2,6 +2,7 @@ #include <xen/events.h> #include <xen/grant_table.h> #include <xen/hvm.h> +#include <xen/interface/vcpu.h> #include <xen/interface/xen.h> #include <xen/interface/memory.h> #include <xen/interface/hvm/params.h> @@ -9,9 +10,11 @@ #include <xen/platform_pci.h> #include <xen/xenbus.h> #include <xen/page.h> +#include <xen/interface/sched.h> #include <xen/xen-ops.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> +#include <asm/system_misc.h> #include <linux/interrupt.h> #include <linux/irqreturn.h> #include <linux/module.h> @@ -32,6 +35,7 @@ struct shared_info xen_dummy_shared_info; struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); +static struct vcpu_info __percpu *xen_vcpu_info; /* These are unused until we support booting "pre-ballooned" */ unsigned long xen_released_pages; @@ -148,6 +152,44 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, } EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); +static void __init xen_percpu_init(void *unused) +{ + struct vcpu_register_vcpu_info info; + struct vcpu_info *vcpup; + int err; + int cpu = get_cpu(); + + pr_info("Xen: initializing cpu%d\n", cpu); + vcpup = per_cpu_ptr(xen_vcpu_info, cpu); + + info.mfn = __pa(vcpup) >> PAGE_SHIFT; + info.offset = offset_in_page(vcpup); + + err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); + BUG_ON(err); + per_cpu(xen_vcpu, cpu) = vcpup; + + enable_percpu_irq(xen_events_irq, 0); +} + +static void xen_restart(char str, const char *cmd) +{ + struct sched_shutdown r = { .reason = SHUTDOWN_reboot }; + int rc; + rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); + if (rc) + BUG(); +} + +static void xen_power_off(void) +{ + struct sched_shutdown r = { .reason = SHUTDOWN_poweroff }; + int rc; + rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); + if (rc) + BUG(); +} + /* * see Documentation/devicetree/bindings/arm/xen.txt for the * documentation of the Xen Device Tree format. @@ -209,13 +251,16 @@ static int __init xen_guest_init(void) /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info * page, we use it in the event channel upcall and in some pvclock - * related functions. We don't need the vcpu_info placement - * optimizations because we don't use any pv_mmu or pv_irq op on - * HVM. + * related functions. * The shared info contains exactly 1 CPU (the boot CPU). The guest * is required to use VCPUOP_register_vcpu_info to place vcpu info - * for secondary CPUs as they are brought up. */ - per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; + * for secondary CPUs as they are brought up. + * For uniformity we use VCPUOP_register_vcpu_info even on cpu0. + */ + xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info), + sizeof(struct vcpu_info)); + if (xen_vcpu_info == NULL) + return -ENOMEM; gnttab_init(); if (!xen_initial_domain()) @@ -225,6 +270,15 @@ static int __init xen_guest_init(void) } core_initcall(xen_guest_init); +static int __init xen_pm_init(void) +{ + pm_power_off = xen_power_off; + arm_pm_restart = xen_restart; + + return 0; +} +subsys_initcall(xen_pm_init); + static irqreturn_t xen_arm_callback(int irq, void *arg) { xen_hvm_evtchn_do_upcall(); @@ -239,12 +293,12 @@ static int __init xen_init_events(void) xen_init_IRQ(); if (request_percpu_irq(xen_events_irq, xen_arm_callback, - "events", xen_vcpu)) { + "events", &xen_vcpu)) { pr_err("Error requesting IRQ %d\n", xen_events_irq); return -EINVAL; } - enable_percpu_irq(xen_events_irq, 0); + on_each_cpu(xen_percpu_init, NULL, 0); return 0; } @@ -259,4 +313,5 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op); EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op); EXPORT_SYMBOL_GPL(privcmd_call); diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S index 71f723984cbd..199cb2da7663 100644 --- a/arch/arm/xen/hypercall.S +++ b/arch/arm/xen/hypercall.S @@ -87,6 +87,7 @@ HYPERCALL2(event_channel_op); HYPERCALL2(hvm_op); HYPERCALL2(memory_op); HYPERCALL2(physdev_op); +HYPERCALL3(vcpu_op); ENTRY(privcmd_call) stmdb sp!, {r4} diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 73b6e764034c..56b3f6d447ae 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -6,6 +6,7 @@ config ARM64 select ARCH_WANT_FRAME_POINTERS select ARM_AMBA select ARM_ARCH_TIMER + select ARM_GIC select CLONE_BACKWARDS select COMMON_CLK select GENERIC_CLOCKEVENTS @@ -31,6 +32,8 @@ config ARM64 select OF select OF_EARLY_FLATTREE select PERF_USE_VMALLOC + select POWER_RESET + select POWER_SUPPLY select RTC_LIB select SPARSE_IRQ select SYSCTL_EXCEPTION_TRACE @@ -92,9 +95,6 @@ config SWIOTLB config IOMMU_HELPER def_bool SWIOTLB -config GENERIC_GPIO - bool - source "init/Kconfig" source "kernel/Kconfig.freezer" @@ -105,6 +105,7 @@ config ARCH_VEXPRESS bool "ARMv8 software model (Versatile Express)" select ARCH_REQUIRE_GPIOLIB select COMMON_CLK_VERSATILE + select POWER_RESET_VEXPRESS select VEXPRESS_CONFIG help This enables support for the ARMv8 software model (Versatile @@ -121,8 +122,6 @@ endmenu menu "Kernel Features" -source "kernel/time/Kconfig" - config ARM64_64K_PAGES bool "Enable 64KB pages support" help diff --git a/arch/arm64/boot/dts/foundation-v8.dts b/arch/arm64/boot/dts/foundation-v8.dts index 198682b6de31..84fcc5018284 100644 --- a/arch/arm64/boot/dts/foundation-v8.dts +++ b/arch/arm64/boot/dts/foundation-v8.dts @@ -23,7 +23,7 @@ }; cpus { - #address-cells = <1>; + #address-cells = <2>; #size-cells = <0>; cpu@0 { diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 91e2a6a6fcd4..bf6ab242f047 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -130,4 +130,9 @@ static inline u64 arch_counter_get_cntvct(void) return cval; } +static inline int arch_timer_arch_init(void) +{ + return 0; +} + #endif diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index c8eedc604984..5aceb83b3f5c 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -82,7 +82,7 @@ .macro enable_dbg_if_not_stepping, tmp mrs \tmp, mdscr_el1 - tbnz \tmp, #1, 9990f + tbnz \tmp, #0, 9990f enable_dbg 9990: .endm diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 95e407255347..a6e1750369ef 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -41,7 +41,7 @@ extern void show_pte(struct mm_struct *mm, unsigned long addr); extern void __show_regs(struct pt_regs *); void soft_restart(unsigned long); -extern void (*pm_restart)(const char *cmd); +extern void (*arm_pm_restart)(char str, const char *cmd); #define UDBG_UNDEFINED (1 << 0) #define UDBG_SYSCALL (1 << 1) diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 12f22492df4c..58125bf008d3 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -389,7 +389,7 @@ __SYSCALL(364, sys_perf_event_open) __SYSCALL(365, compat_sys_recvmmsg) __SYSCALL(366, sys_accept4) __SYSCALL(367, sys_fanotify_init) -__SYSCALL(368, compat_sys_fanotify_mark_wrapper) +__SYSCALL(368, compat_sys_fanotify_mark) __SYSCALL(369, sys_prlimit64) __SYSCALL(370, sys_name_to_handle_at) __SYSCALL(371, compat_sys_open_by_handle_at) diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 0c3ba9f51376..f4726dc054b3 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -136,8 +136,6 @@ void disable_debug_monitors(enum debug_el el) */ static void clear_os_lock(void *unused) { - asm volatile("msr mdscr_el1, %0" : : "r" (0)); - isb(); asm volatile("msr oslar_el1, %0" : : "r" (0)); isb(); } diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c index ac974f48a7a2..fbb6e1843659 100644 --- a/arch/arm64/kernel/early_printk.c +++ b/arch/arm64/kernel/early_printk.c @@ -95,7 +95,7 @@ static void early_write(struct console *con, const char *s, unsigned n) } } -static struct console early_console = { +static struct console early_console_dev = { .name = "earlycon", .write = early_write, .flags = CON_PRINTBUFFER | CON_BOOT, @@ -145,7 +145,8 @@ static int __init setup_early_printk(char *buf) early_base = early_io_map(paddr, EARLYCON_IOBASE); printch = match->printch; - register_console(&early_console); + early_console = &early_console_dev; + register_console(&early_console_dev); return 0; } diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index f4919721f7dd..46f02c3b5015 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -81,8 +81,8 @@ void soft_restart(unsigned long addr) void (*pm_power_off)(void); EXPORT_SYMBOL_GPL(pm_power_off); -void (*pm_restart)(const char *cmd); -EXPORT_SYMBOL_GPL(pm_restart); +void (*arm_pm_restart)(char str, const char *cmd); +EXPORT_SYMBOL_GPL(arm_pm_restart); void arch_cpu_idle_prepare(void) { @@ -131,8 +131,8 @@ void machine_restart(char *cmd) local_fiq_disable(); /* Now call the architecture specific reboot code. */ - if (pm_restart) - pm_restart(cmd); + if (arm_pm_restart) + arm_pm_restart('h', cmd); /* * Whoops - the architecture was unable to reboot. diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 6a9a53292590..add6ea616843 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -282,12 +282,13 @@ void __init setup_arch(char **cmdline_p) #endif } -static int __init arm64_of_clk_init(void) +static int __init arm64_device_init(void) { of_clk_init(NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); return 0; } -arch_initcall(arm64_of_clk_init); +arch_initcall(arm64_device_init); static DEFINE_PER_CPU(struct cpu, cpu_data); @@ -305,13 +306,6 @@ static int __init topology_init(void) } subsys_initcall(topology_init); -static int __init arm64_device_probe(void) -{ - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - return 0; -} -device_initcall(arm64_device_probe); - static const char *hwcap_str[] = { "fp", "asimd", diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S index db01aa978c41..a1b19ed7467c 100644 --- a/arch/arm64/kernel/sys32.S +++ b/arch/arm64/kernel/sys32.S @@ -104,13 +104,6 @@ compat_sys_fallocate_wrapper: b sys_fallocate ENDPROC(compat_sys_fallocate_wrapper) -compat_sys_fanotify_mark_wrapper: - orr x2, x2, x3, lsl #32 - mov w3, w4 - mov w4, w5 - b sys_fanotify_mark -ENDPROC(compat_sys_fanotify_mark_wrapper) - #undef __SYSCALL #define __SYSCALL(x, y) .quad y // x diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c index b0ef18d14c3b..a551f88ae2c1 100644 --- a/arch/arm64/kernel/time.c +++ b/arch/arm64/kernel/time.c @@ -32,6 +32,7 @@ #include <linux/timer.h> #include <linux/irq.h> #include <linux/delay.h> +#include <linux/clocksource.h> #include <clocksource/arm_arch_timer.h> @@ -77,10 +78,11 @@ void __init time_init(void) { u32 arch_timer_rate; - if (arch_timer_init()) - panic("Unable to initialise architected timer.\n"); + clocksource_of_init(); arch_timer_rate = arch_timer_get_rate(); + if (!arch_timer_rate) + panic("Unable to initialise architected timer.\n"); /* Cache the sched_clock multiplier to save a divide in the hot path. */ sched_clock_mult = NSEC_PER_SEC / arch_timer_rate; diff --git a/arch/arm64/lib/bitops.S b/arch/arm64/lib/bitops.S index 36216d30cb9a..e5db797790d3 100644 --- a/arch/arm64/lib/bitops.S +++ b/arch/arm64/lib/bitops.S @@ -21,13 +21,13 @@ /* * x0: bits 5:0 bit offset - * bits 63:6 word offset + * bits 31:6 word offset * x1: address */ .macro bitop, name, instr ENTRY( \name ) - and x3, x0, #63 // Get bit offset - eor x0, x0, x3 // Clear low bits + and w3, w0, #63 // Get bit offset + eor w0, w0, w3 // Clear low bits mov x2, #1 add x1, x1, x0, lsr #3 // Get word offset lsl x3, x2, x3 // Create mask @@ -41,8 +41,8 @@ ENDPROC(\name ) .macro testop, name, instr ENTRY( \name ) - and x3, x0, #63 // Get bit offset - eor x0, x0, x3 // Clear low bits + and w3, w0, #63 // Get bit offset + eor w0, w0, w3 // Clear low bits mov x2, #1 add x1, x1, x0, lsr #3 // Get word offset lsl x4, x2, x3 // Create mask diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S index abe69b80cf7f..48a386094fa3 100644 --- a/arch/arm64/mm/cache.S +++ b/arch/arm64/mm/cache.S @@ -52,7 +52,7 @@ loop1: add x2, x2, #4 // add 4 (line length offset) mov x4, #0x3ff and x4, x4, x1, lsr #3 // find maximum number on the way size - clz x5, x4 // find bit position of way size increment + clz w5, w4 // find bit position of way size increment mov x7, #0x7fff and x7, x7, x1, lsr #13 // extract max number of the index size loop2: diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 52638171d6fd..98af6e760cce 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -148,6 +148,7 @@ void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) #define VM_FAULT_BADACCESS 0x020000 #define ESR_WRITE (1 << 6) +#define ESR_CM (1 << 8) #define ESR_LNX_EXEC (1 << 24) /* @@ -206,7 +207,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, struct task_struct *tsk; struct mm_struct *mm; int fault, sig, code; - int write = esr & ESR_WRITE; + bool write = (esr & ESR_WRITE) && !(esr & ESR_CM); unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | (write ? FAULT_FLAG_WRITE : 0); diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index f1d8b9bbfdad..a82ae8868077 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -119,8 +119,7 @@ ENTRY(__cpu_setup) mov x0, #3 << 20 msr cpacr_el1, x0 // Enable FP/ASIMD - mov x0, #1 - msr oslar_el1, x0 // Set the debug OS lock + msr mdscr_el1, xzr // Reset mdscr_el1 tlbi vmalle1is // invalidate I + D TLBs /* * Memory region attributes for LPAE: diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 22c40308360b..bdc35589277f 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -26,9 +26,6 @@ config AVR32 There is an AVR32 Linux project with a web page at http://avr32linux.org/. -config GENERIC_GPIO - def_bool y - config STACKTRACE_SUPPORT def_bool y diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 453ebe46b065..a117652b5fea 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -27,7 +27,7 @@ config BLACKFIN select HAVE_OPROFILE select HAVE_PERF_EVENTS select ARCH_HAVE_CUSTOM_GPIO_H - select ARCH_WANT_OPTIONAL_GPIOLIB + select ARCH_REQUIRE_GPIOLIB select HAVE_UID16 select HAVE_UNDERSCORE_SYMBOL_PREFIX select VIRT_TO_BUS @@ -52,9 +52,6 @@ config GENERIC_BUG config ZONE_DMA def_bool y -config GENERIC_GPIO - def_bool y - config FORCE_MAX_ZONEORDER int default "14" diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index 66cf00095b84..1fce08632ad7 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -141,11 +141,11 @@ archclean: INSTALL_PATH ?= /tftpboot boot := arch/$(ARCH)/boot -BOOT_TARGETS = vmImage vmImage.bin vmImage.bz2 vmImage.gz vmImage.lzma vmImage.lzo vmImage.xip +BOOT_TARGETS = uImage uImage.bin uImage.bz2 uImage.gz uImage.lzma uImage.lzo uImage.xip PHONY += $(BOOT_TARGETS) install -KBUILD_IMAGE := $(boot)/vmImage +KBUILD_IMAGE := $(boot)/uImage -all: vmImage +all: uImage $(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile index f7d27d50d02c..3efaa094fb90 100644 --- a/arch/blackfin/boot/Makefile +++ b/arch/blackfin/boot/Makefile @@ -6,7 +6,7 @@ # for more details. # -targets := vmImage vmImage.bin vmImage.bz2 vmImage.gz vmImage.lzma vmImage.lzo vmImage.xip +targets := uImage uImage.bin uImage.bz2 uImage.gz uImage.lzma uImage.lzo uImage.xip extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.xip ifeq ($(CONFIG_RAMKERNEL),y) @@ -39,22 +39,22 @@ quiet_cmd_mk_bin_xip = BIN $@ $(obj)/vmlinux.bin.xip: $(obj)/vmlinux.bin FORCE $(call if_changed,mk_bin_xip) -$(obj)/vmImage.bin: $(obj)/vmlinux.bin +$(obj)/uImage.bin: $(obj)/vmlinux.bin $(call if_changed,uimage,none) -$(obj)/vmImage.bz2: $(obj)/vmlinux.bin.bz2 +$(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2 $(call if_changed,uimage,bzip2) -$(obj)/vmImage.gz: $(obj)/vmlinux.bin.gz +$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz $(call if_changed,uimage,gzip) -$(obj)/vmImage.lzma: $(obj)/vmlinux.bin.lzma +$(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma $(call if_changed,uimage,lzma) -$(obj)/vmImage.lzo: $(obj)/vmlinux.bin.lzo +$(obj)/uImage.lzo: $(obj)/vmlinux.bin.lzo $(call if_changed,uimage,lzo) -$(obj)/vmImage.xip: $(obj)/vmlinux.bin.xip +$(obj)/uImage.xip: $(obj)/vmlinux.bin.xip $(call if_changed,uimage,none) suffix-y := bin @@ -64,7 +64,7 @@ suffix-$(CONFIG_KERNEL_LZMA) := lzma suffix-$(CONFIG_KERNEL_LZO) := lzo suffix-$(CONFIG_ROMKERNEL) := xip -$(obj)/vmImage: $(obj)/vmImage.$(suffix-y) +$(obj)/uImage: $(obj)/uImage.$(suffix-y) @ln -sf $(notdir $<) $@ install: diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h index c8db653c72d2..a107a98e9978 100644 --- a/arch/blackfin/include/asm/atomic.h +++ b/arch/blackfin/include/asm/atomic.h @@ -11,7 +11,9 @@ #ifdef CONFIG_SMP +#include <asm/barrier.h> #include <linux/linkage.h> +#include <linux/types.h> asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr); asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value); diff --git a/arch/blackfin/include/asm/bfin_sdh.h b/arch/blackfin/include/asm/bfin_sdh.h index 6a4cfe2d3367..a99957ea9e9b 100644 --- a/arch/blackfin/include/asm/bfin_sdh.h +++ b/arch/blackfin/include/asm/bfin_sdh.h @@ -24,18 +24,27 @@ struct bfin_sd_host { #define CMD_INT_E (1 << 8) /* Command Interrupt */ #define CMD_PEND_E (1 << 9) /* Command Pending */ #define CMD_E (1 << 10) /* Command Enable */ +#ifdef RSI_BLKSZ +#define CMD_CRC_CHECK_D (1 << 11) /* CRC Check is disabled */ +#define CMD_DATA0_BUSY (1 << 12) /* Check for Busy State on the DATA0 pin */ +#endif /* SDH_PWR_CTL bitmasks */ +#ifndef RSI_BLKSZ #define PWR_ON 0x3 /* Power On */ #define SD_CMD_OD (1 << 6) /* Open Drain Output */ #define ROD_CTL (1 << 7) /* Rod Control */ +#endif /* SDH_CLK_CTL bitmasks */ #define CLKDIV 0xff /* MC_CLK Divisor */ #define CLK_E (1 << 8) /* MC_CLK Bus Clock Enable */ #define PWR_SV_E (1 << 9) /* Power Save Enable */ #define CLKDIV_BYPASS (1 << 10) /* Bypass Divisor */ -#define WIDE_BUS (1 << 11) /* Wide Bus Mode Enable */ +#define BUS_MODE_MASK 0x1800 /* Bus Mode Mask */ +#define STD_BUS_1 0x000 /* Standard Bus 1 bit mode */ +#define WIDE_BUS_4 0x800 /* Wide Bus 4 bit mode */ +#define BYTE_BUS_8 0x1000 /* Byte Bus 8 bit mode */ /* SDH_RESP_CMD bitmasks */ #define RESP_CMD 0x3f /* Response Command */ @@ -45,7 +54,13 @@ struct bfin_sd_host { #define DTX_DIR (1 << 1) /* Data Transfer Direction */ #define DTX_MODE (1 << 2) /* Data Transfer Mode */ #define DTX_DMA_E (1 << 3) /* Data Transfer DMA Enable */ +#ifndef RSI_BLKSZ #define DTX_BLK_LGTH (0xf << 4) /* Data Transfer Block Length */ +#else + +/* Bit masks for SDH_BLK_SIZE */ +#define DTX_BLK_LGTH 0x1fff /* Data Transfer Block Length */ +#endif /* SDH_STATUS bitmasks */ #define CMD_CRC_FAIL (1 << 0) /* CMD CRC Fail */ @@ -114,10 +129,14 @@ struct bfin_sd_host { /* SDH_E_STATUS bitmasks */ #define SDIO_INT_DET (1 << 1) /* SDIO Int Detected */ #define SD_CARD_DET (1 << 4) /* SD Card Detect */ +#define SD_CARD_BUSYMODE (1 << 31) /* Card is in Busy mode */ +#define SD_CARD_SLPMODE (1 << 30) /* Card in Sleep Mode */ +#define SD_CARD_READY (1 << 17) /* Card Ready */ /* SDH_E_MASK bitmasks */ #define SDIO_MSK (1 << 1) /* Mask SDIO Int Detected */ -#define SCD_MSK (1 << 6) /* Mask Card Detect */ +#define SCD_MSK (1 << 4) /* Mask Card Detect */ +#define CARD_READY_MSK (1 << 16) /* Mask Card Ready */ /* SDH_CFG bitmasks */ #define CLKS_EN (1 << 0) /* Clocks Enable */ @@ -126,7 +145,15 @@ struct bfin_sd_host { #define SD_RST (1 << 4) /* SDMMC Reset */ #define PUP_SDDAT (1 << 5) /* Pull-up SD_DAT */ #define PUP_SDDAT3 (1 << 6) /* Pull-up SD_DAT3 */ +#ifndef RSI_BLKSZ #define PD_SDDAT3 (1 << 7) /* Pull-down SD_DAT3 */ +#else +#define PWR_ON 0x600 /* Power On */ +#define SD_CMD_OD (1 << 11) /* Open Drain Output */ +#define BOOT_EN (1 << 12) /* Boot Enable */ +#define BOOT_MODE (1 << 13) /* Alternate Boot Mode */ +#define BOOT_ACK_EN (1 << 14) /* Boot ACK is expected */ +#endif /* SDH_RD_WAIT_EN bitmasks */ #define RWR (1 << 0) /* Read Wait Request */ diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h index 8a0fed16058f..0ca40dd44724 100644 --- a/arch/blackfin/include/asm/bitops.h +++ b/arch/blackfin/include/asm/bitops.h @@ -41,6 +41,7 @@ #include <asm-generic/bitops/non-atomic.h> #else +#include <asm/barrier.h> #include <asm/byteorder.h> /* swab32 */ #include <linux/linkage.h> diff --git a/arch/blackfin/include/asm/def_LPBlackfin.h b/arch/blackfin/include/asm/def_LPBlackfin.h index fe0ca03a1cb2..ca67145c6a45 100644 --- a/arch/blackfin/include/asm/def_LPBlackfin.h +++ b/arch/blackfin/include/asm/def_LPBlackfin.h @@ -622,10 +622,12 @@ do { \ #define PAGE_SIZE_4KB 0x00010000 /* 4 KB page size */ #define PAGE_SIZE_1MB 0x00020000 /* 1 MB page size */ #define PAGE_SIZE_4MB 0x00030000 /* 4 MB page size */ +#ifdef CONFIG_BF60x #define PAGE_SIZE_16KB 0x00040000 /* 16 KB page size */ #define PAGE_SIZE_64KB 0x00050000 /* 64 KB page size */ #define PAGE_SIZE_16MB 0x00060000 /* 16 MB page size */ #define PAGE_SIZE_64MB 0x00070000 /* 64 MB page size */ +#endif #define CPLB_L1SRAM 0x00000020 /* 0=SRAM mapped in L1, 0=SRAM not * mapped to L1 */ diff --git a/arch/blackfin/include/asm/mem_init.h b/arch/blackfin/include/asm/mem_init.h index 9b33e7247864..c865b33eeb68 100644 --- a/arch/blackfin/include/asm/mem_init.h +++ b/arch/blackfin/include/asm/mem_init.h @@ -335,6 +335,7 @@ struct ddr_config { u32 ddr_clk; u32 dmc_ddrctl; + u32 dmc_effctl; u32 dmc_ddrcfg; u32 dmc_ddrtr0; u32 dmc_ddrtr1; @@ -348,6 +349,7 @@ static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) [0] = { .ddr_clk = 125, .dmc_ddrctl = 0x00000904, + .dmc_effctl = 0x004400C0, .dmc_ddrcfg = 0x00000422, .dmc_ddrtr0 = 0x20705212, .dmc_ddrtr1 = 0x201003CF, @@ -358,6 +360,7 @@ static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) [1] = { .ddr_clk = 133, .dmc_ddrctl = 0x00000904, + .dmc_effctl = 0x004400C0, .dmc_ddrcfg = 0x00000422, .dmc_ddrtr0 = 0x20806313, .dmc_ddrtr1 = 0x2013040D, @@ -368,6 +371,7 @@ static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) [2] = { .ddr_clk = 150, .dmc_ddrctl = 0x00000904, + .dmc_effctl = 0x004400C0, .dmc_ddrcfg = 0x00000422, .dmc_ddrtr0 = 0x20A07323, .dmc_ddrtr1 = 0x20160492, @@ -378,6 +382,7 @@ static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) [3] = { .ddr_clk = 166, .dmc_ddrctl = 0x00000904, + .dmc_effctl = 0x004400C0, .dmc_ddrcfg = 0x00000422, .dmc_ddrtr0 = 0x20A07323, .dmc_ddrtr1 = 0x2016050E, @@ -388,6 +393,7 @@ static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) [4] = { .ddr_clk = 200, .dmc_ddrctl = 0x00000904, + .dmc_effctl = 0x004400C0, .dmc_ddrcfg = 0x00000422, .dmc_ddrtr0 = 0x20a07323, .dmc_ddrtr1 = 0x2016050f, @@ -398,6 +404,7 @@ static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) [5] = { .ddr_clk = 225, .dmc_ddrctl = 0x00000904, + .dmc_effctl = 0x004400C0, .dmc_ddrcfg = 0x00000422, .dmc_ddrtr0 = 0x20E0A424, .dmc_ddrtr1 = 0x302006DB, @@ -408,6 +415,7 @@ static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) [6] = { .ddr_clk = 250, .dmc_ddrctl = 0x00000904, + .dmc_effctl = 0x004400C0, .dmc_ddrcfg = 0x00000422, .dmc_ddrtr0 = 0x20E0A424, .dmc_ddrtr1 = 0x3020079E, @@ -469,6 +477,7 @@ static inline void init_dmc(u32 dmc_clk) bfin_write_DMC0_TR2(ddr_config_table[i].dmc_ddrtr2); bfin_write_DMC0_MR(ddr_config_table[i].dmc_ddrmr); bfin_write_DMC0_EMR1(ddr_config_table[i].dmc_ddrmr1); + bfin_write_DMC0_EFFCTL(ddr_config_table[i].dmc_effctl); bfin_write_DMC0_CTL(ddr_config_table[i].dmc_ddrctl); break; } diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c index 34e96ce02aa9..b49a53b583d5 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c @@ -30,6 +30,7 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) { int i_d, i_i; unsigned long addr; + unsigned long cplb_pageflags, cplb_pagesize; struct cplb_entry *d_tbl = dcplb_tbl[cpu]; struct cplb_entry *i_tbl = icplb_tbl[cpu]; @@ -49,11 +50,20 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) /* Cover kernel memory with 4M pages. */ addr = 0; - for (; addr < memory_start; addr += 4 * 1024 * 1024) { +#ifdef PAGE_SIZE_16MB + cplb_pageflags = PAGE_SIZE_16MB; + cplb_pagesize = SIZE_16M; +#else + cplb_pageflags = PAGE_SIZE_4MB; + cplb_pagesize = SIZE_4M; +#endif + + + for (; addr < memory_start; addr += cplb_pagesize) { d_tbl[i_d].addr = addr; - d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_4MB; + d_tbl[i_d++].data = SDRAM_DGENERIC | cplb_pageflags; i_tbl[i_i].addr = addr; - i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_4MB; + i_tbl[i_i++].data = SDRAM_IGENERIC | cplb_pageflags; } #ifdef CONFIG_ROMKERNEL diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c index e854f9066cbd..79cc0f6dcdd5 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c @@ -145,7 +145,7 @@ MGR_ATTR static int dcplb_miss(int cpu) unsigned long addr = bfin_read_DCPLB_FAULT_ADDR(); int status = bfin_read_DCPLB_STATUS(); int idx; - unsigned long d_data, base, addr1, eaddr; + unsigned long d_data, base, addr1, eaddr, cplb_pagesize, cplb_pageflags; nr_dcplb_miss[cpu]++; if (unlikely(status & FAULT_USERSUPV)) @@ -167,18 +167,37 @@ MGR_ATTR static int dcplb_miss(int cpu) if (unlikely(d_data == 0)) return CPLB_NO_ADDR_MATCH; - addr1 = addr & ~(SIZE_4M - 1); addr &= ~(SIZE_1M - 1); d_data |= PAGE_SIZE_1MB; - if (addr1 >= base && (addr1 + SIZE_4M) <= eaddr) { + + /* BF60x support large than 4M CPLB page size */ +#ifdef PAGE_SIZE_16MB + cplb_pageflags = PAGE_SIZE_16MB; + cplb_pagesize = SIZE_16M; +#else + cplb_pageflags = PAGE_SIZE_4MB; + cplb_pagesize = SIZE_4M; +#endif + +find_pagesize: + addr1 = addr & ~(cplb_pagesize - 1); + if (addr1 >= base && (addr1 + cplb_pagesize) <= eaddr) { /* * This works because * (PAGE_SIZE_4MB & PAGE_SIZE_1MB) == PAGE_SIZE_1MB. */ - d_data |= PAGE_SIZE_4MB; + d_data |= cplb_pageflags; addr = addr1; + goto found_pagesize; + } else { + if (cplb_pagesize > SIZE_4M) { + cplb_pageflags = PAGE_SIZE_4MB; + cplb_pagesize = SIZE_4M; + goto find_pagesize; + } } +found_pagesize: #ifdef CONFIG_BF60x if ((addr >= ASYNC_BANK0_BASE) && (addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)) diff --git a/arch/blackfin/kernel/cplbinfo.c b/arch/blackfin/kernel/cplbinfo.c index 404045dcc5e4..5b80d59e66e5 100644 --- a/arch/blackfin/kernel/cplbinfo.c +++ b/arch/blackfin/kernel/cplbinfo.c @@ -17,8 +17,13 @@ #include <asm/cplbinit.h> #include <asm/blackfin.h> -static char const page_strtbl[][3] = { "1K", "4K", "1M", "4M" }; -#define page(flags) (((flags) & 0x30000) >> 16) +static char const page_strtbl[][4] = { + "1K", "4K", "1M", "4M", +#ifdef CONFIG_BF60x + "16K", "64K", "16M", "64M", +#endif +}; +#define page(flags) (((flags) & 0x70000) >> 16) #define strpage(flags) page_strtbl[page(flags)] struct cplbinfo_data { diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index fb96e607adcf..107b306b06f1 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -1314,7 +1314,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "(Compiled for Rev %d)", bfin_compiled_revid()); } - seq_printf(m, "\ncpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", + seq_printf(m, "\ncpu MHz\t\t: %lu.%06lu/%lu.%06lu\n", cclk/1000000, cclk%1000000, sclk/1000000, sclk%1000000); seq_printf(m, "bogomips\t: %lu.%02lu\n" diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 95114ed395ac..6a3a14bcd3a1 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -455,6 +455,7 @@ static struct platform_device bfin_async_nand_device = { static void bfin_plat_nand_init(void) { gpio_request(BFIN_NAND_PLAT_READY, "bfin_nand_plat"); + gpio_direction_input(BFIN_NAND_PLAT_READY); } #else static void bfin_plat_nand_init(void) {} diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c index a4fce0370c1d..755f0dc12010 100644 --- a/arch/blackfin/mach-bf538/boards/ezkit.c +++ b/arch/blackfin/mach-bf538/boards/ezkit.c @@ -764,7 +764,6 @@ static struct platform_device i2c_bfin_twi1_device = { .num_resources = ARRAY_SIZE(bfin_twi1_resource), .resource = bfin_twi1_resource, }; -#endif /* CONFIG_BF542 */ #endif /* CONFIG_I2C_BLACKFIN_TWI */ #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) diff --git a/arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h b/arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h index 4954cf3f7e16..102ee4025ac9 100644 --- a/arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h +++ b/arch/blackfin/mach-bf609/include/mach/cdefBF60x_base.h @@ -312,6 +312,8 @@ #define bfin_write_DMC0_EMR1(val) bfin_write32(DMC0_EMR1, val) #define bfin_read_DMC0_CTL() bfin_read32(DMC0_CTL) #define bfin_write_DMC0_CTL(val) bfin_write32(DMC0_CTL, val) +#define bfin_read_DMC0_EFFCTL() bfin_read32(DMC0_EFFCTL) +#define bfin_write_DMC0_EFFCTL(val) bfin_write32(DMC0_EFFCTL, val) #define bfin_read_DMC0_STAT() bfin_read32(DMC0_STAT) #define bfin_write_DMC0_STAT(val) bfin_write32(DMC0_STAT, val) #define bfin_read_DMC0_DLLCTL() bfin_read32(DMC0_DLLCTL) diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 06dd026533e3..8769a9045a54 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -264,7 +264,6 @@ config ETRAX_AXISFLASHMAP select MTD_CFI select MTD_CFI_AMDSTD select MTD_JEDECPROBE if ETRAX_ARCH_V32 - select MTD_CHAR select MTD_BLOCK select MTD_COMPLEX_MAPPINGS help diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index af4a486dadcd..c55971a40c34 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -404,7 +404,6 @@ config ETRAX_AXISFLASHMAP select MTD_CFI select MTD_CFI_AMDSTD select MTD_JEDECPROBE - select MTD_CHAR select MTD_BLOCK select MTD_COMPLEX_MAPPINGS help diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c index b82e08615d1b..cd9f15b92f8f 100644 --- a/arch/cris/kernel/profile.c +++ b/arch/cris/kernel/profile.c @@ -76,7 +76,7 @@ static int __init init_cris_profile(void) entry = proc_create("system_profile", S_IWUSR | S_IRUGO, NULL, &cris_proc_profile_operations); if (entry) { - entry->size = SAMPLE_BUFFER_SIZE; + proc_set_size(entry, SAMPLE_BUFFER_SIZE); } prof_running = 1; diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 04dff5bdcbf7..33a97929d055 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig @@ -30,8 +30,6 @@ config HEXAGON select GENERIC_CLOCKEVENTS_BROADCAST select MODULES_USE_ELF_RELA select GENERIC_CPU_DEVICES - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE ---help--- Qualcomm Hexagon is a processor architecture designed for high performance and low power across a wide variety of applications. @@ -157,9 +155,6 @@ source "mm/Kconfig" source "kernel/Kconfig.hz" -config GENERIC_GPIO - def_bool n - endmenu source "init/Kconfig" diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S index e3086185fc9f..67c6ccc14770 100644 --- a/arch/hexagon/kernel/vm_entry.S +++ b/arch/hexagon/kernel/vm_entry.S @@ -291,12 +291,12 @@ event_dispatch: /* "Nested control path" -- if the previous mode was kernel */ { R0 = memw(R29 + #_PT_ER_VMEST); - R16.L = #LO(do_work_pending); + R26.L = #LO(do_work_pending); } { P0 = tstbit(R0, #HVM_VMEST_UM_SFT); if (!P0.new) jump:nt restore_all; - R16.H = #HI(do_work_pending); + R26.H = #HI(do_work_pending); R0 = #VM_INT_DISABLE; } @@ -304,7 +304,7 @@ event_dispatch: * Check also the return from fork/system call, normally coming back from * user mode * - * R16 needs to have do_work_pending, and R0 should have VM_INT_DISABLE + * R26 needs to have do_work_pending, and R0 should have VM_INT_DISABLE */ check_work_pending: @@ -313,7 +313,7 @@ check_work_pending: { R0 = R29; /* regs should still be at top of stack */ R1 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS); - callr R16; + callr R26; } { @@ -375,11 +375,11 @@ _K_enter_debug: ret_from_fork: { call schedule_tail - R16.H = #HI(do_work_pending); + R26.H = #HI(do_work_pending); } { P0 = cmp.eq(R24, #0); - R16.L = #LO(do_work_pending); + R26.L = #LO(do_work_pending); R0 = #VM_INT_DISABLE; } if P0 jump check_work_pending diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index d393f841ff5a..1a2b7749b047 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -101,9 +101,6 @@ config GENERIC_CALIBRATE_DELAY config HAVE_SETUP_PER_CPU_AREA def_bool y -config GENERIC_GPIO - bool - config DMI bool default y diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 6de813370b8c..821170e5f6ed 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -35,9 +35,6 @@ config ARCH_HAS_ILOG2_U32 config ARCH_HAS_ILOG2_U64 bool -config GENERIC_GPIO - bool - config GENERIC_HWEIGHT bool default y diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index b1cfff832fb5..33013dfcd3e1 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -22,8 +22,7 @@ config M68KCLASSIC config COLDFIRE bool "Coldfire CPU family support" - select GENERIC_GPIO - select ARCH_WANT_OPTIONAL_GPIOLIB + select ARCH_REQUIRE_GPIOLIB select ARCH_HAVE_CUSTOM_GPIO_H select CPU_HAS_NO_BITFIELDS select CPU_HAS_NO_MULDIV64 @@ -224,13 +223,25 @@ config M5307 help Motorola ColdFire 5307 processor support. +config M53xx + bool + config M532x bool "MCF532x" depends on !MMU + select M53xx select HAVE_CACHE_CB help Freescale (Motorola) ColdFire 532x processor support. +config M537x + bool "MCF537x" + depends on !MMU + select M53xx + select HAVE_CACHE_CB + help + Freescale ColdFire 537x processor support. + config M5407 bool "MCF5407" depends on !MMU diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine index 7240584d3439..b9ab0a69561c 100644 --- a/arch/m68k/Kconfig.machine +++ b/arch/m68k/Kconfig.machine @@ -358,6 +358,13 @@ config COBRA5329 help Support for the senTec COBRA5329 board. +config M5373EVB + bool "Freescale M5373EVB board support" + depends on M537x + select FREESCALE + help + Support for the Freescale M5373EVB board. + config M5407C3 bool "Motorola M5407C3 board support" depends on M5407 @@ -539,15 +546,6 @@ config ROMVEC 68000 type variants the vectors are at the base of the boot device on system startup. -config ROMVECSIZE - hex "Size of ROM vector region (in bytes)" - default "0x400" - depends on ROM - help - Define the size of the vector region in ROM. For most 68000 - variants this would be 0x400 bytes in size. Set to 0 if you do - not want a vector region at the start of the ROM. - config ROMSTART hex "Address of the base of system image in ROM" default "0x400" diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile index 2f02acfb8edf..7f7830f2c5bc 100644 --- a/arch/m68k/Makefile +++ b/arch/m68k/Makefile @@ -45,6 +45,7 @@ cpuflags-$(CONFIG_M5441x) := $(call cc-option,-mcpu=54455,-mcfv4e) cpuflags-$(CONFIG_M54xx) := $(call cc-option,-mcpu=5475,-m5200) cpuflags-$(CONFIG_M5407) := $(call cc-option,-mcpu=5407,-m5200) cpuflags-$(CONFIG_M532x) := $(call cc-option,-mcpu=532x,-m5307) +cpuflags-$(CONFIG_M537x) := $(call cc-option,-mcpu=537x,-m5307) cpuflags-$(CONFIG_M5307) := $(call cc-option,-mcpu=5307,-m5200) cpuflags-$(CONFIG_M528x) := $(call cc-option,-mcpu=528x,-m5307) cpuflags-$(CONFIG_M5275) := $(call cc-option,-mcpu=5275,-m5307) diff --git a/arch/m68k/include/asm/commproc.h b/arch/m68k/include/asm/commproc.h index a73998528d26..66a36bd51aa1 100644 --- a/arch/m68k/include/asm/commproc.h +++ b/arch/m68k/include/asm/commproc.h @@ -480,23 +480,6 @@ typedef struct scc_enet { #define SICR_ENET_CLKRT ((uint)0x0000003d) #endif -#ifdef CONFIG_RPXLITE -/* This ENET stuff is for the MPC850 with ethernet on SCC2. Some of - * this may be unique to the RPX-Lite configuration. - * Note TENA is on Port B. - */ -#define PA_ENET_RXD ((ushort)0x0004) -#define PA_ENET_TXD ((ushort)0x0008) -#define PA_ENET_TCLK ((ushort)0x0200) -#define PA_ENET_RCLK ((ushort)0x0800) -#define PB_ENET_TENA ((uint)0x00002000) -#define PC_ENET_CLSN ((ushort)0x0040) -#define PC_ENET_RENA ((ushort)0x0080) - -#define SICR_ENET_MASK ((uint)0x0000ff00) -#define SICR_ENET_CLKRT ((uint)0x00003d00) -#endif - #ifdef CONFIG_BSEIP /* This ENET stuff is for the MPC823 with ethernet on SCC2. * This is unique to the BSE ip-Engine board. diff --git a/arch/m68k/include/asm/dbg.h b/arch/m68k/include/asm/dbg.h deleted file mode 100644 index 27af3270f671..000000000000 --- a/arch/m68k/include/asm/dbg.h +++ /dev/null @@ -1,6 +0,0 @@ -#define DEBUG 1 -#ifdef CONFIG_COLDFIRE -#define BREAK asm volatile ("halt") -#else -#define BREAK *(volatile unsigned char *)0xdeadbee0 = 0 -#endif diff --git a/arch/m68k/include/asm/dma.h b/arch/m68k/include/asm/dma.h index 0ff3fc6a6d9a..429fe26e320c 100644 --- a/arch/m68k/include/asm/dma.h +++ b/arch/m68k/include/asm/dma.h @@ -39,7 +39,7 @@ #define MAX_M68K_DMA_CHANNELS 4 #elif defined(CONFIG_M5272) #define MAX_M68K_DMA_CHANNELS 1 -#elif defined(CONFIG_M532x) +#elif defined(CONFIG_M53xx) #define MAX_M68K_DMA_CHANNELS 0 #else #define MAX_M68K_DMA_CHANNELS 2 diff --git a/arch/m68k/include/asm/m53xxacr.h b/arch/m68k/include/asm/m53xxacr.h index cd952b0a8bd3..3177ce8331d6 100644 --- a/arch/m68k/include/asm/m53xxacr.h +++ b/arch/m68k/include/asm/m53xxacr.h @@ -55,8 +55,8 @@ #define CACHE_SIZE 0x2000 /* 8k of unified cache */ #define ICACHE_SIZE CACHE_SIZE #define DCACHE_SIZE CACHE_SIZE -#elif defined(CONFIG_M532x) -#define CACHE_SIZE 0x4000 /* 32k of unified cache */ +#elif defined(CONFIG_M53xx) +#define CACHE_SIZE 0x4000 /* 16k of unified cache */ #define ICACHE_SIZE CACHE_SIZE #define DCACHE_SIZE CACHE_SIZE #endif diff --git a/arch/m68k/include/asm/m532xsim.h b/arch/m68k/include/asm/m53xxsim.h index 8668e47ced0e..faa1a2133bfd 100644 --- a/arch/m68k/include/asm/m532xsim.h +++ b/arch/m68k/include/asm/m53xxsim.h @@ -1,15 +1,15 @@ /****************************************************************************/ /* - * m532xsim.h -- ColdFire 5329 registers + * m53xxsim.h -- ColdFire 5329 registers */ /****************************************************************************/ -#ifndef m532xsim_h -#define m532xsim_h +#ifndef m53xxsim_h +#define m53xxsim_h /****************************************************************************/ -#define CPU_NAME "COLDFIRE(m532x)" +#define CPU_NAME "COLDFIRE(m53xx)" #define CPU_INSTR_PER_JIFFY 3 #define MCF_BUSCLK (MCF_CLK / 3) @@ -107,7 +107,7 @@ /* * QSPI module. */ -#define MCFQSPI_BASE 0xFC058000 /* Base address of QSPI */ +#define MCFQSPI_BASE 0xFC05C000 /* Base address of QSPI */ #define MCFQSPI_SIZE 0x40 /* Size of QSPI region */ #define MCFQSPI_CS0 84 @@ -1238,4 +1238,4 @@ #define MCFEPORT_EPFR (0xFC094006) /********************************************************************/ -#endif /* m532xsim_h */ +#endif /* m53xxsim_h */ diff --git a/arch/m68k/include/asm/m54xxacr.h b/arch/m68k/include/asm/m54xxacr.h index 192bbfeabf70..6d13cae44af5 100644 --- a/arch/m68k/include/asm/m54xxacr.h +++ b/arch/m68k/include/asm/m54xxacr.h @@ -96,8 +96,13 @@ */ #define ACR0_MODE (ACR_BA(CONFIG_MBAR)+ACR_ADMSK(0x1000000)+ \ ACR_ENABLE+ACR_SUPER+ACR_CM_OFF_PRE+ACR_SP) +#if defined(CONFIG_CACHE_COPYBACK) #define ACR1_MODE (ACR_BA(CONFIG_RAMBASE)+ACR_ADMSK(CONFIG_RAMSIZE)+ \ - ACR_ENABLE+ACR_SUPER+ACR_SP) + ACR_ENABLE+ACR_SUPER+ACR_SP+ACR_CM_CP) +#else +#define ACR1_MODE (ACR_BA(CONFIG_RAMBASE)+ACR_ADMSK(CONFIG_RAMSIZE)+ \ + ACR_ENABLE+ACR_SUPER+ACR_SP+ACR_CM_WT) +#endif #define ACR2_MODE 0 #define ACR3_MODE (ACR_BA(CONFIG_RAMBASE)+ACR_ADMSK(CONFIG_RAMSIZE)+ \ ACR_ENABLE+ACR_SUPER+ACR_SP) diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h index fa1059f50dfc..c41ebf45f1d0 100644 --- a/arch/m68k/include/asm/mcfgpio.h +++ b/arch/m68k/include/asm/mcfgpio.h @@ -104,7 +104,7 @@ static inline void gpio_free(unsigned gpio) #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M532x) || defined(CONFIG_M54xx) || \ + defined(CONFIG_M53xx) || defined(CONFIG_M54xx) || \ defined(CONFIG_M5441x) /* These parts have GPIO organized by 8 bit ports */ @@ -139,7 +139,7 @@ static inline void gpio_free(unsigned gpio) #if defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M532x) || defined(CONFIG_M5441x) + defined(CONFIG_M53xx) || defined(CONFIG_M5441x) /* * These parts have an 'Edge' Port module (external interrupt/GPIO) which uses * read-modify-write to change an output and a GPIO module which has separate @@ -195,7 +195,7 @@ static inline u32 __mcfgpio_ppdr(unsigned gpio) return MCFSIM2_GPIO1READ; #elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M532x) || defined(CONFIG_M5441x) + defined(CONFIG_M53xx) || defined(CONFIG_M5441x) #if !defined(CONFIG_M5441x) if (gpio < 8) return MCFEPORT_EPPDR; @@ -237,7 +237,7 @@ static inline u32 __mcfgpio_podr(unsigned gpio) return MCFSIM2_GPIO1WRITE; #elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M532x) || defined(CONFIG_M5441x) + defined(CONFIG_M53xx) || defined(CONFIG_M5441x) #if !defined(CONFIG_M5441x) if (gpio < 8) return MCFEPORT_EPDR; @@ -279,7 +279,7 @@ static inline u32 __mcfgpio_pddr(unsigned gpio) return MCFSIM2_GPIO1ENABLE; #elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M532x) || defined(CONFIG_M5441x) + defined(CONFIG_M53xx) || defined(CONFIG_M5441x) #if !defined(CONFIG_M5441x) if (gpio < 8) return MCFEPORT_EPDDR; diff --git a/arch/m68k/include/asm/mcfsim.h b/arch/m68k/include/asm/mcfsim.h index a04fd9b2714c..bc867de8a1e9 100644 --- a/arch/m68k/include/asm/mcfsim.h +++ b/arch/m68k/include/asm/mcfsim.h @@ -36,8 +36,8 @@ #elif defined(CONFIG_M5307) #include <asm/m5307sim.h> #include <asm/mcfintc.h> -#elif defined(CONFIG_M532x) -#include <asm/m532xsim.h> +#elif defined(CONFIG_M53xx) +#include <asm/m53xxsim.h> #elif defined(CONFIG_M5407) #include <asm/m5407sim.h> #include <asm/mcfintc.h> diff --git a/arch/m68k/include/asm/mcftimer.h b/arch/m68k/include/asm/mcftimer.h index da2fa43c2e45..089f0f150bbf 100644 --- a/arch/m68k/include/asm/mcftimer.h +++ b/arch/m68k/include/asm/mcftimer.h @@ -19,7 +19,7 @@ #define MCFTIMER_TRR 0x04 /* Timer Reference (r/w) */ #define MCFTIMER_TCR 0x08 /* Timer Capture reg (r/w) */ #define MCFTIMER_TCN 0x0C /* Timer Counter reg (r/w) */ -#if defined(CONFIG_M532x) || defined(CONFIG_M5441x) +#if defined(CONFIG_M53xx) || defined(CONFIG_M5441x) #define MCFTIMER_TER 0x03 /* Timer Event reg (r/w) */ #else #define MCFTIMER_TER 0x11 /* Timer Event reg (r/w) */ diff --git a/arch/m68k/platform/coldfire/Makefile b/arch/m68k/platform/coldfire/Makefile index 02591a109f8c..68f0fac60099 100644 --- a/arch/m68k/platform/coldfire/Makefile +++ b/arch/m68k/platform/coldfire/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_M527x) += m527x.o pit.o intc-2.o reset.o obj-$(CONFIG_M5272) += m5272.o intc-5272.o timers.o obj-$(CONFIG_M528x) += m528x.o pit.o intc-2.o reset.o obj-$(CONFIG_M5307) += m5307.o timers.o intc.o reset.o -obj-$(CONFIG_M532x) += m532x.o timers.o intc-simr.o reset.o +obj-$(CONFIG_M53xx) += m53xx.o timers.o intc-simr.o reset.o obj-$(CONFIG_M5407) += m5407.o timers.o intc.o reset.o obj-$(CONFIG_M54xx) += m54xx.o sltimers.o intc-2.o obj-$(CONFIG_M5441x) += m5441x.o pit.o intc-simr.o reset.o diff --git a/arch/m68k/platform/coldfire/m532x.c b/arch/m68k/platform/coldfire/m53xx.c index 7951d1d43357..5286f98fbed0 100644 --- a/arch/m68k/platform/coldfire/m532x.c +++ b/arch/m68k/platform/coldfire/m53xx.c @@ -1,7 +1,7 @@ /***************************************************************************/ /* - * linux/arch/m68knommu/platform/532x/config.c + * m53xx.c -- platform support for ColdFire 53xx based boards * * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) * Copyright (C) 2000, Lineo (www.lineo.com) @@ -118,7 +118,8 @@ static struct clk * const enable_clks[] __initconst = { &__clk_0_24, /* mcfuart.0 */ &__clk_0_25, /* mcfuart.1 */ &__clk_0_26, /* mcfuart.2 */ - + &__clk_0_28, /* mcftmr.0 */ + &__clk_0_29, /* mcftmr.1 */ &__clk_0_32, /* mcfpit.0 */ &__clk_0_33, /* mcfpit.1 */ &__clk_0_37, /* mcfeport.0 */ @@ -134,8 +135,6 @@ static struct clk * const disable_clks[] __initconst = { &__clk_0_17, /* edma */ &__clk_0_22, /* mcfi2c.0 */ &__clk_0_23, /* mcfqspi.0 */ - &__clk_0_28, /* mcftmr.0 */ - &__clk_0_29, /* mcftmr.1 */ &__clk_0_30, /* mcftmr.2 */ &__clk_0_31, /* mcftmr.3 */ &__clk_0_34, /* mcfpit.2 */ @@ -153,7 +152,7 @@ static struct clk * const disable_clks[] __initconst = { }; -static void __init m532x_clk_init(void) +static void __init m53xx_clk_init(void) { unsigned i; @@ -169,7 +168,7 @@ static void __init m532x_clk_init(void) #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) -static void __init m532x_qspi_init(void) +static void __init m53xx_qspi_init(void) { /* setup QSPS pins for QSPI with gpio CS control */ writew(0x01f0, MCFGPIO_PAR_QSPI); @@ -179,7 +178,7 @@ static void __init m532x_qspi_init(void) /***************************************************************************/ -static void __init m532x_uarts_init(void) +static void __init m53xx_uarts_init(void) { /* UART GPIO initialization */ writew(readw(MCFGPIO_PAR_UART) | 0x0FFF, MCFGPIO_PAR_UART); @@ -187,7 +186,7 @@ static void __init m532x_uarts_init(void) /***************************************************************************/ -static void __init m532x_fec_init(void) +static void __init m53xx_fec_init(void) { u8 v; @@ -217,11 +216,11 @@ void __init config_BSP(char *commandp, int size) } #endif mach_sched_init = hw_timer_init; - m532x_clk_init(); - m532x_uarts_init(); - m532x_fec_init(); + m53xx_clk_init(); + m53xx_uarts_init(); + m53xx_fec_init(); #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) - m532x_qspi_init(); + m53xx_qspi_init(); #endif #ifdef CONFIG_BDM_DISABLE diff --git a/arch/m68k/platform/coldfire/timers.c b/arch/m68k/platform/coldfire/timers.c index 51f6d2af807f..d06068e45764 100644 --- a/arch/m68k/platform/coldfire/timers.c +++ b/arch/m68k/platform/coldfire/timers.c @@ -36,7 +36,7 @@ */ void coldfire_profile_init(void); -#if defined(CONFIG_M532x) || defined(CONFIG_M5441x) +#if defined(CONFIG_M53xx) || defined(CONFIG_M5441x) #define __raw_readtrr __raw_readl #define __raw_writetrr __raw_writel #else diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig index 6f16c1469327..dcd94406030e 100644 --- a/arch/metag/Kconfig +++ b/arch/metag/Kconfig @@ -52,9 +52,6 @@ config GENERIC_HWEIGHT config GENERIC_CALIBRATE_DELAY def_bool y -config GENERIC_GPIO - def_bool n - config NO_IOPORT def_bool y diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 54237af0b07c..d22a4ecffff4 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -54,9 +54,6 @@ config GENERIC_HWEIGHT config GENERIC_CALIBRATE_DELAY def_bool y -config GENERIC_GPIO - bool - config GENERIC_CSUM def_bool y diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig index d2b097a652d9..3649a8b150c0 100644 --- a/arch/microblaze/configs/mmu_defconfig +++ b/arch/microblaze/configs/mmu_defconfig @@ -17,7 +17,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set CONFIG_PARTITION_ADVANCED=y # CONFIG_EFI_PARTITION is not set -CONFIG_OPT_LIB_ASM=y CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h index 41cc841091b0..d52abb6812fa 100644 --- a/arch/microblaze/include/asm/pci.h +++ b/arch/microblaze/include/asm/pci.h @@ -153,7 +153,5 @@ extern void __init xilinx_pci_init(void); static inline void __init xilinx_pci_init(void) { return; } #endif -#include <asm-generic/pci-dma-compat.h> - #endif /* __KERNEL__ */ #endif /* __ASM_MICROBLAZE_PCI_H */ diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index a1ab5f0009ef..efe59d881789 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -90,17 +90,25 @@ static inline int ___range_ok(unsigned long addr, unsigned long size) #else -/* - * Address is valid if: - * - "addr", "addr + size" and "size" are all below the limit - */ -#define access_ok(type, addr, size) \ - (get_fs().seg >= (((unsigned long)(addr)) | \ - (size) | ((unsigned long)(addr) + (size)))) - -/* || printk("access_ok failed for %s at 0x%08lx (size %d), seg 0x%08x\n", - type?"WRITE":"READ",addr,size,get_fs().seg)) */ - +static inline int access_ok(int type, const void __user *addr, + unsigned long size) +{ + if (!size) + goto ok; + + if ((get_fs().seg < ((unsigned long)addr)) || + (get_fs().seg < ((unsigned long)addr + size - 1))) { + pr_debug("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n", + type ? "WRITE" : "READ ", (u32)addr, (u32)size, + (u32)get_fs().seg); + return 0; + } +ok: + pr_debug("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n", + type ? "WRITE" : "READ ", (u32)addr, (u32)size, + (u32)get_fs().seg); + return 1; +} #endif #ifdef CONFIG_MMU diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 0b2299bcb948..410398f6db55 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -37,6 +37,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"8.20.a", 0x15}, {"8.20.b", 0x16}, {"8.30.a", 0x17}, + {"8.40.a", 0x18}, + {"8.40.b", 0x19}, {NULL, 0}, }; @@ -57,6 +59,9 @@ const struct family_string_key family_string_lookup[] = { {"virtex6", 0xe}, /* FIXME There is no key code defined for spartan2 */ {"spartan2", 0xf0}, + {"kintex7", 0x10}, + {"artix7", 0x11}, + {"zynq7000", 0x12}, {NULL, 0}, }; diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S index eef84de5e8c8..fcc797feb9db 100644 --- a/arch/microblaze/kernel/head.S +++ b/arch/microblaze/kernel/head.S @@ -112,16 +112,16 @@ no_fdt_arg: * copy command line directly to cmd_line placed in data section. */ beqid r5, skip /* Skip if NULL pointer */ - or r6, r0, r0 /* incremment */ + or r11, r0, r0 /* incremment */ ori r4, r0, cmd_line /* load address of command line */ tophys(r4,r4) /* convert to phys address */ ori r3, r0, COMMAND_LINE_SIZE - 1 /* number of loops */ _copy_command_line: /* r2=r5+r6 - r5 contain pointer to command line */ - lbu r2, r5, r6 + lbu r2, r5, r11 beqid r2, skip /* Skip if no data */ - sb r2, r4, r6 /* addr[r4+r6]= r2*/ - addik r6, r6, 1 /* increment counting */ + sb r2, r4, r11 /* addr[r4+r6]= r2 */ + addik r11, r11, 1 /* increment counting */ bgtid r3, _copy_command_line /* loop for all entries */ addik r3, r3, -1 /* decrement loop */ addik r5, r4, 0 /* add new space for command line */ @@ -131,13 +131,13 @@ skip: #ifdef NOT_COMPILE /* save bram context */ - or r6, r0, r0 /* incremment */ + or r11, r0, r0 /* incremment */ ori r4, r0, TOPHYS(_bram_load_start) /* save bram context */ ori r3, r0, (LMB_SIZE - 4) _copy_bram: - lw r7, r0, r6 /* r7 = r0 + r6 */ - sw r7, r4, r6 /* addr[r4 + r6] = r7*/ - addik r6, r6, 4 /* increment counting */ + lw r7, r0, r11 /* r7 = r0 + r6 */ + sw r7, r4, r11 /* addr[r4 + r6] = r7 */ + addik r11, r11, 4 /* increment counting */ bgtid r3, _copy_bram /* loop for all entries */ addik r3, r3, -4 /* descrement loop */ #endif @@ -303,8 +303,8 @@ jump_over2: * the exception vectors, using a 4k real==virtual mapping. */ /* Use temporary TLB_ID for LMB - clear this temporary mapping later */ - ori r6, r0, MICROBLAZE_LMB_TLB_ID - mts rtlbx,r6 + ori r11, r0, MICROBLAZE_LMB_TLB_ID + mts rtlbx,r11 ori r4,r0,(TLB_WR | TLB_EX) ori r3,r0,(TLB_VALID | TLB_PAGESZ(PAGESZ_4K)) diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 8778adf72bd3..d85fa3a2b0f8 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -172,4 +172,6 @@ void __init init_IRQ(void) * and commits this patch. ~~gcl */ root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, (void *)intr_mask); + + irq_set_default_host(root_domain); } diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index a55893807274..7d1a9c8b1f3d 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -160,3 +160,8 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) return 0; /* MicroBlaze has no separate FPU registers */ } #endif /* CONFIG_MMU */ + +void arch_cpu_idle(void) +{ + local_irq_enable(); +} diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 4ec137d13ad7..b38ae3acfeb4 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -404,10 +404,11 @@ asmlinkage void __init mmu_init(void) #if defined(CONFIG_BLK_DEV_INITRD) /* Remove the init RAM disk from the available memory. */ -/* if (initrd_start) { - mem_pieces_remove(&phys_avail, __pa(initrd_start), - initrd_end - initrd_start, 1); - }*/ + if (initrd_start) { + unsigned long size; + size = initrd_end - initrd_start; + memblock_reserve(virt_to_phys(initrd_start), size); + } #endif /* CONFIG_BLK_DEV_INITRD */ /* Initialize the MMU hardware */ diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 9ea521e4959e..bdb8ea100e73 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -30,7 +30,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_pci.h> -#include <linux/pci.h> #include <linux/export.h> #include <asm/processor.h> diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index 7dd65cfae837..d2cfe45f332b 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild @@ -17,3 +17,7 @@ obj- := $(platform-) obj-y += kernel/ obj-y += mm/ obj-y += math-emu/ + +ifdef CONFIG_KVM +obj-y += kvm/ +endif diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e5f3794744f1..7a58ab933b20 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -61,8 +61,7 @@ config MIPS_ALCHEMY select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_APM_EMULATION - select GENERIC_GPIO - select ARCH_WANT_OPTIONAL_GPIOLIB + select ARCH_REQUIRE_GPIOLIB select SYS_SUPPORTS_ZBOOT select USB_ARCH_HAS_OHCI select USB_ARCH_HAS_EHCI @@ -225,7 +224,6 @@ config MACH_JZ4740 select SYS_SUPPORTS_ZBOOT_UART16550 select DMA_NONCOHERENT select IRQ_CPU - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select SYS_HAS_EARLY_PRINTK select HAVE_PWM @@ -306,7 +304,6 @@ config MIPS_MALTA select HW_HAS_PCI select I8253 select I8259 - select MIPS_BOARDS_GEN select MIPS_BONITO64 select MIPS_CPU_SCACHE select PCI_GT64XXX_PCI0 @@ -337,12 +334,12 @@ config MIPS_SEAD3 select BOOT_RAW select CEVT_R4K select CSRC_R4K + select CSRC_GIC select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI select DMA_NONCOHERENT select IRQ_CPU select IRQ_GIC - select MIPS_BOARDS_GEN select MIPS_CPU_SCACHE select MIPS_MSC select SYS_HAS_CPU_MIPS32_R1 @@ -354,6 +351,7 @@ config MIPS_SEAD3 select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_SMARTMIPS + select SYS_SUPPORTS_MICROMIPS select USB_ARCH_HAS_EHCI select USB_EHCI_BIG_ENDIAN_DESC select USB_EHCI_BIG_ENDIAN_MMIO @@ -912,6 +910,9 @@ config CEVT_GT641XX config CEVT_R4K bool +config CEVT_GIC + bool + config CEVT_SB1250 bool @@ -937,7 +938,6 @@ config CSRC_SB1250 bool config GPIO_TXX9 - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB bool @@ -985,9 +985,6 @@ config MIPS_MSC config MIPS_NILE4 bool -config MIPS_DISABLE_OBSOLETE_IDE - bool - config SYNC_R4K bool @@ -1009,9 +1006,6 @@ config GENERIC_ISA_DMA_SUPPORT_BROKEN config ISA_DMA_API bool -config GENERIC_GPIO - bool - config HOLES_IN_ZONE bool @@ -1081,9 +1075,6 @@ config IRQ_GT641XX config IRQ_GIC bool -config MIPS_BOARDS_GEN - bool - config PCI_GT64XXX_PCI0 bool @@ -1112,7 +1103,6 @@ config SOC_PNX833X select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN - select GENERIC_GPIO select CPU_MIPSR2_IRQ_VI config SOC_PNX8335 @@ -1154,7 +1144,7 @@ config BOOT_ELF32 config MIPS_L1_CACHE_SHIFT int - default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL + default "4" if MACH_DECSTATION || MIKROTIK_RB532 || PMC_MSP4200_EVAL || SOC_RT288X default "6" if MIPS_CPU_SCACHE default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON default "5" @@ -1203,7 +1193,6 @@ config CPU_LOONGSON2F bool "Loongson 2F" depends on SYS_HAS_CPU_LOONGSON2F select CPU_LOONGSON2 - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help The Loongson 2F processor implements the MIPS III instruction set @@ -1244,6 +1233,7 @@ config CPU_MIPS32_R2 select CPU_HAS_PREFETCH select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_HIGHMEM + select HAVE_KVM help Choose this option to build a kernel for release 2 or later of the MIPS32 architecture. Most modern embedded systems with a 32-bit @@ -1744,6 +1734,20 @@ config 64BIT endchoice +config KVM_GUEST + bool "KVM Guest Kernel" + help + Select this option if building a guest kernel for KVM (Trap & Emulate) mode + +config KVM_HOST_FREQ + int "KVM Host Processor Frequency (MHz)" + depends on KVM_GUEST + default 500 + help + Select this option if building a guest kernel for KVM to skip + RTC emulation when determining guest CPU Frequency. Instead, the guest + processor frequency is automatically derived from the host frequency. + choice prompt "Kernel page size" default PAGE_SIZE_4KB @@ -1819,6 +1823,15 @@ config FORCE_MAX_ZONEORDER The page size is not necessarily 4KB. Keep this in mind when choosing a value for this option. +config CEVT_GIC + bool "Use GIC global counter for clock events" + depends on IRQ_GIC && !(MIPS_SEAD3 || MIPS_MT_SMTC) + help + Use the GIC global counter for the clock events. The R4K clock + event driver is always present, so if the platform ends up not + detecting a GIC, it will fall back to the R4K timer for the + generation of clock events. + config BOARD_SCACHE bool @@ -2024,6 +2037,7 @@ config SB1_PASS_2_1_WORKAROUNDS depends on CPU_SB1 && CPU_SB1_PASS_2 default y + config 64BIT_PHYS_ADDR bool @@ -2042,6 +2056,13 @@ config CPU_HAS_SMARTMIPS you don't know you probably don't have SmartMIPS and should say N here. +config CPU_MICROMIPS + depends on SYS_SUPPORTS_MICROMIPS + bool "Build kernel using microMIPS ISA" + help + When this option is enabled the kernel will be built using the + microMIPS ISA + config CPU_HAS_WB bool @@ -2104,6 +2125,9 @@ config SYS_SUPPORTS_HIGHMEM config SYS_SUPPORTS_SMARTMIPS bool +config SYS_SUPPORTS_MICROMIPS + bool + config ARCH_FLATMEM_ENABLE def_bool y depends on !NUMA && !CPU_LOONGSON2 @@ -2564,3 +2588,5 @@ source "security/Kconfig" source "crypto/Kconfig" source "lib/Kconfig" + +source "arch/mips/kvm/Kconfig" diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 6f7978f95090..dd58a04ef4bc 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -114,6 +114,7 @@ cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*e cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le)) cflags-$(CONFIG_CPU_HAS_SMARTMIPS) += $(call cc-option,-msmartmips) +cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips -mno-jals) cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \ -fno-omit-frame-pointer diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig index c8862bdc2ff2..7032ac7ecd1b 100644 --- a/arch/mips/alchemy/Kconfig +++ b/arch/mips/alchemy/Kconfig @@ -31,7 +31,6 @@ config MIPS_DB1000 select ALCHEMY_GPIOINT_AU1000 select DMA_NONCOHERENT select HW_HAS_PCI - select MIPS_DISABLE_OBSOLETE_IDE select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK @@ -41,7 +40,6 @@ config MIPS_DB1235 select ARCH_REQUIRE_GPIOLIB select HW_HAS_PCI select DMA_COHERENT - select MIPS_DISABLE_OBSOLETE_IDE select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK @@ -57,7 +55,6 @@ config MIPS_GPR select ALCHEMY_GPIOINT_AU1000 select HW_HAS_PCI select DMA_NONCOHERENT - select MIPS_DISABLE_OBSOLETE_IDE select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_HAS_EARLY_PRINTK diff --git a/arch/mips/alchemy/Platform b/arch/mips/alchemy/Platform index fa1bdd1aea15..b3afcdd8d77a 100644 --- a/arch/mips/alchemy/Platform +++ b/arch/mips/alchemy/Platform @@ -5,32 +5,14 @@ platform-$(CONFIG_MIPS_ALCHEMY) += alchemy/common/ # -# AMD Alchemy Pb1100 eval board -# -platform-$(CONFIG_MIPS_PB1100) += alchemy/devboards/ -load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1500 eval board -# -platform-$(CONFIG_MIPS_PB1500) += alchemy/devboards/ -load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 - -# -# AMD Alchemy Pb1550 eval board -# -platform-$(CONFIG_MIPS_PB1550) += alchemy/devboards/ -load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 - -# -# AMD Alchemy Db1000/Db1500/Db1100 eval boards +# AMD Alchemy Db1000/Db1500/Pb1500/Db1100/Pb1100 eval boards # platform-$(CONFIG_MIPS_DB1000) += alchemy/devboards/ cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 # -# AMD Alchemy Db1200/Pb1200/Db1550/Db1300 eval boards +# AMD Alchemy Db1200/Pb1200/Db1550/Pb1550/Db1300 eval boards # platform-$(CONFIG_MIPS_DB1235) += alchemy/devboards/ cflags-$(CONFIG_MIPS_DB1235) += -I$(srctree)/arch/mips/include/asm/mach-db1x00 diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c index 28abfeef09d6..92dfa481205b 100644 --- a/arch/mips/ar7/memory.c +++ b/arch/mips/ar7/memory.c @@ -30,7 +30,6 @@ #include <asm/sections.h> #include <asm/mach-ar7/ar7.h> -#include <asm/mips-boards/prom.h> static int __init memsize(void) { diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index d5b3c9057018..a0233a2c1988 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -51,20 +51,6 @@ static void ath79_halt(void) cpu_wait(); } -static void __init ath79_detect_mem_size(void) -{ - unsigned long size; - - for (size = ATH79_MEM_SIZE_MIN; size < ATH79_MEM_SIZE_MAX; - size <<= 1) { - if (!memcmp(ath79_detect_mem_size, - ath79_detect_mem_size + size, 1024)) - break; - } - - add_memory_region(0, size, BOOT_MEM_RAM); -} - static void __init ath79_detect_sys_type(void) { char *chip = "????"; @@ -212,7 +198,7 @@ void __init plat_mem_setup(void) AR71XX_DDR_CTRL_SIZE); ath79_detect_sys_type(); - ath79_detect_mem_size(); + detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX); ath79_clocks_init(); _machine_restart = ath79_restart; diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index d03e8799d1cf..5639662fd503 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -25,6 +25,10 @@ config BCM63XX_CPU_6358 bool "support 6358 CPU" select HW_HAS_PCI +config BCM63XX_CPU_6362 + bool "support 6362 CPU" + select HW_HAS_PCI + config BCM63XX_CPU_6368 bool "support 6368 CPU" select HW_HAS_PCI diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 9aa7d44898ed..a9505c4867e8 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -726,11 +726,11 @@ void __init board_prom_init(void) u32 val; /* read base address of boot chip select (0) - * 6328 does not have MPI but boots from a fixed address + * 6328/6362 do not have MPI but boot from a fixed address */ - if (BCMCPU_IS_6328()) + if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) { val = 0x18000000; - else { + } else { val = bcm_mpi_readl(MPI_CSBASE_REG(0)); val &= MPI_CSBASE_BASE_MASK; } diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index b9e948d59430..c726a97fc798 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -15,7 +15,13 @@ #include <bcm63xx_io.h> #include <bcm63xx_regs.h> #include <bcm63xx_reset.h> -#include <bcm63xx_clk.h> + +struct clk { + void (*set)(struct clk *, int); + unsigned int rate; + unsigned int usage; + int id; +}; static DEFINE_MUTEX(clocks_mutex); @@ -119,11 +125,18 @@ static struct clk clk_ephy = { */ static void enetsw_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6368()) + if (BCMCPU_IS_6328()) + bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable); + else if (BCMCPU_IS_6368()) + bcm_hwclock_set(CKCTL_6368_ROBOSW_EN | + CKCTL_6368_SWPKT_USB_EN | + CKCTL_6368_SWPKT_SAR_EN, + enable); + else return; - bcm_hwclock_set(CKCTL_6368_ROBOSW_EN | - CKCTL_6368_SWPKT_USB_EN | - CKCTL_6368_SWPKT_SAR_EN, enable); + if (enable) { /* reset switch core afer clock change */ bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1); @@ -160,6 +173,8 @@ static void usbh_set(struct clk *clk, int enable) bcm_hwclock_set(CKCTL_6328_USBH_EN, enable); else if (BCMCPU_IS_6348()) bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_USBH_EN, enable); else if (BCMCPU_IS_6368()) bcm_hwclock_set(CKCTL_6368_USBH_EN, enable); } @@ -175,6 +190,8 @@ static void usbd_set(struct clk *clk, int enable) { if (BCMCPU_IS_6328()) bcm_hwclock_set(CKCTL_6328_USBD_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_USBD_EN, enable); else if (BCMCPU_IS_6368()) bcm_hwclock_set(CKCTL_6368_USBD_EN, enable); } @@ -196,6 +213,8 @@ static void spi_set(struct clk *clk, int enable) mask = CKCTL_6348_SPI_EN; else if (BCMCPU_IS_6358()) mask = CKCTL_6358_SPI_EN; + else if (BCMCPU_IS_6362()) + mask = CKCTL_6362_SPI_EN; else /* BCMCPU_IS_6368 */ mask = CKCTL_6368_SPI_EN; @@ -236,7 +255,10 @@ static struct clk clk_xtm = { */ static void ipsec_set(struct clk *clk, int enable) { - bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable); + if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable); + else if (BCMCPU_IS_6368()) + bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable); } static struct clk clk_ipsec = { @@ -249,7 +271,10 @@ static struct clk clk_ipsec = { static void pcie_set(struct clk *clk, int enable) { - bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable); + if (BCMCPU_IS_6328()) + bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable); + else if (BCMCPU_IS_6362()) + bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable); } static struct clk clk_pcie = { @@ -315,9 +340,9 @@ struct clk *clk_get(struct device *dev, const char *id) return &clk_periph; if (BCMCPU_IS_6358() && !strcmp(id, "pcm")) return &clk_pcm; - if (BCMCPU_IS_6368() && !strcmp(id, "ipsec")) + if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec")) return &clk_ipsec; - if (BCMCPU_IS_6328() && !strcmp(id, "pcie")) + if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie")) return &clk_pcie; return ERR_PTR(-ENOENT); } diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index a7afb289b15a..79fe32df5e96 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -25,7 +25,7 @@ const int *bcm63xx_irqs; EXPORT_SYMBOL(bcm63xx_irqs); static u16 bcm63xx_cpu_id; -static u16 bcm63xx_cpu_rev; +static u8 bcm63xx_cpu_rev; static unsigned int bcm63xx_cpu_freq; static unsigned int bcm63xx_memory_size; @@ -71,6 +71,15 @@ static const int bcm6358_irqs[] = { }; +static const unsigned long bcm6362_regs_base[] = { + __GEN_CPU_REGS_TABLE(6362) +}; + +static const int bcm6362_irqs[] = { + __GEN_CPU_IRQ_TABLE(6362) + +}; + static const unsigned long bcm6368_regs_base[] = { __GEN_CPU_REGS_TABLE(6368) }; @@ -87,7 +96,7 @@ u16 __bcm63xx_get_cpu_id(void) EXPORT_SYMBOL(__bcm63xx_get_cpu_id); -u16 bcm63xx_get_cpu_rev(void) +u8 bcm63xx_get_cpu_rev(void) { return bcm63xx_cpu_rev; } @@ -169,6 +178,42 @@ static unsigned int detect_cpu_clock(void) return (16 * 1000000 * n1 * n2) / m1; } + case BCM6362_CPU_ID: + { + unsigned int tmp, mips_pll_fcvo; + + tmp = bcm_misc_readl(MISC_STRAPBUS_6362_REG); + mips_pll_fcvo = (tmp & STRAPBUS_6362_FCVO_MASK) + >> STRAPBUS_6362_FCVO_SHIFT; + switch (mips_pll_fcvo) { + case 0x03: + case 0x0b: + case 0x13: + case 0x1b: + return 240000000; + case 0x04: + case 0x0c: + case 0x14: + case 0x1c: + return 160000000; + case 0x05: + case 0x0e: + case 0x16: + case 0x1e: + case 0x1f: + return 400000000; + case 0x06: + return 440000000; + case 0x07: + case 0x17: + return 384000000; + case 0x15: + case 0x1d: + return 200000000; + default: + return 320000000; + } + } case BCM6368_CPU_ID: { unsigned int tmp, p1, p2, ndiv, m1; @@ -205,7 +250,7 @@ static unsigned int detect_memory_size(void) unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0; u32 val; - if (BCMCPU_IS_6328()) + if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) return bcm_ddr_readl(DDR_CSEND_REG) << 24; if (BCMCPU_IS_6345()) { @@ -240,53 +285,27 @@ static unsigned int detect_memory_size(void) void __init bcm63xx_cpu_init(void) { - unsigned int tmp, expected_cpu_id; + unsigned int tmp; struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int cpu = smp_processor_id(); + u32 chipid_reg; /* soc registers location depends on cpu type */ - expected_cpu_id = 0; + chipid_reg = 0; switch (c->cputype) { case CPU_BMIPS3300: - if ((read_c0_prid() & 0xff00) == PRID_IMP_BMIPS3300_ALT) { - expected_cpu_id = BCM6348_CPU_ID; - bcm63xx_regs_base = bcm6348_regs_base; - bcm63xx_irqs = bcm6348_irqs; - } else { + if ((read_c0_prid() & 0xff00) != PRID_IMP_BMIPS3300_ALT) __cpu_name[cpu] = "Broadcom BCM6338"; - expected_cpu_id = BCM6338_CPU_ID; - bcm63xx_regs_base = bcm6338_regs_base; - bcm63xx_irqs = bcm6338_irqs; - } - break; + /* fall-through */ case CPU_BMIPS32: - expected_cpu_id = BCM6345_CPU_ID; - bcm63xx_regs_base = bcm6345_regs_base; - bcm63xx_irqs = bcm6345_irqs; + chipid_reg = BCM_6345_PERF_BASE; break; case CPU_BMIPS4350: - if ((read_c0_prid() & 0xf0) == 0x10) { - expected_cpu_id = BCM6358_CPU_ID; - bcm63xx_regs_base = bcm6358_regs_base; - bcm63xx_irqs = bcm6358_irqs; - } else { - /* all newer chips have the same chip id location */ - u16 chip_id = bcm_readw(BCM_6368_PERF_BASE); - - switch (chip_id) { - case BCM6328_CPU_ID: - expected_cpu_id = BCM6328_CPU_ID; - bcm63xx_regs_base = bcm6328_regs_base; - bcm63xx_irqs = bcm6328_irqs; - break; - case BCM6368_CPU_ID: - expected_cpu_id = BCM6368_CPU_ID; - bcm63xx_regs_base = bcm6368_regs_base; - bcm63xx_irqs = bcm6368_irqs; - break; - } - } + if ((read_c0_prid() & 0xf0) == 0x10) + chipid_reg = BCM_6345_PERF_BASE; + else + chipid_reg = BCM_6368_PERF_BASE; break; } @@ -294,20 +313,47 @@ void __init bcm63xx_cpu_init(void) * really early to panic, but delaying panic would not help since we * will never get any working console */ - if (!expected_cpu_id) + if (!chipid_reg) panic("unsupported Broadcom CPU"); - /* - * bcm63xx_regs_base is set, we can access soc registers - */ - - /* double check CPU type */ - tmp = bcm_perf_readl(PERF_REV_REG); + /* read out CPU type */ + tmp = bcm_readl(chipid_reg); bcm63xx_cpu_id = (tmp & REV_CHIPID_MASK) >> REV_CHIPID_SHIFT; bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT; - if (bcm63xx_cpu_id != expected_cpu_id) - panic("bcm63xx CPU id mismatch"); + switch (bcm63xx_cpu_id) { + case BCM6328_CPU_ID: + bcm63xx_regs_base = bcm6328_regs_base; + bcm63xx_irqs = bcm6328_irqs; + break; + case BCM6338_CPU_ID: + bcm63xx_regs_base = bcm6338_regs_base; + bcm63xx_irqs = bcm6338_irqs; + break; + case BCM6345_CPU_ID: + bcm63xx_regs_base = bcm6345_regs_base; + bcm63xx_irqs = bcm6345_irqs; + break; + case BCM6348_CPU_ID: + bcm63xx_regs_base = bcm6348_regs_base; + bcm63xx_irqs = bcm6348_irqs; + break; + case BCM6358_CPU_ID: + bcm63xx_regs_base = bcm6358_regs_base; + bcm63xx_irqs = bcm6358_irqs; + break; + case BCM6362_CPU_ID: + bcm63xx_regs_base = bcm6362_regs_base; + bcm63xx_irqs = bcm6362_irqs; + break; + case BCM6368_CPU_ID: + bcm63xx_regs_base = bcm6368_regs_base; + bcm63xx_irqs = bcm6368_irqs; + break; + default: + panic("unsupported broadcom CPU %x", bcm63xx_cpu_id); + break; + } bcm63xx_cpu_freq = detect_cpu_clock(); bcm63xx_memory_size = detect_memory_size(); diff --git a/arch/mips/bcm63xx/dev-flash.c b/arch/mips/bcm63xx/dev-flash.c index 58371c7deac2..588d1ec622e4 100644 --- a/arch/mips/bcm63xx/dev-flash.c +++ b/arch/mips/bcm63xx/dev-flash.c @@ -77,6 +77,12 @@ static int __init bcm63xx_detect_flash_type(void) return BCM63XX_FLASH_TYPE_PARALLEL; else return BCM63XX_FLASH_TYPE_SERIAL; + case BCM6362_CPU_ID: + val = bcm_misc_readl(MISC_STRAPBUS_6362_REG); + if (val & STRAPBUS_6362_BOOT_SEL_SERIAL) + return BCM63XX_FLASH_TYPE_SERIAL; + else + return BCM63XX_FLASH_TYPE_NAND; case BCM6368_CPU_ID: val = bcm_gpio_readl(GPIO_STRAPBUS_REG); switch (val & STRAPBUS_6368_BOOT_SEL_MASK) { diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c index e97fd60e92ef..3065bb61820d 100644 --- a/arch/mips/bcm63xx/dev-spi.c +++ b/arch/mips/bcm63xx/dev-spi.c @@ -22,10 +22,6 @@ /* * register offsets */ -static const unsigned long bcm6338_regs_spi[] = { - __GEN_SPI_REGS_TABLE(6338) -}; - static const unsigned long bcm6348_regs_spi[] = { __GEN_SPI_REGS_TABLE(6348) }; @@ -34,23 +30,15 @@ static const unsigned long bcm6358_regs_spi[] = { __GEN_SPI_REGS_TABLE(6358) }; -static const unsigned long bcm6368_regs_spi[] = { - __GEN_SPI_REGS_TABLE(6368) -}; - const unsigned long *bcm63xx_regs_spi; EXPORT_SYMBOL(bcm63xx_regs_spi); static __init void bcm63xx_spi_regs_init(void) { - if (BCMCPU_IS_6338()) - bcm63xx_regs_spi = bcm6338_regs_spi; - if (BCMCPU_IS_6348()) + if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) bcm63xx_regs_spi = bcm6348_regs_spi; - if (BCMCPU_IS_6358()) + if (BCMCPU_IS_6358() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) bcm63xx_regs_spi = bcm6358_regs_spi; - if (BCMCPU_IS_6368()) - bcm63xx_regs_spi = bcm6368_regs_spi; } #else static __init void bcm63xx_spi_regs_init(void) { } @@ -93,13 +81,13 @@ int __init bcm63xx_spi_register(void) spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { - spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; - spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; - spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT; - spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH; + spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1; + spi_pdata.fifo_size = SPI_6348_MSG_DATA_SIZE; + spi_pdata.msg_type_shift = SPI_6348_MSG_TYPE_SHIFT; + spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH; } - if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { + if (BCMCPU_IS_6358() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) { spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT; diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index da24c2bd9b7c..c0ab3887f42e 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -82,6 +82,17 @@ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358 #define ext_irq_cfg_reg2 0 #endif +#ifdef CONFIG_BCM63XX_CPU_6362 +#define irq_stat_reg PERF_IRQSTAT_6362_REG +#define irq_mask_reg PERF_IRQMASK_6362_REG +#define irq_bits 64 +#define is_ext_irq_cascaded 1 +#define ext_irq_start (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE) +#define ext_irq_end (BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE) +#define ext_irq_count 4 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6362 +#define ext_irq_cfg_reg2 0 +#endif #ifdef CONFIG_BCM63XX_CPU_6368 #define irq_stat_reg PERF_IRQSTAT_6368_REG #define irq_mask_reg PERF_IRQMASK_6368_REG @@ -170,6 +181,16 @@ static void bcm63xx_init_irq(void) ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE; ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358; break; + case BCM6362_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6362_REG; + irq_mask_addr += PERF_IRQMASK_6362_REG; + irq_bits = 64; + ext_irq_count = 4; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362; + break; case BCM6368_CPU_ID: irq_stat_addr += PERF_IRQSTAT_6368_REG; irq_mask_addr += PERF_IRQMASK_6368_REG; @@ -458,6 +479,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d, case BCM6338_CPU_ID: case BCM6345_CPU_ID: case BCM6358_CPU_ID: + case BCM6362_CPU_ID: case BCM6368_CPU_ID: if (levelsense) reg |= EXTIRQ_CFG_LEVELSENSE(irq); diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index 10eaff458071..fd698087fbfd 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -36,6 +36,8 @@ void __init prom_init(void) mask = CKCTL_6348_ALL_SAFE_EN; else if (BCMCPU_IS_6358()) mask = CKCTL_6358_ALL_SAFE_EN; + else if (BCMCPU_IS_6362()) + mask = CKCTL_6362_ALL_SAFE_EN; else if (BCMCPU_IS_6368()) mask = CKCTL_6368_ALL_SAFE_EN; else diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c index 68a31bb90cbf..317931c6cf58 100644 --- a/arch/mips/bcm63xx/reset.c +++ b/arch/mips/bcm63xx/reset.c @@ -85,6 +85,20 @@ #define BCM6358_RESET_PCIE 0 #define BCM6358_RESET_PCIE_EXT 0 +#define BCM6362_RESET_SPI SOFTRESET_6362_SPI_MASK +#define BCM6362_RESET_ENET 0 +#define BCM6362_RESET_USBH SOFTRESET_6362_USBH_MASK +#define BCM6362_RESET_USBD SOFTRESET_6362_USBS_MASK +#define BCM6362_RESET_DSL 0 +#define BCM6362_RESET_SAR SOFTRESET_6362_SAR_MASK +#define BCM6362_RESET_EPHY SOFTRESET_6362_EPHY_MASK +#define BCM6362_RESET_ENETSW SOFTRESET_6362_ENETSW_MASK +#define BCM6362_RESET_PCM SOFTRESET_6362_PCM_MASK +#define BCM6362_RESET_MPI 0 +#define BCM6362_RESET_PCIE (SOFTRESET_6362_PCIE_MASK | \ + SOFTRESET_6362_PCIE_CORE_MASK) +#define BCM6362_RESET_PCIE_EXT SOFTRESET_6362_PCIE_EXT_MASK + #define BCM6368_RESET_SPI SOFTRESET_6368_SPI_MASK #define BCM6368_RESET_ENET 0 #define BCM6368_RESET_USBH SOFTRESET_6368_USBH_MASK @@ -119,6 +133,10 @@ static const u32 bcm6358_reset_bits[] = { __GEN_RESET_BITS_TABLE(6358) }; +static const u32 bcm6362_reset_bits[] = { + __GEN_RESET_BITS_TABLE(6362) +}; + static const u32 bcm6368_reset_bits[] = { __GEN_RESET_BITS_TABLE(6368) }; @@ -140,6 +158,9 @@ static int __init bcm63xx_reset_bits_init(void) } else if (BCMCPU_IS_6358()) { reset_reg = PERF_SOFTRESET_6358_REG; bcm63xx_reset_bits = bcm6358_reset_bits; + } else if (BCMCPU_IS_6362()) { + reset_reg = PERF_SOFTRESET_6362_REG; + bcm63xx_reset_bits = bcm6362_reset_bits; } else if (BCMCPU_IS_6368()) { reset_reg = PERF_SOFTRESET_6368_REG; bcm63xx_reset_bits = bcm6368_reset_bits; @@ -182,6 +203,13 @@ static const u32 bcm63xx_reset_bits[] = { #define reset_reg PERF_SOFTRESET_6358_REG #endif +#ifdef CONFIG_BCM63XX_CPU_6362 +static const u32 bcm63xx_reset_bits[] = { + __GEN_RESET_BITS_TABLE(6362) +}; +#define reset_reg PERF_SOFTRESET_6362_REG +#endif + #ifdef CONFIG_BCM63XX_CPU_6368 static const u32 bcm63xx_reset_bits[] = { __GEN_RESET_BITS_TABLE(6368) diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index 35e18e98beb9..24a24445db64 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -83,6 +83,9 @@ void bcm63xx_machine_reboot(void) case BCM6358_CPU_ID: perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358; break; + case BCM6362_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_6362; + break; } for (i = 0; i < 2; i++) { @@ -126,7 +129,7 @@ static void __bcm63xx_machine_reboot(char *p) const char *get_system_type(void) { static char buf[128]; - snprintf(buf, sizeof(buf), "bcm63xx/%s (0x%04x/0x%04X)", + snprintf(buf, sizeof(buf), "bcm63xx/%s (0x%04x/0x%02X)", board_get_name(), bcm63xx_get_cpu_id(), bcm63xx_get_cpu_rev()); return buf; diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 156aa6143e11..a22f06a6f7ca 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -1032,9 +1032,8 @@ static int octeon_irq_gpio_map_common(struct irq_domain *d, if (!octeon_irq_virq_in_range(virq)) return -EINVAL; - hw += gpiod->base_hwirq; - line = hw >> 6; - bit = hw & 63; + line = (hw + gpiod->base_hwirq) >> 6; + bit = (hw + gpiod->base_hwirq) & 63; if (line > line_limit || octeon_irq_ciu_to_irq[line][bit] != 0) return -EINVAL; diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index cd732e5b4fd5..ce1d3eeeb737 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig @@ -2,30 +2,21 @@ CONFIG_MIPS_MALTA=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y CONFIG_MIPS_MT_SMP=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_HZ_100=y -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=15 -CONFIG_SYSFS_DEPRECATED_V2=y -CONFIG_RELAY=y CONFIG_NAMESPACES=y -CONFIG_UTS_NS=y -CONFIG_IPC_NS=y -CONFIG_PID_NS=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_RELAY=y CONFIG_EXPERT=y -# CONFIG_SYSCTL_SYSCALL is not set # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y -# CONFIG_BLK_DEV_BSG is not set CONFIG_PCI=y -CONFIG_PM=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_XFRM_USER=m @@ -41,8 +32,6 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y CONFIG_IP_PNP_BOOTP=y CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -CONFIG_NET_IPGRE_BROADCAST=y CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -65,7 +54,6 @@ CONFIG_IPV6_MROUTE=y CONFIG_IPV6_PIMSM_V2=y CONFIG_NETWORK_SECMARK=y CONFIG_NETFILTER=y -CONFIG_NETFILTER_NETLINK_QUEUE=m CONFIG_NF_CONNTRACK=m CONFIG_NF_CONNTRACK_SECMARK=y CONFIG_NF_CONNTRACK_EVENTS=y @@ -136,23 +124,15 @@ CONFIG_IP_VS_DH=m CONFIG_IP_VS_SH=m CONFIG_IP_VS_SED=m CONFIG_IP_VS_NQ=m -CONFIG_IP_VS_FTP=m CONFIG_NF_CONNTRACK_IPV4=m CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m CONFIG_IP_NF_MATCH_AH=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_NF_NAT=m -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_MANGLE=m CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_TARGET_ECN=m @@ -162,8 +142,6 @@ CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m CONFIG_NF_CONNTRACK_IPV6=m -CONFIG_IP6_NF_QUEUE=m -CONFIG_IP6_NF_IPTABLES=m CONFIG_IP6_NF_MATCH_AH=m CONFIG_IP6_NF_MATCH_EUI64=m CONFIG_IP6_NF_MATCH_FRAG=m @@ -173,7 +151,6 @@ CONFIG_IP6_NF_MATCH_IPV6HEADER=m CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_MANGLE=m @@ -247,12 +224,10 @@ CONFIG_MAC80211=m CONFIG_MAC80211_RC_PID=y CONFIG_MAC80211_RC_DEFAULT_PID=y CONFIG_MAC80211_MESH=y -CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_CONNECTOR=m CONFIG_MTD=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_OOPS=m @@ -271,7 +246,6 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_CDROM_PKTCDVD=m CONFIG_ATA_OVER_ETH=m -# CONFIG_MISC_DEVICES is not set CONFIG_IDE=y CONFIG_BLK_DEV_IDECD=y CONFIG_IDE_GENERIC=y @@ -317,13 +291,19 @@ CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m CONFIG_NETDEVICES=y -CONFIG_IFB=m -CONFIG_DUMMY=m CONFIG_BONDING=m -CONFIG_MACVLAN=m +CONFIG_DUMMY=m CONFIG_EQUALIZER=m +CONFIG_IFB=m +CONFIG_MACVLAN=m CONFIG_TUN=m CONFIG_VETH=m +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_PCNET32=y +CONFIG_CHELSIO_T3=m +CONFIG_AX88796=m +CONFIG_NETXEN_NIC=m +CONFIG_TC35815=m CONFIG_MARVELL_PHY=m CONFIG_DAVICOM_PHY=m CONFIG_QSEMI_PHY=m @@ -334,14 +314,6 @@ CONFIG_SMSC_PHY=m CONFIG_BROADCOM_PHY=m CONFIG_ICPLUS_PHY=m CONFIG_REALTEK_PHY=m -CONFIG_MDIO_BITBANG=m -CONFIG_NET_ETHERNET=y -CONFIG_AX88796=m -CONFIG_NET_PCI=y -CONFIG_PCNET32=y -CONFIG_TC35815=m -CONFIG_CHELSIO_T3=m -CONFIG_NETXEN_NIC=m CONFIG_ATMEL=m CONFIG_PCI_ATMEL=m CONFIG_PRISM54=m @@ -352,15 +324,7 @@ CONFIG_HOSTAP_PLX=m CONFIG_HOSTAP_PCI=m CONFIG_IPW2100=m CONFIG_IPW2100_MONITOR=y -CONFIG_IPW2200=m -CONFIG_IPW2200_MONITOR=y -CONFIG_IPW2200_PROMISCUOUS=y -CONFIG_IPW2200_QOS=y CONFIG_LIBERTAS=m -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_TMD_HERMES=m -CONFIG_NORTEL_HERMES=m # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_SERIO_I8042 is not set @@ -373,12 +337,6 @@ CONFIG_FB_CIRRUS=y # CONFIG_VGA_CONSOLE is not set CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_HID=m -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_TRIGGER_TIMER=m -CONFIG_LEDS_TRIGGER_IDE_DISK=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=m -CONFIG_LEDS_TRIGGER_BACKLIGHT=m -CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_CMOS=y CONFIG_UIO=m @@ -398,7 +356,6 @@ CONFIG_XFS_QUOTA=y CONFIG_XFS_POSIX_ACL=y CONFIG_QUOTA=y CONFIG_QFMT_V2=y -CONFIG_AUTOFS_FS=y CONFIG_FUSE_FS=m CONFIG_ISO9660_FS=m CONFIG_JOLIET=y @@ -425,7 +382,6 @@ CONFIG_ROMFS_FS=m CONFIG_SYSV_FS=m CONFIG_UFS_FS=m CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y CONFIG_NFSD=y CONFIG_NFSD_V3=y @@ -466,7 +422,6 @@ CONFIG_NLS_ISO8859_14=m CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_LRW=m diff --git a/arch/mips/configs/malta_kvm_defconfig b/arch/mips/configs/malta_kvm_defconfig new file mode 100644 index 000000000000..341bb47204d6 --- /dev/null +++ b/arch/mips/configs/malta_kvm_defconfig @@ -0,0 +1,456 @@ +CONFIG_MIPS_MALTA=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_PAGE_SIZE_16KB=y +CONFIG_MIPS_MT_SMP=y +CONFIG_HZ_100=y +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_NAMESPACES=y +CONFIG_RELAY=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_PCI=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_SCTP=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_PHONET=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_RC_DEFAULT_PID=y +CONFIG_MAC80211_MESH=y +CONFIG_RFKILL=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_CONNECTOR=m +CONFIG_MTD=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_OOPS=m +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_GLUEBI=m +CONFIG_BLK_DEV_FD=m +CONFIG_BLK_DEV_UMEM=m +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_ATA_OVER_ETH=m +CONFIG_IDE=y +CONFIG_BLK_DEV_IDECD=y +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_GENERIC=y +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT8213=m +CONFIG_BLK_DEV_TC86C001=m +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_TGT=m +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_FC_ATTRS=m +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_EQUALIZER=m +CONFIG_IFB=m +CONFIG_MACVLAN=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_PCNET32=y +CONFIG_CHELSIO_T3=m +CONFIG_AX88796=m +CONFIG_NETXEN_NIC=m +CONFIG_TC35815=m +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m +CONFIG_PRISM54=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_LIBERTAS=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO_I8042 is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HWMON is not set +CONFIG_FB=y +CONFIG_FB_CIRRUS=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_HID=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_CMOS=y +CONFIG_UIO=m +CONFIG_UIO_CIF=m +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_CONFIGFS_FS=y +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_RUBIN=y +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC16=m +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=m +CONFIG_KVM_MIPS_DYN_TRANS=y +CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS=y +CONFIG_VHOST_NET=m diff --git a/arch/mips/configs/malta_kvm_guest_defconfig b/arch/mips/configs/malta_kvm_guest_defconfig new file mode 100644 index 000000000000..2b8558b71080 --- /dev/null +++ b/arch/mips/configs/malta_kvm_guest_defconfig @@ -0,0 +1,453 @@ +CONFIG_MIPS_MALTA=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_KVM_GUEST=y +CONFIG_PAGE_SIZE_16KB=y +CONFIG_HZ_100=y +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_NAMESPACES=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_PCI=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_SCTP=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_PHONET=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_CLS_IND=y +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_PID=y +CONFIG_MAC80211_RC_DEFAULT_PID=y +CONFIG_MAC80211_MESH=y +CONFIG_RFKILL=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_CONNECTOR=m +CONFIG_MTD=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_OOPS=m +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_GLUEBI=m +CONFIG_BLK_DEV_FD=m +CONFIG_BLK_DEV_UMEM=m +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_ATA_OVER_ETH=m +CONFIG_VIRTIO_BLK=y +CONFIG_IDE=y +CONFIG_BLK_DEV_IDECD=y +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_GENERIC=y +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT8213=m +CONFIG_BLK_DEV_TC86C001=m +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_TGT=m +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_FC_ATTRS=m +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_EQUALIZER=m +CONFIG_IFB=m +CONFIG_MACVLAN=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_VIRTIO_NET=y +CONFIG_PCNET32=y +CONFIG_CHELSIO_T3=m +CONFIG_AX88796=m +CONFIG_NETXEN_NIC=m +CONFIG_TC35815=m +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m +CONFIG_PRISM54=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_LIBERTAS=m +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO_I8042 is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HWMON is not set +CONFIG_FB=y +CONFIG_FB_CIRRUS=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_HID=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_CMOS=y +CONFIG_UIO=m +CONFIG_UIO_CIF=m +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_RUBIN=y +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC16=m diff --git a/arch/mips/configs/maltaaprp_defconfig b/arch/mips/configs/maltaaprp_defconfig new file mode 100644 index 000000000000..93057a760dfa --- /dev/null +++ b/arch/mips/configs/maltaaprp_defconfig @@ -0,0 +1,195 @@ +CONFIG_MIPS_MALTA=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_MIPS_VPE_LOADER=y +CONFIG_MIPS_VPE_APSP_API=y +CONFIG_HZ_100=y +CONFIG_LOCALVERSION="aprp" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PCI=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_INET_LRO is not set +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_CLS_IND=y +# CONFIG_WIRELESS is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_IDE=y +# CONFIG_IDE_PROC_FS is not set +# CONFIG_IDEPCI_PCIBUS_ORDER is not set +CONFIG_BLK_DEV_GENERIC=y +CONFIG_BLK_DEV_PIIX=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +CONFIG_PCNET32=y +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_HP is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_TOSHIBA is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_WLAN is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_HW_RANDOM=y +# CONFIG_HWMON is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_G=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_CMOS=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ISO8859_1=m +# CONFIG_FTRACE is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/maltasmtc_defconfig b/arch/mips/configs/maltasmtc_defconfig new file mode 100644 index 000000000000..4e54b75d89be --- /dev/null +++ b/arch/mips/configs/maltasmtc_defconfig @@ -0,0 +1,196 @@ +CONFIG_MIPS_MALTA=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_MIPS_MT_SMTC=y +# CONFIG_MIPS_MT_FPAFF is not set +CONFIG_NR_CPUS=9 +CONFIG_HZ_48=y +CONFIG_LOCALVERSION="smtc" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PCI=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_INET_LRO is not set +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_CLS_IND=y +# CONFIG_WIRELESS is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_IDE=y +# CONFIG_IDE_PROC_FS is not set +# CONFIG_IDEPCI_PCIBUS_ORDER is not set +CONFIG_BLK_DEV_GENERIC=y +CONFIG_BLK_DEV_PIIX=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +CONFIG_PCNET32=y +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_HP is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_TOSHIBA is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_WLAN is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_HW_RANDOM=y +# CONFIG_HWMON is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_G=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_CMOS=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ISO8859_1=m +# CONFIG_FTRACE is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig new file mode 100644 index 000000000000..8a666021b870 --- /dev/null +++ b/arch/mips/configs/maltasmvp_defconfig @@ -0,0 +1,199 @@ +CONFIG_MIPS_MALTA=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_MIPS_MT_SMP=y +CONFIG_SCHED_SMT=y +CONFIG_MIPS_CMP=y +CONFIG_NR_CPUS=8 +CONFIG_HZ_100=y +CONFIG_LOCALVERSION="cmp" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PCI=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_INET_LRO is not set +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_CLS_IND=y +# CONFIG_WIRELESS is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_IDE=y +# CONFIG_IDE_PROC_FS is not set +# CONFIG_IDEPCI_PCIBUS_ORDER is not set +CONFIG_BLK_DEV_GENERIC=y +CONFIG_BLK_DEV_PIIX=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +CONFIG_PCNET32=y +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_HP is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_TOSHIBA is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=4 +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_HW_RANDOM=y +# CONFIG_HWMON is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_G=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_CMOS=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ISO8859_1=m +# CONFIG_FTRACE is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/maltaup_defconfig b/arch/mips/configs/maltaup_defconfig new file mode 100644 index 000000000000..9868fc9c1133 --- /dev/null +++ b/arch/mips/configs/maltaup_defconfig @@ -0,0 +1,194 @@ +CONFIG_MIPS_MALTA=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_HZ_100=y +CONFIG_LOCALVERSION="up" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PCI=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_NET_IPIP=m +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_INET_LRO is not set +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=y +CONFIG_NET_CLS_IND=y +# CONFIG_WIRELESS is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_IDE=y +# CONFIG_IDE_PROC_FS is not set +# CONFIG_IDEPCI_PCIBUS_ORDER is not set +CONFIG_BLK_DEV_GENERIC=y +CONFIG_BLK_DEV_PIIX=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_ALTEON is not set +CONFIG_PCNET32=y +# CONFIG_NET_VENDOR_ATHEROS is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_BROCADE is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_HP is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set +# CONFIG_NET_PACKET_ENGINE is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_REALTEK is not set +# CONFIG_NET_VENDOR_RDC is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SUN is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set +# CONFIG_NET_VENDOR_TOSHIBA is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_WLAN is not set +# CONFIG_VT is not set +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_HW_RANDOM=y +# CONFIG_HWMON is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_G=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_CMOS=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ISO8859_1=m +# CONFIG_FTRACE is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/sead3_defconfig b/arch/mips/configs/sead3_defconfig index e3eec68d9132..0abe681c11a0 100644 --- a/arch/mips/configs/sead3_defconfig +++ b/arch/mips/configs/sead3_defconfig @@ -2,7 +2,6 @@ CONFIG_MIPS_SEAD3=y CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_CPU_MIPS32_R2=y CONFIG_HZ_100=y -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_NO_HZ=y @@ -115,10 +114,8 @@ CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_15=y CONFIG_NLS_UTF8=y # CONFIG_FTRACE is not set -CONFIG_CRYPTO=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/configs/sead3micro_defconfig b/arch/mips/configs/sead3micro_defconfig new file mode 100644 index 000000000000..2a0da5bf4b64 --- /dev/null +++ b/arch/mips/configs/sead3micro_defconfig @@ -0,0 +1,122 @@ +CONFIG_MIPS_SEAD3=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MICROMIPS=y +CONFIG_HZ_100=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +CONFIG_PROFILING=y +CONFIG_OPROFILE=y +CONFIG_MODULES=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_MTD=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_GLUEBI=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_MARVELL_PHY=y +CONFIG_DAVICOM_PHY=y +CONFIG_QSEMI_PHY=y +CONFIG_LXT_PHY=y +CONFIG_CICADA_PHY=y +CONFIG_VITESSE_PHY=y +CONFIG_SMSC_PHY=y +CONFIG_BROADCOM_PHY=y +CONFIG_ICPLUS_PHY=y +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +# CONFIG_CONSOLE_TRANSLATIONS is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_LEGACY_PTY_COUNT=32 +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_SPI=y +CONFIG_SENSORS_ADT7475=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_STORAGE=y +CONFIG_MMC=y +CONFIG_MMC_DEBUG=y +CONFIG_MMC_SPI=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_M41T80=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_QUOTA=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_TMPFS=y +CONFIG_JFFS2_FS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_UTF8=y +# CONFIG_FTRACE is not set +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/fw/lib/Makefile b/arch/mips/fw/lib/Makefile index 84befc968fc4..529150516777 100644 --- a/arch/mips/fw/lib/Makefile +++ b/arch/mips/fw/lib/Makefile @@ -2,4 +2,6 @@ # Makefile for generic prom monitor library routines under Linux. # +lib-y += cmdline.o + lib-$(CONFIG_64BIT) += call_o32.o diff --git a/arch/mips/fw/lib/cmdline.c b/arch/mips/fw/lib/cmdline.c new file mode 100644 index 000000000000..ffd0345780ae --- /dev/null +++ b/arch/mips/fw/lib/cmdline.c @@ -0,0 +1,101 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/string.h> + +#include <asm/addrspace.h> +#include <asm/fw/fw.h> + +int fw_argc; +int *_fw_argv; +int *_fw_envp; + +void __init fw_init_cmdline(void) +{ + int i; + + /* Validate command line parameters. */ + if ((fw_arg0 >= CKSEG0) || (fw_arg1 < CKSEG0)) { + fw_argc = 0; + _fw_argv = NULL; + } else { + fw_argc = (fw_arg0 & 0x0000ffff); + _fw_argv = (int *)fw_arg1; + } + + /* Validate environment pointer. */ + if (fw_arg2 < CKSEG0) + _fw_envp = NULL; + else + _fw_envp = (int *)fw_arg2; + + for (i = 1; i < fw_argc; i++) { + strlcat(arcs_cmdline, fw_argv(i), COMMAND_LINE_SIZE); + if (i < (fw_argc - 1)) + strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); + } +} + +char * __init fw_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +char *fw_getenv(char *envname) +{ + char *result = NULL; + + if (_fw_envp != NULL) { + /* + * Return a pointer to the given environment variable. + * YAMON uses "name", "value" pairs, while U-Boot uses + * "name=value". + */ + int i, yamon, index = 0; + + yamon = (strchr(fw_envp(index), '=') == NULL); + i = strlen(envname); + + while (fw_envp(index)) { + if (strncmp(envname, fw_envp(index), i) == 0) { + if (yamon) { + result = fw_envp(index + 1); + break; + } else if (fw_envp(index)[i] == '=') { + result = (fw_envp(index + 1) + i); + break; + } + } + + /* Increment array index. */ + if (yamon) + index += 2; + else + index += 1; + } + } + + return result; +} + +unsigned long fw_getenvl(char *envname) +{ + unsigned long envl = 0UL; + char *str; + long val; + int tmp; + + str = fw_getenv(envname); + if (str) { + tmp = kstrtol(str, 0, &val); + envl = (unsigned long)val; + } + + return envl; +} diff --git a/arch/mips/include/asm/asm.h b/arch/mips/include/asm/asm.h index 164a21e65b42..879691d194af 100644 --- a/arch/mips/include/asm/asm.h +++ b/arch/mips/include/asm/asm.h @@ -296,6 +296,7 @@ symbol = value #define LONG_SUBU subu #define LONG_L lw #define LONG_S sw +#define LONG_SP swp #define LONG_SLL sll #define LONG_SLLV sllv #define LONG_SRL srl @@ -318,6 +319,7 @@ symbol = value #define LONG_SUBU dsubu #define LONG_L ld #define LONG_S sd +#define LONG_SP sdp #define LONG_SLL dsll #define LONG_SLLV dsllv #define LONG_SRL dsrl diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h index b71dd5b16085..4d2cdea5aa37 100644 --- a/arch/mips/include/asm/bootinfo.h +++ b/arch/mips/include/asm/bootinfo.h @@ -104,6 +104,7 @@ struct boot_mem_map { extern struct boot_mem_map boot_mem_map; extern void add_memory_region(phys_t start, phys_t size, long type); +extern void detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max); extern void prom_init(void); extern void prom_free_prom_memory(void); diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h index 888766ae1f85..e28a3e0eb3cb 100644 --- a/arch/mips/include/asm/branch.h +++ b/arch/mips/include/asm/branch.h @@ -11,6 +11,14 @@ #include <asm/ptrace.h> #include <asm/inst.h> +extern int __isa_exception_epc(struct pt_regs *regs); +extern int __compute_return_epc(struct pt_regs *regs); +extern int __compute_return_epc_for_insn(struct pt_regs *regs, + union mips_instruction insn); +extern int __microMIPS_compute_return_epc(struct pt_regs *regs); +extern int __MIPS16e_compute_return_epc(struct pt_regs *regs); + + static inline int delay_slot(struct pt_regs *regs) { return regs->cp0_cause & CAUSEF_BD; @@ -18,20 +26,27 @@ static inline int delay_slot(struct pt_regs *regs) static inline unsigned long exception_epc(struct pt_regs *regs) { - if (!delay_slot(regs)) + if (likely(!delay_slot(regs))) return regs->cp0_epc; + if (get_isa16_mode(regs->cp0_epc)) + return __isa_exception_epc(regs); + return regs->cp0_epc + 4; } #define BRANCH_LIKELY_TAKEN 0x0001 -extern int __compute_return_epc(struct pt_regs *regs); -extern int __compute_return_epc_for_insn(struct pt_regs *regs, - union mips_instruction insn); - static inline int compute_return_epc(struct pt_regs *regs) { + if (get_isa16_mode(regs->cp0_epc)) { + if (cpu_has_mmips) + return __microMIPS_compute_return_epc(regs); + if (cpu_has_mips16) + return __MIPS16e_compute_return_epc(regs); + return regs->cp0_epc; + } + if (!delay_slot(regs)) { regs->cp0_epc += 4; return 0; @@ -40,4 +55,19 @@ static inline int compute_return_epc(struct pt_regs *regs) return __compute_return_epc(regs); } +static inline int MIPS16e_compute_return_epc(struct pt_regs *regs, + union mips16e_instruction *inst) +{ + if (likely(!delay_slot(regs))) { + if (inst->ri.opcode == MIPS16e_extend_op) { + regs->cp0_epc += 4; + return 0; + } + regs->cp0_epc += 2; + return 0; + } + + return __MIPS16e_compute_return_epc(regs); +} + #endif /* _ASM_BRANCH_H */ diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 1a57e8b4d092..e5ec8fcd8afa 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -113,6 +113,9 @@ #ifndef cpu_has_pindexed_dcache #define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX) #endif +#ifndef cpu_has_local_ebase +#define cpu_has_local_ebase 1 +#endif /* * I-Cache snoops remote store. This only matters on SMP. Some multiprocessors diff --git a/arch/mips/include/asm/dma-coherence.h b/arch/mips/include/asm/dma-coherence.h new file mode 100644 index 000000000000..242cbb3ca582 --- /dev/null +++ b/arch/mips/include/asm/dma-coherence.h @@ -0,0 +1,15 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org> + * + */ +#ifndef __ASM_DMA_COHERENCE_H +#define __ASM_DMA_COHERENCE_H + +extern int coherentio; +extern int hw_coherentio; + +#endif diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h index f8fc74b6cb47..84238c574d5e 100644 --- a/arch/mips/include/asm/dma-mapping.h +++ b/arch/mips/include/asm/dma-mapping.h @@ -2,6 +2,7 @@ #define _ASM_DMA_MAPPING_H #include <asm/scatterlist.h> +#include <asm/dma-coherence.h> #include <asm/cache.h> #include <asm-generic/dma-coherent.h> diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h index 3b4092705567..2abb587d5ab4 100644 --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h @@ -54,6 +54,12 @@ do { \ extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc); extern int do_dsemulret(struct pt_regs *xcp); +extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, + struct mips_fpu_struct *ctx, int has_fpu, + void *__user *fault_addr); +int process_fpemu_return(int sig, void __user *fault_addr); +int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, + unsigned long *contpc); /* * Instruction inserted following the badinst to further tag the sequence diff --git a/arch/mips/include/asm/fw/fw.h b/arch/mips/include/asm/fw/fw.h new file mode 100644 index 000000000000..d6c50a7e9ede --- /dev/null +++ b/arch/mips/include/asm/fw/fw.h @@ -0,0 +1,47 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. + */ +#ifndef __ASM_FW_H_ +#define __ASM_FW_H_ + +#include <asm/bootinfo.h> /* For cleaner code... */ + +enum fw_memtypes { + fw_dontuse, + fw_code, + fw_free, +}; + +typedef struct { + unsigned long base; /* Within KSEG0 */ + unsigned int size; /* bytes */ + enum fw_memtypes type; /* fw_memtypes */ +} fw_memblock_t; + +/* Maximum number of memory block descriptors. */ +#define FW_MAX_MEMBLOCKS 32 + +extern int fw_argc; +extern int *_fw_argv; +extern int *_fw_envp; + +/* + * Most firmware like YAMON, PMON, etc. pass arguments and environment + * variables as 32-bit pointers. These take care of sign extension. + */ +#define fw_argv(index) ((char *)(long)_fw_argv[(index)]) +#define fw_envp(index) ((char *)(long)_fw_envp[(index)]) + +extern void fw_init_cmdline(void); +extern char *fw_getcmdline(void); +extern fw_memblock_t *fw_getmdesc(void); +extern void fw_meminit(void); +extern char *fw_getenv(char *name); +extern unsigned long fw_getenvl(char *name); +extern void fw_init_early_console(char port); + +#endif /* __ASM_FW_H_ */ diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index bdc9786ab5a7..7153b32de18e 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -202,7 +202,7 @@ #define GIC_VPE_WD_COUNT0_OFS 0x0094 #define GIC_VPE_WD_INITIAL0_OFS 0x0098 #define GIC_VPE_COMPARE_LO_OFS 0x00a0 -#define GIC_VPE_COMPARE_HI 0x00a4 +#define GIC_VPE_COMPARE_HI_OFS 0x00a4 #define GIC_VPE_EIC_SHADOW_SET_BASE 0x0100 #define GIC_VPE_EIC_SS(intr) \ @@ -359,7 +359,11 @@ struct gic_shared_intr_map { /* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */ #define GIC_PIN_TO_VEC_OFFSET (1) -extern int gic_present; +#include <linux/clocksource.h> +#include <linux/irq.h> + +extern unsigned int gic_present; +extern unsigned int gic_frequency; extern unsigned long _gic_base; extern unsigned int gic_irq_base; extern unsigned int gic_irq_flags[]; @@ -368,18 +372,20 @@ extern struct gic_shared_intr_map gic_shared_intr_map[]; extern void gic_init(unsigned long gic_base_addr, unsigned long gic_addrspace_size, struct gic_intr_map *intrmap, unsigned int intrmap_size, unsigned int irqbase); - extern void gic_clocksource_init(unsigned int); -extern unsigned int gic_get_int(void); +extern unsigned int gic_compare_int (void); +extern cycle_t gic_read_count(void); +extern cycle_t gic_read_compare(void); +extern void gic_write_compare(cycle_t cnt); extern void gic_send_ipi(unsigned int intr); extern unsigned int plat_ipi_call_int_xlate(unsigned int); extern unsigned int plat_ipi_resched_int_xlate(unsigned int); extern void gic_bind_eic_interrupt(int irq, int set); extern unsigned int gic_get_timer_pending(void); +extern unsigned int gic_get_int(void); extern void gic_enable_interrupt(int irq_vec); extern void gic_disable_interrupt(int irq_vec); extern void gic_irq_ack(struct irq_data *d); extern void gic_finish_irq(struct irq_data *d); extern void gic_platform_init(int irqs, struct irq_chip *irq_controller); - #endif /* _ASM_GICREGS_H */ diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h index 44d6a5bde4a1..e3ee92d4dbe7 100644 --- a/arch/mips/include/asm/hazards.h +++ b/arch/mips/include/asm/hazards.h @@ -10,34 +10,13 @@ #ifndef _ASM_HAZARDS_H #define _ASM_HAZARDS_H -#ifdef __ASSEMBLY__ -#define ASMMACRO(name, code...) .macro name; code; .endm -#else - -#include <asm/cpu-features.h> - -#define ASMMACRO(name, code...) \ -__asm__(".macro " #name "; " #code "; .endm"); \ - \ -static inline void name(void) \ -{ \ - __asm__ __volatile__ (#name); \ -} - -/* - * MIPS R2 instruction hazard barrier. Needs to be called as a subroutine. - */ -extern void mips_ihb(void); - -#endif +#include <linux/stringify.h> -ASMMACRO(_ssnop, - sll $0, $0, 1 - ) +#define ___ssnop \ + sll $0, $0, 1 -ASMMACRO(_ehb, - sll $0, $0, 3 - ) +#define ___ehb \ + sll $0, $0, 3 /* * TLB hazards @@ -48,24 +27,24 @@ ASMMACRO(_ehb, * MIPSR2 defines ehb for hazard avoidance */ -ASMMACRO(mtc0_tlbw_hazard, - _ehb - ) -ASMMACRO(tlbw_use_hazard, - _ehb - ) -ASMMACRO(tlb_probe_hazard, - _ehb - ) -ASMMACRO(irq_enable_hazard, - _ehb - ) -ASMMACRO(irq_disable_hazard, - _ehb - ) -ASMMACRO(back_to_back_c0_hazard, - _ehb - ) +#define __mtc0_tlbw_hazard \ + ___ehb + +#define __tlbw_use_hazard \ + ___ehb + +#define __tlb_probe_hazard \ + ___ehb + +#define __irq_enable_hazard \ + ___ehb + +#define __irq_disable_hazard \ + ___ehb + +#define __back_to_back_c0_hazard \ + ___ehb + /* * gcc has a tradition of misscompiling the previous construct using the * address of a label as argument to inline assembler. Gas otoh has the @@ -94,24 +73,42 @@ do { \ * These are slightly complicated by the fact that we guarantee R1 kernels to * run fine on R2 processors. */ -ASMMACRO(mtc0_tlbw_hazard, - _ssnop; _ssnop; _ehb - ) -ASMMACRO(tlbw_use_hazard, - _ssnop; _ssnop; _ssnop; _ehb - ) -ASMMACRO(tlb_probe_hazard, - _ssnop; _ssnop; _ssnop; _ehb - ) -ASMMACRO(irq_enable_hazard, - _ssnop; _ssnop; _ssnop; _ehb - ) -ASMMACRO(irq_disable_hazard, - _ssnop; _ssnop; _ssnop; _ehb - ) -ASMMACRO(back_to_back_c0_hazard, - _ssnop; _ssnop; _ssnop; _ehb - ) + +#define __mtc0_tlbw_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ehb + +#define __tlbw_use_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop; \ + ___ehb + +#define __tlb_probe_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop; \ + ___ehb + +#define __irq_enable_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop; \ + ___ehb + +#define __irq_disable_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop; \ + ___ehb + +#define __back_to_back_c0_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop; \ + ___ehb + /* * gcc has a tradition of misscompiling the previous construct using the * address of a label as argument to inline assembler. Gas otoh has the @@ -147,18 +144,18 @@ do { \ * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. */ -ASMMACRO(mtc0_tlbw_hazard, - ) -ASMMACRO(tlbw_use_hazard, - ) -ASMMACRO(tlb_probe_hazard, - ) -ASMMACRO(irq_enable_hazard, - ) -ASMMACRO(irq_disable_hazard, - ) -ASMMACRO(back_to_back_c0_hazard, - ) +#define __mtc0_tlbw_hazard + +#define __tlbw_use_hazard + +#define __tlb_probe_hazard + +#define __irq_enable_hazard + +#define __irq_disable_hazard + +#define __back_to_back_c0_hazard + #define instruction_hazard() do { } while (0) #elif defined(CONFIG_CPU_SB1) @@ -166,19 +163,21 @@ ASMMACRO(back_to_back_c0_hazard, /* * Mostly like R4000 for historic reasons */ -ASMMACRO(mtc0_tlbw_hazard, - ) -ASMMACRO(tlbw_use_hazard, - ) -ASMMACRO(tlb_probe_hazard, - ) -ASMMACRO(irq_enable_hazard, - ) -ASMMACRO(irq_disable_hazard, - _ssnop; _ssnop; _ssnop - ) -ASMMACRO(back_to_back_c0_hazard, - ) +#define __mtc0_tlbw_hazard + +#define __tlbw_use_hazard + +#define __tlb_probe_hazard + +#define __irq_enable_hazard + +#define __irq_disable_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop + +#define __back_to_back_c0_hazard + #define instruction_hazard() do { } while (0) #else @@ -192,24 +191,35 @@ ASMMACRO(back_to_back_c0_hazard, * hazard so this is nice trick to have an optimal code for a range of * processors. */ -ASMMACRO(mtc0_tlbw_hazard, - nop; nop - ) -ASMMACRO(tlbw_use_hazard, - nop; nop; nop - ) -ASMMACRO(tlb_probe_hazard, - nop; nop; nop - ) -ASMMACRO(irq_enable_hazard, - _ssnop; _ssnop; _ssnop; - ) -ASMMACRO(irq_disable_hazard, - nop; nop; nop - ) -ASMMACRO(back_to_back_c0_hazard, - _ssnop; _ssnop; _ssnop; - ) +#define __mtc0_tlbw_hazard \ + nop; \ + nop + +#define __tlbw_use_hazard \ + nop; \ + nop; \ + nop + +#define __tlb_probe_hazard \ + nop; \ + nop; \ + nop + +#define __irq_enable_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop + +#define __irq_disable_hazard \ + nop; \ + nop; \ + nop + +#define __back_to_back_c0_hazard \ + ___ssnop; \ + ___ssnop; \ + ___ssnop + #define instruction_hazard() do { } while (0) #endif @@ -218,32 +228,137 @@ ASMMACRO(back_to_back_c0_hazard, /* FPU hazards */ #if defined(CONFIG_CPU_SB1) -ASMMACRO(enable_fpu_hazard, - .set push; - .set mips64; - .set noreorder; - _ssnop; - bnezl $0, .+4; - _ssnop; - .set pop -) -ASMMACRO(disable_fpu_hazard, -) + +#define __enable_fpu_hazard \ + .set push; \ + .set mips64; \ + .set noreorder; \ + ___ssnop; \ + bnezl $0, .+4; \ + ___ssnop; \ + .set pop + +#define __disable_fpu_hazard #elif defined(CONFIG_CPU_MIPSR2) -ASMMACRO(enable_fpu_hazard, - _ehb -) -ASMMACRO(disable_fpu_hazard, - _ehb -) + +#define __enable_fpu_hazard \ + ___ehb + +#define __disable_fpu_hazard \ + ___ehb + #else -ASMMACRO(enable_fpu_hazard, - nop; nop; nop; nop -) -ASMMACRO(disable_fpu_hazard, - _ehb -) + +#define __enable_fpu_hazard \ + nop; \ + nop; \ + nop; \ + nop + +#define __disable_fpu_hazard \ + ___ehb + #endif +#ifdef __ASSEMBLY__ + +#define _ssnop ___ssnop +#define _ehb ___ehb +#define mtc0_tlbw_hazard __mtc0_tlbw_hazard +#define tlbw_use_hazard __tlbw_use_hazard +#define tlb_probe_hazard __tlb_probe_hazard +#define irq_enable_hazard __irq_enable_hazard +#define irq_disable_hazard __irq_disable_hazard +#define back_to_back_c0_hazard __back_to_back_c0_hazard +#define enable_fpu_hazard __enable_fpu_hazard +#define disable_fpu_hazard __disable_fpu_hazard + +#else + +#define _ssnop() \ +do { \ + __asm__ __volatile__( \ + __stringify(___ssnop) \ + ); \ +} while (0) + +#define _ehb() \ +do { \ + __asm__ __volatile__( \ + __stringify(___ehb) \ + ); \ +} while (0) + + +#define mtc0_tlbw_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__mtc0_tlbw_hazard) \ + ); \ +} while (0) + + +#define tlbw_use_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__tlbw_use_hazard) \ + ); \ +} while (0) + + +#define tlb_probe_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__tlb_probe_hazard) \ + ); \ +} while (0) + + +#define irq_enable_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__irq_enable_hazard) \ + ); \ +} while (0) + + +#define irq_disable_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__irq_disable_hazard) \ + ); \ +} while (0) + + +#define back_to_back_c0_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__back_to_back_c0_hazard) \ + ); \ +} while (0) + + +#define enable_fpu_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__enable_fpu_hazard) \ + ); \ +} while (0) + + +#define disable_fpu_hazard() \ +do { \ + __asm__ __volatile__( \ + __stringify(__disable_fpu_hazard) \ + ); \ +} while (0) + +/* + * MIPS R2 instruction hazard barrier. Needs to be called as a subroutine. + */ +extern void mips_ihb(void); + +#endif /* __ASSEMBLY__ */ + #endif /* _ASM_HAZARDS_H */ diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h index f1eadf764071..22912f78401c 100644 --- a/arch/mips/include/asm/inst.h +++ b/arch/mips/include/asm/inst.h @@ -73,4 +73,16 @@ typedef unsigned int mips_instruction; +/* microMIPS instruction decode structure. Do NOT export!!! */ +struct mm_decoded_insn { + mips_instruction insn; + mips_instruction next_insn; + int pc_inc; + int next_pc_inc; + int micro_mips_mode; +}; + +/* Recode table from 16-bit register notation to 32-bit GPR. Do NOT export!!! */ +extern const int reg16to32[]; + #endif /* _ASM_INST_H */ diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 1be13727323f..b7e59853fd33 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -118,7 +118,7 @@ static inline void set_io_port_base(unsigned long base) */ static inline unsigned long virt_to_phys(volatile const void *address) { - return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET; + return __pa(address); } /* diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h index 9f3384c789d7..45c00951888b 100644 --- a/arch/mips/include/asm/irqflags.h +++ b/arch/mips/include/asm/irqflags.h @@ -14,53 +14,48 @@ #ifndef __ASSEMBLY__ #include <linux/compiler.h> +#include <linux/stringify.h> #include <asm/hazards.h> #if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) -__asm__( - " .macro arch_local_irq_disable\n" +static inline void arch_local_irq_disable(void) +{ + __asm__ __volatile__( " .set push \n" " .set noat \n" " di \n" - " irq_disable_hazard \n" + " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" - " .endm \n"); - -static inline void arch_local_irq_disable(void) -{ - __asm__ __volatile__( - "arch_local_irq_disable" - : /* no outputs */ - : /* no inputs */ - : "memory"); + : /* no outputs */ + : /* no inputs */ + : "memory"); } +static inline unsigned long arch_local_irq_save(void) +{ + unsigned long flags; -__asm__( - " .macro arch_local_irq_save result \n" + asm __volatile__( " .set push \n" " .set reorder \n" " .set noat \n" - " di \\result \n" - " andi \\result, 1 \n" - " irq_disable_hazard \n" + " di %[flags] \n" + " andi %[flags], 1 \n" + " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" - " .endm \n"); + : [flags] "=r" (flags) + : /* no inputs */ + : "memory"); -static inline unsigned long arch_local_irq_save(void) -{ - unsigned long flags; - asm volatile("arch_local_irq_save\t%0" - : "=r" (flags) - : /* no inputs */ - : "memory"); return flags; } +static inline void arch_local_irq_restore(unsigned long flags) +{ + unsigned long __tmp1; -__asm__( - " .macro arch_local_irq_restore flags \n" + __asm__ __volatile__( " .set push \n" " .set noreorder \n" " .set noat \n" @@ -69,7 +64,7 @@ __asm__( * Slow, but doesn't suffer from a relatively unlikely race * condition we're having since days 1. */ - " beqz \\flags, 1f \n" + " beqz %[flags], 1f \n" " di \n" " ei \n" "1: \n" @@ -78,33 +73,44 @@ __asm__( * Fast, dangerous. Life is fun, life is good. */ " mfc0 $1, $12 \n" - " ins $1, \\flags, 0, 1 \n" + " ins $1, %[flags], 0, 1 \n" " mtc0 $1, $12 \n" #endif - " irq_disable_hazard \n" + " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" - " .endm \n"); - -static inline void arch_local_irq_restore(unsigned long flags) -{ - unsigned long __tmp1; - - __asm__ __volatile__( - "arch_local_irq_restore\t%0" - : "=r" (__tmp1) - : "0" (flags) - : "memory"); + : [flags] "=r" (__tmp1) + : "0" (flags) + : "memory"); } static inline void __arch_local_irq_restore(unsigned long flags) { - unsigned long __tmp1; - __asm__ __volatile__( - "arch_local_irq_restore\t%0" - : "=r" (__tmp1) - : "0" (flags) - : "memory"); + " .set push \n" + " .set noreorder \n" + " .set noat \n" +#if defined(CONFIG_IRQ_CPU) + /* + * Slow, but doesn't suffer from a relatively unlikely race + * condition we're having since days 1. + */ + " beqz %[flags], 1f \n" + " di \n" + " ei \n" + "1: \n" +#else + /* + * Fast, dangerous. Life is fun, life is good. + */ + " mfc0 $1, $12 \n" + " ins $1, %[flags], 0, 1 \n" + " mtc0 $1, $12 \n" +#endif + " " __stringify(__irq_disable_hazard) " \n" + " .set pop \n" + : [flags] "=r" (flags) + : "0" (flags) + : "memory"); } #else /* Functions that require preempt_{dis,en}able() are in mips-atomic.c */ @@ -115,8 +121,18 @@ void __arch_local_irq_restore(unsigned long flags); #endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */ -__asm__( - " .macro arch_local_irq_enable \n" +extern void smtc_ipi_replay(void); + +static inline void arch_local_irq_enable(void) +{ +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC kernel needs to do a software replay of queued + * IPIs, at the cost of call overhead on each local_irq_enable() + */ + smtc_ipi_replay(); +#endif + __asm__ __volatile__( " .set push \n" " .set reorder \n" " .set noat \n" @@ -133,45 +149,28 @@ __asm__( " xori $1,0x1e \n" " mtc0 $1,$12 \n" #endif - " irq_enable_hazard \n" + " " __stringify(__irq_enable_hazard) " \n" " .set pop \n" - " .endm"); - -extern void smtc_ipi_replay(void); - -static inline void arch_local_irq_enable(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC kernel needs to do a software replay of queued - * IPIs, at the cost of call overhead on each local_irq_enable() - */ - smtc_ipi_replay(); -#endif - __asm__ __volatile__( - "arch_local_irq_enable" - : /* no outputs */ - : /* no inputs */ - : "memory"); + : /* no outputs */ + : /* no inputs */ + : "memory"); } +static inline unsigned long arch_local_save_flags(void) +{ + unsigned long flags; -__asm__( - " .macro arch_local_save_flags flags \n" + asm __volatile__( " .set push \n" " .set reorder \n" #ifdef CONFIG_MIPS_MT_SMTC - " mfc0 \\flags, $2, 1 \n" + " mfc0 %[flags], $2, 1 \n" #else - " mfc0 \\flags, $12 \n" + " mfc0 %[flags], $12 \n" #endif " .set pop \n" - " .endm \n"); + : [flags] "=r" (flags)); -static inline unsigned long arch_local_save_flags(void) -{ - unsigned long flags; - asm volatile("arch_local_save_flags %0" : "=r" (flags)); return flags; } diff --git a/arch/mips/include/asm/kvm.h b/arch/mips/include/asm/kvm.h new file mode 100644 index 000000000000..85789eacbf18 --- /dev/null +++ b/arch/mips/include/asm/kvm.h @@ -0,0 +1,55 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#ifndef __LINUX_KVM_MIPS_H +#define __LINUX_KVM_MIPS_H + +#include <linux/types.h> + +#define __KVM_MIPS + +#define N_MIPS_COPROC_REGS 32 +#define N_MIPS_COPROC_SEL 8 + +/* for KVM_GET_REGS and KVM_SET_REGS */ +struct kvm_regs { + __u32 gprs[32]; + __u32 hi; + __u32 lo; + __u32 pc; + + __u32 cp0reg[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL]; +}; + +/* for KVM_GET_SREGS and KVM_SET_SREGS */ +struct kvm_sregs { +}; + +/* for KVM_GET_FPU and KVM_SET_FPU */ +struct kvm_fpu { +}; + +struct kvm_debug_exit_arch { +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { +}; + +struct kvm_mips_interrupt { + /* in */ + __u32 cpu; + __u32 irq; +}; + +/* definition of registers in kvm_run */ +struct kvm_sync_regs { +}; + +#endif /* __LINUX_KVM_MIPS_H */ diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h new file mode 100644 index 000000000000..143875c6c95a --- /dev/null +++ b/arch/mips/include/asm/kvm_host.h @@ -0,0 +1,667 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#ifndef __MIPS_KVM_HOST_H__ +#define __MIPS_KVM_HOST_H__ + +#include <linux/mutex.h> +#include <linux/hrtimer.h> +#include <linux/interrupt.h> +#include <linux/types.h> +#include <linux/kvm.h> +#include <linux/kvm_types.h> +#include <linux/threads.h> +#include <linux/spinlock.h> + + +#define KVM_MAX_VCPUS 1 +#define KVM_USER_MEM_SLOTS 8 +/* memory slots that does not exposed to userspace */ +#define KVM_PRIVATE_MEM_SLOTS 0 + +#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 + +/* Don't support huge pages */ +#define KVM_HPAGE_GFN_SHIFT(x) 0 + +/* We don't currently support large pages. */ +#define KVM_NR_PAGE_SIZES 1 +#define KVM_PAGES_PER_HPAGE(x) 1 + + + +/* Special address that contains the comm page, used for reducing # of traps */ +#define KVM_GUEST_COMMPAGE_ADDR 0x0 + +#define KVM_GUEST_KERNEL_MODE(vcpu) ((kvm_read_c0_guest_status(vcpu->arch.cop0) & (ST0_EXL | ST0_ERL)) || \ + ((kvm_read_c0_guest_status(vcpu->arch.cop0) & KSU_USER) == 0)) + +#define KVM_GUEST_KUSEG 0x00000000UL +#define KVM_GUEST_KSEG0 0x40000000UL +#define KVM_GUEST_KSEG23 0x60000000UL +#define KVM_GUEST_KSEGX(a) ((_ACAST32_(a)) & 0x60000000) +#define KVM_GUEST_CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) + +#define KVM_GUEST_CKSEG0ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0) +#define KVM_GUEST_CKSEG1ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG1) +#define KVM_GUEST_CKSEG23ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG23) + +/* + * Map an address to a certain kernel segment + */ +#define KVM_GUEST_KSEG0ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0) +#define KVM_GUEST_KSEG1ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG1) +#define KVM_GUEST_KSEG23ADDR(a) (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG23) + +#define KVM_INVALID_PAGE 0xdeadbeef +#define KVM_INVALID_INST 0xdeadbeef +#define KVM_INVALID_ADDR 0xdeadbeef + +#define KVM_MALTA_GUEST_RTC_ADDR 0xb8000070UL + +#define GUEST_TICKS_PER_JIFFY (40000000/HZ) +#define MS_TO_NS(x) (x * 1E6L) + +#define CAUSEB_DC 27 +#define CAUSEF_DC (_ULCAST_(1) << 27) + +struct kvm; +struct kvm_run; +struct kvm_vcpu; +struct kvm_interrupt; + +extern atomic_t kvm_mips_instance; +extern pfn_t(*kvm_mips_gfn_to_pfn) (struct kvm *kvm, gfn_t gfn); +extern void (*kvm_mips_release_pfn_clean) (pfn_t pfn); +extern bool(*kvm_mips_is_error_pfn) (pfn_t pfn); + +struct kvm_vm_stat { + u32 remote_tlb_flush; +}; + +struct kvm_vcpu_stat { + u32 wait_exits; + u32 cache_exits; + u32 signal_exits; + u32 int_exits; + u32 cop_unusable_exits; + u32 tlbmod_exits; + u32 tlbmiss_ld_exits; + u32 tlbmiss_st_exits; + u32 addrerr_st_exits; + u32 addrerr_ld_exits; + u32 syscall_exits; + u32 resvd_inst_exits; + u32 break_inst_exits; + u32 flush_dcache_exits; + u32 halt_wakeup; +}; + +enum kvm_mips_exit_types { + WAIT_EXITS, + CACHE_EXITS, + SIGNAL_EXITS, + INT_EXITS, + COP_UNUSABLE_EXITS, + TLBMOD_EXITS, + TLBMISS_LD_EXITS, + TLBMISS_ST_EXITS, + ADDRERR_ST_EXITS, + ADDRERR_LD_EXITS, + SYSCALL_EXITS, + RESVD_INST_EXITS, + BREAK_INST_EXITS, + FLUSH_DCACHE_EXITS, + MAX_KVM_MIPS_EXIT_TYPES +}; + +struct kvm_arch_memory_slot { +}; + +struct kvm_arch { + /* Guest GVA->HPA page table */ + unsigned long *guest_pmap; + unsigned long guest_pmap_npages; + + /* Wired host TLB used for the commpage */ + int commpage_tlb; +}; + +#define N_MIPS_COPROC_REGS 32 +#define N_MIPS_COPROC_SEL 8 + +struct mips_coproc { + unsigned long reg[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL]; +#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS + unsigned long stat[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL]; +#endif +}; + +/* + * Coprocessor 0 register names + */ +#define MIPS_CP0_TLB_INDEX 0 +#define MIPS_CP0_TLB_RANDOM 1 +#define MIPS_CP0_TLB_LOW 2 +#define MIPS_CP0_TLB_LO0 2 +#define MIPS_CP0_TLB_LO1 3 +#define MIPS_CP0_TLB_CONTEXT 4 +#define MIPS_CP0_TLB_PG_MASK 5 +#define MIPS_CP0_TLB_WIRED 6 +#define MIPS_CP0_HWRENA 7 +#define MIPS_CP0_BAD_VADDR 8 +#define MIPS_CP0_COUNT 9 +#define MIPS_CP0_TLB_HI 10 +#define MIPS_CP0_COMPARE 11 +#define MIPS_CP0_STATUS 12 +#define MIPS_CP0_CAUSE 13 +#define MIPS_CP0_EXC_PC 14 +#define MIPS_CP0_PRID 15 +#define MIPS_CP0_CONFIG 16 +#define MIPS_CP0_LLADDR 17 +#define MIPS_CP0_WATCH_LO 18 +#define MIPS_CP0_WATCH_HI 19 +#define MIPS_CP0_TLB_XCONTEXT 20 +#define MIPS_CP0_ECC 26 +#define MIPS_CP0_CACHE_ERR 27 +#define MIPS_CP0_TAG_LO 28 +#define MIPS_CP0_TAG_HI 29 +#define MIPS_CP0_ERROR_PC 30 +#define MIPS_CP0_DEBUG 23 +#define MIPS_CP0_DEPC 24 +#define MIPS_CP0_PERFCNT 25 +#define MIPS_CP0_ERRCTL 26 +#define MIPS_CP0_DATA_LO 28 +#define MIPS_CP0_DATA_HI 29 +#define MIPS_CP0_DESAVE 31 + +#define MIPS_CP0_CONFIG_SEL 0 +#define MIPS_CP0_CONFIG1_SEL 1 +#define MIPS_CP0_CONFIG2_SEL 2 +#define MIPS_CP0_CONFIG3_SEL 3 + +/* Config0 register bits */ +#define CP0C0_M 31 +#define CP0C0_K23 28 +#define CP0C0_KU 25 +#define CP0C0_MDU 20 +#define CP0C0_MM 17 +#define CP0C0_BM 16 +#define CP0C0_BE 15 +#define CP0C0_AT 13 +#define CP0C0_AR 10 +#define CP0C0_MT 7 +#define CP0C0_VI 3 +#define CP0C0_K0 0 + +/* Config1 register bits */ +#define CP0C1_M 31 +#define CP0C1_MMU 25 +#define CP0C1_IS 22 +#define CP0C1_IL 19 +#define CP0C1_IA 16 +#define CP0C1_DS 13 +#define CP0C1_DL 10 +#define CP0C1_DA 7 +#define CP0C1_C2 6 +#define CP0C1_MD 5 +#define CP0C1_PC 4 +#define CP0C1_WR 3 +#define CP0C1_CA 2 +#define CP0C1_EP 1 +#define CP0C1_FP 0 + +/* Config2 Register bits */ +#define CP0C2_M 31 +#define CP0C2_TU 28 +#define CP0C2_TS 24 +#define CP0C2_TL 20 +#define CP0C2_TA 16 +#define CP0C2_SU 12 +#define CP0C2_SS 8 +#define CP0C2_SL 4 +#define CP0C2_SA 0 + +/* Config3 Register bits */ +#define CP0C3_M 31 +#define CP0C3_ISA_ON_EXC 16 +#define CP0C3_ULRI 13 +#define CP0C3_DSPP 10 +#define CP0C3_LPA 7 +#define CP0C3_VEIC 6 +#define CP0C3_VInt 5 +#define CP0C3_SP 4 +#define CP0C3_MT 2 +#define CP0C3_SM 1 +#define CP0C3_TL 0 + +/* Have config1, Cacheable, noncoherent, write-back, write allocate*/ +#define MIPS_CONFIG0 \ + ((1 << CP0C0_M) | (0x3 << CP0C0_K0)) + +/* Have config2, no coprocessor2 attached, no MDMX support attached, + no performance counters, watch registers present, + no code compression, EJTAG present, no FPU, no watch registers */ +#define MIPS_CONFIG1 \ +((1 << CP0C1_M) | \ + (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ + (0 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \ + (0 << CP0C1_FP)) + +/* Have config3, no tertiary/secondary caches implemented */ +#define MIPS_CONFIG2 \ +((1 << CP0C2_M)) + +/* No config4, no DSP ASE, no large physaddr (PABITS), + no external interrupt controller, no vectored interrupts, + no 1kb pages, no SmartMIPS ASE, no trace logic */ +#define MIPS_CONFIG3 \ +((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ + (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ + (0 << CP0C3_SM) | (0 << CP0C3_TL)) + +/* MMU types, the first four entries have the same layout as the + CP0C0_MT field. */ +enum mips_mmu_types { + MMU_TYPE_NONE, + MMU_TYPE_R4000, + MMU_TYPE_RESERVED, + MMU_TYPE_FMT, + MMU_TYPE_R3000, + MMU_TYPE_R6000, + MMU_TYPE_R8000 +}; + +/* + * Trap codes + */ +#define T_INT 0 /* Interrupt pending */ +#define T_TLB_MOD 1 /* TLB modified fault */ +#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */ +#define T_TLB_ST_MISS 3 /* TLB miss on a store */ +#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */ +#define T_ADDR_ERR_ST 5 /* Address error on a store */ +#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */ +#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */ +#define T_SYSCALL 8 /* System call */ +#define T_BREAK 9 /* Breakpoint */ +#define T_RES_INST 10 /* Reserved instruction exception */ +#define T_COP_UNUSABLE 11 /* Coprocessor unusable */ +#define T_OVFLOW 12 /* Arithmetic overflow */ + +/* + * Trap definitions added for r4000 port. + */ +#define T_TRAP 13 /* Trap instruction */ +#define T_VCEI 14 /* Virtual coherency exception */ +#define T_FPE 15 /* Floating point exception */ +#define T_WATCH 23 /* Watch address reference */ +#define T_VCED 31 /* Virtual coherency data */ + +/* Resume Flags */ +#define RESUME_FLAG_DR (1<<0) /* Reload guest nonvolatile state? */ +#define RESUME_FLAG_HOST (1<<1) /* Resume host? */ + +#define RESUME_GUEST 0 +#define RESUME_GUEST_DR RESUME_FLAG_DR +#define RESUME_HOST RESUME_FLAG_HOST + +enum emulation_result { + EMULATE_DONE, /* no further processing */ + EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */ + EMULATE_FAIL, /* can't emulate this instruction */ + EMULATE_WAIT, /* WAIT instruction */ + EMULATE_PRIV_FAIL, +}; + +#define MIPS3_PG_G 0x00000001 /* Global; ignore ASID if in lo0 & lo1 */ +#define MIPS3_PG_V 0x00000002 /* Valid */ +#define MIPS3_PG_NV 0x00000000 +#define MIPS3_PG_D 0x00000004 /* Dirty */ + +#define mips3_paddr_to_tlbpfn(x) \ + (((unsigned long)(x) >> MIPS3_PG_SHIFT) & MIPS3_PG_FRAME) +#define mips3_tlbpfn_to_paddr(x) \ + ((unsigned long)((x) & MIPS3_PG_FRAME) << MIPS3_PG_SHIFT) + +#define MIPS3_PG_SHIFT 6 +#define MIPS3_PG_FRAME 0x3fffffc0 + +#define VPN2_MASK 0xffffe000 +#define TLB_IS_GLOBAL(x) (((x).tlb_lo0 & MIPS3_PG_G) && ((x).tlb_lo1 & MIPS3_PG_G)) +#define TLB_VPN2(x) ((x).tlb_hi & VPN2_MASK) +#define TLB_ASID(x) ((x).tlb_hi & ASID_MASK) +#define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) ? ((x).tlb_lo1 & MIPS3_PG_V) : ((x).tlb_lo0 & MIPS3_PG_V)) + +struct kvm_mips_tlb { + long tlb_mask; + long tlb_hi; + long tlb_lo0; + long tlb_lo1; +}; + +#define KVM_MIPS_GUEST_TLB_SIZE 64 +struct kvm_vcpu_arch { + void *host_ebase, *guest_ebase; + unsigned long host_stack; + unsigned long host_gp; + + /* Host CP0 registers used when handling exits from guest */ + unsigned long host_cp0_badvaddr; + unsigned long host_cp0_cause; + unsigned long host_cp0_epc; + unsigned long host_cp0_entryhi; + uint32_t guest_inst; + + /* GPRS */ + unsigned long gprs[32]; + unsigned long hi; + unsigned long lo; + unsigned long pc; + + /* FPU State */ + struct mips_fpu_struct fpu; + + /* COP0 State */ + struct mips_coproc *cop0; + + /* Host KSEG0 address of the EI/DI offset */ + void *kseg0_commpage; + + u32 io_gpr; /* GPR used as IO source/target */ + + /* Used to calibrate the virutal count register for the guest */ + int32_t host_cp0_count; + + /* Bitmask of exceptions that are pending */ + unsigned long pending_exceptions; + + /* Bitmask of pending exceptions to be cleared */ + unsigned long pending_exceptions_clr; + + unsigned long pending_load_cause; + + /* Save/Restore the entryhi register when are are preempted/scheduled back in */ + unsigned long preempt_entryhi; + + /* S/W Based TLB for guest */ + struct kvm_mips_tlb guest_tlb[KVM_MIPS_GUEST_TLB_SIZE]; + + /* Cached guest kernel/user ASIDs */ + uint32_t guest_user_asid[NR_CPUS]; + uint32_t guest_kernel_asid[NR_CPUS]; + struct mm_struct guest_kernel_mm, guest_user_mm; + + struct kvm_mips_tlb shadow_tlb[NR_CPUS][KVM_MIPS_GUEST_TLB_SIZE]; + + + struct hrtimer comparecount_timer; + + int last_sched_cpu; + + /* WAIT executed */ + int wait; +}; + + +#define kvm_read_c0_guest_index(cop0) (cop0->reg[MIPS_CP0_TLB_INDEX][0]) +#define kvm_write_c0_guest_index(cop0, val) (cop0->reg[MIPS_CP0_TLB_INDEX][0] = val) +#define kvm_read_c0_guest_entrylo0(cop0) (cop0->reg[MIPS_CP0_TLB_LO0][0]) +#define kvm_read_c0_guest_entrylo1(cop0) (cop0->reg[MIPS_CP0_TLB_LO1][0]) +#define kvm_read_c0_guest_context(cop0) (cop0->reg[MIPS_CP0_TLB_CONTEXT][0]) +#define kvm_write_c0_guest_context(cop0, val) (cop0->reg[MIPS_CP0_TLB_CONTEXT][0] = (val)) +#define kvm_read_c0_guest_userlocal(cop0) (cop0->reg[MIPS_CP0_TLB_CONTEXT][2]) +#define kvm_read_c0_guest_pagemask(cop0) (cop0->reg[MIPS_CP0_TLB_PG_MASK][0]) +#define kvm_write_c0_guest_pagemask(cop0, val) (cop0->reg[MIPS_CP0_TLB_PG_MASK][0] = (val)) +#define kvm_read_c0_guest_wired(cop0) (cop0->reg[MIPS_CP0_TLB_WIRED][0]) +#define kvm_write_c0_guest_wired(cop0, val) (cop0->reg[MIPS_CP0_TLB_WIRED][0] = (val)) +#define kvm_read_c0_guest_badvaddr(cop0) (cop0->reg[MIPS_CP0_BAD_VADDR][0]) +#define kvm_write_c0_guest_badvaddr(cop0, val) (cop0->reg[MIPS_CP0_BAD_VADDR][0] = (val)) +#define kvm_read_c0_guest_count(cop0) (cop0->reg[MIPS_CP0_COUNT][0]) +#define kvm_write_c0_guest_count(cop0, val) (cop0->reg[MIPS_CP0_COUNT][0] = (val)) +#define kvm_read_c0_guest_entryhi(cop0) (cop0->reg[MIPS_CP0_TLB_HI][0]) +#define kvm_write_c0_guest_entryhi(cop0, val) (cop0->reg[MIPS_CP0_TLB_HI][0] = (val)) +#define kvm_read_c0_guest_compare(cop0) (cop0->reg[MIPS_CP0_COMPARE][0]) +#define kvm_write_c0_guest_compare(cop0, val) (cop0->reg[MIPS_CP0_COMPARE][0] = (val)) +#define kvm_read_c0_guest_status(cop0) (cop0->reg[MIPS_CP0_STATUS][0]) +#define kvm_write_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] = (val)) +#define kvm_read_c0_guest_intctl(cop0) (cop0->reg[MIPS_CP0_STATUS][1]) +#define kvm_write_c0_guest_intctl(cop0, val) (cop0->reg[MIPS_CP0_STATUS][1] = (val)) +#define kvm_read_c0_guest_cause(cop0) (cop0->reg[MIPS_CP0_CAUSE][0]) +#define kvm_write_c0_guest_cause(cop0, val) (cop0->reg[MIPS_CP0_CAUSE][0] = (val)) +#define kvm_read_c0_guest_epc(cop0) (cop0->reg[MIPS_CP0_EXC_PC][0]) +#define kvm_write_c0_guest_epc(cop0, val) (cop0->reg[MIPS_CP0_EXC_PC][0] = (val)) +#define kvm_read_c0_guest_prid(cop0) (cop0->reg[MIPS_CP0_PRID][0]) +#define kvm_write_c0_guest_prid(cop0, val) (cop0->reg[MIPS_CP0_PRID][0] = (val)) +#define kvm_read_c0_guest_ebase(cop0) (cop0->reg[MIPS_CP0_PRID][1]) +#define kvm_write_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] = (val)) +#define kvm_read_c0_guest_config(cop0) (cop0->reg[MIPS_CP0_CONFIG][0]) +#define kvm_read_c0_guest_config1(cop0) (cop0->reg[MIPS_CP0_CONFIG][1]) +#define kvm_read_c0_guest_config2(cop0) (cop0->reg[MIPS_CP0_CONFIG][2]) +#define kvm_read_c0_guest_config3(cop0) (cop0->reg[MIPS_CP0_CONFIG][3]) +#define kvm_read_c0_guest_config7(cop0) (cop0->reg[MIPS_CP0_CONFIG][7]) +#define kvm_write_c0_guest_config(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][0] = (val)) +#define kvm_write_c0_guest_config1(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][1] = (val)) +#define kvm_write_c0_guest_config2(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][2] = (val)) +#define kvm_write_c0_guest_config3(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][3] = (val)) +#define kvm_write_c0_guest_config7(cop0, val) (cop0->reg[MIPS_CP0_CONFIG][7] = (val)) +#define kvm_read_c0_guest_errorepc(cop0) (cop0->reg[MIPS_CP0_ERROR_PC][0]) +#define kvm_write_c0_guest_errorepc(cop0, val) (cop0->reg[MIPS_CP0_ERROR_PC][0] = (val)) + +#define kvm_set_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] |= (val)) +#define kvm_clear_c0_guest_status(cop0, val) (cop0->reg[MIPS_CP0_STATUS][0] &= ~(val)) +#define kvm_set_c0_guest_cause(cop0, val) (cop0->reg[MIPS_CP0_CAUSE][0] |= (val)) +#define kvm_clear_c0_guest_cause(cop0, val) (cop0->reg[MIPS_CP0_CAUSE][0] &= ~(val)) +#define kvm_change_c0_guest_cause(cop0, change, val) \ +{ \ + kvm_clear_c0_guest_cause(cop0, change); \ + kvm_set_c0_guest_cause(cop0, ((val) & (change))); \ +} +#define kvm_set_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] |= (val)) +#define kvm_clear_c0_guest_ebase(cop0, val) (cop0->reg[MIPS_CP0_PRID][1] &= ~(val)) +#define kvm_change_c0_guest_ebase(cop0, change, val) \ +{ \ + kvm_clear_c0_guest_ebase(cop0, change); \ + kvm_set_c0_guest_ebase(cop0, ((val) & (change))); \ +} + + +struct kvm_mips_callbacks { + int (*handle_cop_unusable) (struct kvm_vcpu *vcpu); + int (*handle_tlb_mod) (struct kvm_vcpu *vcpu); + int (*handle_tlb_ld_miss) (struct kvm_vcpu *vcpu); + int (*handle_tlb_st_miss) (struct kvm_vcpu *vcpu); + int (*handle_addr_err_st) (struct kvm_vcpu *vcpu); + int (*handle_addr_err_ld) (struct kvm_vcpu *vcpu); + int (*handle_syscall) (struct kvm_vcpu *vcpu); + int (*handle_res_inst) (struct kvm_vcpu *vcpu); + int (*handle_break) (struct kvm_vcpu *vcpu); + int (*vm_init) (struct kvm *kvm); + int (*vcpu_init) (struct kvm_vcpu *vcpu); + int (*vcpu_setup) (struct kvm_vcpu *vcpu); + gpa_t(*gva_to_gpa) (gva_t gva); + void (*queue_timer_int) (struct kvm_vcpu *vcpu); + void (*dequeue_timer_int) (struct kvm_vcpu *vcpu); + void (*queue_io_int) (struct kvm_vcpu *vcpu, + struct kvm_mips_interrupt *irq); + void (*dequeue_io_int) (struct kvm_vcpu *vcpu, + struct kvm_mips_interrupt *irq); + int (*irq_deliver) (struct kvm_vcpu *vcpu, unsigned int priority, + uint32_t cause); + int (*irq_clear) (struct kvm_vcpu *vcpu, unsigned int priority, + uint32_t cause); + int (*vcpu_ioctl_get_regs) (struct kvm_vcpu *vcpu, + struct kvm_regs *regs); + int (*vcpu_ioctl_set_regs) (struct kvm_vcpu *vcpu, + struct kvm_regs *regs); +}; +extern struct kvm_mips_callbacks *kvm_mips_callbacks; +int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks); + +/* Debug: dump vcpu state */ +int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu); + +/* Trampoline ASM routine to start running in "Guest" context */ +extern int __kvm_mips_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu); + +/* TLB handling */ +uint32_t kvm_get_kernel_asid(struct kvm_vcpu *vcpu); + +uint32_t kvm_get_user_asid(struct kvm_vcpu *vcpu); + +uint32_t kvm_get_commpage_asid (struct kvm_vcpu *vcpu); + +extern int kvm_mips_handle_kseg0_tlb_fault(unsigned long badbaddr, + struct kvm_vcpu *vcpu); + +extern int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr, + struct kvm_vcpu *vcpu); + +extern int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu, + struct kvm_mips_tlb *tlb, + unsigned long *hpa0, + unsigned long *hpa1); + +extern enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_handle_tlbmod(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern void kvm_mips_dump_host_tlbs(void); +extern void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu); +extern void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu); +extern void kvm_mips_flush_host_tlb(int skip_kseg0); +extern int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long entryhi); +extern int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index); + +extern int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, + unsigned long entryhi); +extern int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr); +extern unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu, + unsigned long gva); +extern void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, + struct kvm_vcpu *vcpu); +extern void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu); +extern void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu); +extern void kvm_local_flush_tlb_all(void); +extern void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu); +extern void kvm_mips_alloc_new_mmu_context(struct kvm_vcpu *vcpu); +extern void kvm_mips_vcpu_load(struct kvm_vcpu *vcpu, int cpu); +extern void kvm_mips_vcpu_put(struct kvm_vcpu *vcpu); + +/* Emulation */ +uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu); +enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause); + +extern enum emulation_result kvm_mips_emulate_inst(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_syscall(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_fpu_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_handle_ri(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_ri_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, + struct kvm_run *run); + +enum emulation_result kvm_mips_emulate_count(struct kvm_vcpu *vcpu); + +enum emulation_result kvm_mips_check_privilege(unsigned long cause, + uint32_t *opc, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +enum emulation_result kvm_mips_emulate_cache(uint32_t inst, + uint32_t *opc, + uint32_t cause, + struct kvm_run *run, + struct kvm_vcpu *vcpu); +enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, + uint32_t *opc, + uint32_t cause, + struct kvm_run *run, + struct kvm_vcpu *vcpu); +enum emulation_result kvm_mips_emulate_store(uint32_t inst, + uint32_t cause, + struct kvm_run *run, + struct kvm_vcpu *vcpu); +enum emulation_result kvm_mips_emulate_load(uint32_t inst, + uint32_t cause, + struct kvm_run *run, + struct kvm_vcpu *vcpu); + +/* Dynamic binary translation */ +extern int kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc, + struct kvm_vcpu *vcpu); +extern int kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc, + struct kvm_vcpu *vcpu); +extern int kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, + struct kvm_vcpu *vcpu); +extern int kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, + struct kvm_vcpu *vcpu); + +/* Misc */ +extern void mips32_SyncICache(unsigned long addr, unsigned long size); +extern int kvm_mips_dump_stats(struct kvm_vcpu *vcpu); +extern unsigned long kvm_mips_get_ramsize(struct kvm *kvm); + + +#endif /* __MIPS_KVM_HOST_H__ */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_clk.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_clk.h deleted file mode 100644 index 8fcf8df4418a..000000000000 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_clk.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef BCM63XX_CLK_H_ -#define BCM63XX_CLK_H_ - -struct clk { - void (*set)(struct clk *, int); - unsigned int rate; - unsigned int usage; - int id; -}; - -#endif /* ! BCM63XX_CLK_H_ */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index cb922b9cb0e9..336228990808 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -14,11 +14,12 @@ #define BCM6345_CPU_ID 0x6345 #define BCM6348_CPU_ID 0x6348 #define BCM6358_CPU_ID 0x6358 +#define BCM6362_CPU_ID 0x6362 #define BCM6368_CPU_ID 0x6368 void __init bcm63xx_cpu_init(void); u16 __bcm63xx_get_cpu_id(void); -u16 bcm63xx_get_cpu_rev(void); +u8 bcm63xx_get_cpu_rev(void); unsigned int bcm63xx_get_cpu_freq(void); #ifdef CONFIG_BCM63XX_CPU_6328 @@ -86,6 +87,20 @@ unsigned int bcm63xx_get_cpu_freq(void); # define BCMCPU_IS_6358() (0) #endif +#ifdef CONFIG_BCM63XX_CPU_6362 +# ifdef bcm63xx_get_cpu_id +# undef bcm63xx_get_cpu_id +# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id() +# define BCMCPU_RUNTIME_DETECT +# else +# define bcm63xx_get_cpu_id() BCM6362_CPU_ID +# endif +# define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID) +#else +# define BCMCPU_IS_6362() (0) +#endif + + #ifdef CONFIG_BCM63XX_CPU_6368 # ifdef bcm63xx_get_cpu_id # undef bcm63xx_get_cpu_id @@ -406,6 +421,62 @@ enum bcm63xx_regs_set { /* + * 6362 register sets base address + */ +#define BCM_6362_DSL_LMEM_BASE (0xdeadbeef) +#define BCM_6362_PERF_BASE (0xb0000000) +#define BCM_6362_TIMER_BASE (0xb0000040) +#define BCM_6362_WDT_BASE (0xb000005c) +#define BCM_6362_UART0_BASE (0xb0000100) +#define BCM_6362_UART1_BASE (0xb0000120) +#define BCM_6362_GPIO_BASE (0xb0000080) +#define BCM_6362_SPI_BASE (0xb0000800) +#define BCM_6362_HSSPI_BASE (0xb0001000) +#define BCM_6362_UDC0_BASE (0xdeadbeef) +#define BCM_6362_USBDMA_BASE (0xb000c000) +#define BCM_6362_OHCI0_BASE (0xb0002600) +#define BCM_6362_OHCI_PRIV_BASE (0xdeadbeef) +#define BCM_6362_USBH_PRIV_BASE (0xb0002700) +#define BCM_6362_USBD_BASE (0xb0002400) +#define BCM_6362_MPI_BASE (0xdeadbeef) +#define BCM_6362_PCMCIA_BASE (0xdeadbeef) +#define BCM_6362_PCIE_BASE (0xb0e40000) +#define BCM_6362_SDRAM_REGS_BASE (0xdeadbeef) +#define BCM_6362_DSL_BASE (0xdeadbeef) +#define BCM_6362_UBUS_BASE (0xdeadbeef) +#define BCM_6362_ENET0_BASE (0xdeadbeef) +#define BCM_6362_ENET1_BASE (0xdeadbeef) +#define BCM_6362_ENETDMA_BASE (0xb000d800) +#define BCM_6362_ENETDMAC_BASE (0xb000da00) +#define BCM_6362_ENETDMAS_BASE (0xb000dc00) +#define BCM_6362_ENETSW_BASE (0xb0e00000) +#define BCM_6362_EHCI0_BASE (0xb0002500) +#define BCM_6362_SDRAM_BASE (0xdeadbeef) +#define BCM_6362_MEMC_BASE (0xdeadbeef) +#define BCM_6362_DDR_BASE (0xb0003000) +#define BCM_6362_M2M_BASE (0xdeadbeef) +#define BCM_6362_ATM_BASE (0xdeadbeef) +#define BCM_6362_XTM_BASE (0xb0007800) +#define BCM_6362_XTMDMA_BASE (0xb000b800) +#define BCM_6362_XTMDMAC_BASE (0xdeadbeef) +#define BCM_6362_XTMDMAS_BASE (0xdeadbeef) +#define BCM_6362_PCM_BASE (0xb000a800) +#define BCM_6362_PCMDMA_BASE (0xdeadbeef) +#define BCM_6362_PCMDMAC_BASE (0xdeadbeef) +#define BCM_6362_PCMDMAS_BASE (0xdeadbeef) +#define BCM_6362_RNG_BASE (0xdeadbeef) +#define BCM_6362_MISC_BASE (0xb0001800) + +#define BCM_6362_NAND_REG_BASE (0xb0000200) +#define BCM_6362_NAND_CACHE_BASE (0xb0000600) +#define BCM_6362_LED_BASE (0xb0001900) +#define BCM_6362_IPSEC_BASE (0xb0002800) +#define BCM_6362_IPSEC_DMA_BASE (0xb000d000) +#define BCM_6362_WLAN_CHIPCOMMON_BASE (0xb0004000) +#define BCM_6362_WLAN_D11_BASE (0xb0005000) +#define BCM_6362_WLAN_SHIM_BASE (0xb0007000) + +/* * 6368 register sets base address */ #define BCM_6368_DSL_LMEM_BASE (0xdeadbeef) @@ -564,6 +635,9 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) #ifdef CONFIG_BCM63XX_CPU_6358 __GEN_RSET(6358) #endif +#ifdef CONFIG_BCM63XX_CPU_6362 + __GEN_RSET(6362) +#endif #ifdef CONFIG_BCM63XX_CPU_6368 __GEN_RSET(6368) #endif @@ -820,6 +894,71 @@ enum bcm63xx_irq { #define BCM_6358_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28) /* + * 6362 irqs + */ +#define BCM_6362_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32) + +#define BCM_6362_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_6362_SPI_IRQ (IRQ_INTERNAL_BASE + 2) +#define BCM_6362_UART0_IRQ (IRQ_INTERNAL_BASE + 3) +#define BCM_6362_UART1_IRQ (IRQ_INTERNAL_BASE + 4) +#define BCM_6362_DSL_IRQ (IRQ_INTERNAL_BASE + 28) +#define BCM_6362_UDC0_IRQ 0 +#define BCM_6362_ENET0_IRQ 0 +#define BCM_6362_ENET1_IRQ 0 +#define BCM_6362_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 14) +#define BCM_6362_HSSPI_IRQ (IRQ_INTERNAL_BASE + 5) +#define BCM_6362_OHCI0_IRQ (IRQ_INTERNAL_BASE + 9) +#define BCM_6362_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10) +#define BCM_6362_USBD_IRQ (IRQ_INTERNAL_BASE + 11) +#define BCM_6362_USBD_RXDMA0_IRQ (IRQ_INTERNAL_BASE + 20) +#define BCM_6362_USBD_TXDMA0_IRQ (IRQ_INTERNAL_BASE + 21) +#define BCM_6362_USBD_RXDMA1_IRQ (IRQ_INTERNAL_BASE + 22) +#define BCM_6362_USBD_TXDMA1_IRQ (IRQ_INTERNAL_BASE + 23) +#define BCM_6362_USBD_RXDMA2_IRQ (IRQ_INTERNAL_BASE + 24) +#define BCM_6362_USBD_TXDMA2_IRQ (IRQ_INTERNAL_BASE + 25) +#define BCM_6362_PCMCIA_IRQ 0 +#define BCM_6362_ENET0_RXDMA_IRQ 0 +#define BCM_6362_ENET0_TXDMA_IRQ 0 +#define BCM_6362_ENET1_RXDMA_IRQ 0 +#define BCM_6362_ENET1_TXDMA_IRQ 0 +#define BCM_6362_PCI_IRQ (IRQ_INTERNAL_BASE + 30) +#define BCM_6362_ATM_IRQ 0 +#define BCM_6362_ENETSW_RXDMA0_IRQ (BCM_6362_HIGH_IRQ_BASE + 0) +#define BCM_6362_ENETSW_RXDMA1_IRQ (BCM_6362_HIGH_IRQ_BASE + 1) +#define BCM_6362_ENETSW_RXDMA2_IRQ (BCM_6362_HIGH_IRQ_BASE + 2) +#define BCM_6362_ENETSW_RXDMA3_IRQ (BCM_6362_HIGH_IRQ_BASE + 3) +#define BCM_6362_ENETSW_TXDMA0_IRQ 0 +#define BCM_6362_ENETSW_TXDMA1_IRQ 0 +#define BCM_6362_ENETSW_TXDMA2_IRQ 0 +#define BCM_6362_ENETSW_TXDMA3_IRQ 0 +#define BCM_6362_XTM_IRQ 0 +#define BCM_6362_XTM_DMA0_IRQ (BCM_6362_HIGH_IRQ_BASE + 12) + +#define BCM_6362_RING_OSC_IRQ (IRQ_INTERNAL_BASE + 1) +#define BCM_6362_WLAN_GPIO_IRQ (IRQ_INTERNAL_BASE + 6) +#define BCM_6362_WLAN_IRQ (IRQ_INTERNAL_BASE + 7) +#define BCM_6362_IPSEC_IRQ (IRQ_INTERNAL_BASE + 8) +#define BCM_6362_NAND_IRQ (IRQ_INTERNAL_BASE + 12) +#define BCM_6362_PCM_IRQ (IRQ_INTERNAL_BASE + 13) +#define BCM_6362_DG_IRQ (IRQ_INTERNAL_BASE + 15) +#define BCM_6362_EPHY_ENERGY0_IRQ (IRQ_INTERNAL_BASE + 16) +#define BCM_6362_EPHY_ENERGY1_IRQ (IRQ_INTERNAL_BASE + 17) +#define BCM_6362_EPHY_ENERGY2_IRQ (IRQ_INTERNAL_BASE + 18) +#define BCM_6362_EPHY_ENERGY3_IRQ (IRQ_INTERNAL_BASE + 19) +#define BCM_6362_IPSEC_DMA0_IRQ (IRQ_INTERNAL_BASE + 26) +#define BCM_6362_IPSEC_DMA1_IRQ (IRQ_INTERNAL_BASE + 27) +#define BCM_6362_FAP0_IRQ (IRQ_INTERNAL_BASE + 29) +#define BCM_6362_PCM_DMA0_IRQ (BCM_6362_HIGH_IRQ_BASE + 4) +#define BCM_6362_PCM_DMA1_IRQ (BCM_6362_HIGH_IRQ_BASE + 5) +#define BCM_6362_DECT0_IRQ (BCM_6362_HIGH_IRQ_BASE + 6) +#define BCM_6362_DECT1_IRQ (BCM_6362_HIGH_IRQ_BASE + 7) +#define BCM_6362_EXT_IRQ0 (BCM_6362_HIGH_IRQ_BASE + 8) +#define BCM_6362_EXT_IRQ1 (BCM_6362_HIGH_IRQ_BASE + 9) +#define BCM_6362_EXT_IRQ2 (BCM_6362_HIGH_IRQ_BASE + 10) +#define BCM_6362_EXT_IRQ3 (BCM_6362_HIGH_IRQ_BASE + 11) + +/* * 6368 irqs */ #define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32) diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h index b0184cf02575..c426cabc620a 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h @@ -71,18 +71,13 @@ static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg) return bcm63xx_regs_spi[reg]; #else -#ifdef CONFIG_BCM63XX_CPU_6338 - __GEN_SPI_RSET(6338) -#endif -#ifdef CONFIG_BCM63XX_CPU_6348 +#if defined(CONFIG_BCM63XX_CPU_6338) || defined(CONFIG_BCM63XX_CPU_6348) __GEN_SPI_RSET(6348) #endif -#ifdef CONFIG_BCM63XX_CPU_6358 +#if defined(CONFIG_BCM63XX_CPU_6358) || defined(CONFIG_BCM63XX_CPU_6362) || \ + defined(CONFIG_BCM63XX_CPU_6368) __GEN_SPI_RSET(6358) #endif -#ifdef CONFIG_BCM63XX_CPU_6368 - __GEN_SPI_RSET(6368) -#endif #endif return 0; } diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h index 0a9891f7580d..35baa1a60a64 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h @@ -17,6 +17,8 @@ static inline unsigned long bcm63xx_gpio_count(void) return 8; case BCM6345_CPU_ID: return 16; + case BCM6362_CPU_ID: + return 48; case BCM6368_CPU_ID: return 38; case BCM6348_CPU_ID: diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 81b4702f792a..3203fe49b34d 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -10,7 +10,7 @@ #define REV_CHIPID_SHIFT 16 #define REV_CHIPID_MASK (0xffff << REV_CHIPID_SHIFT) #define REV_REVID_SHIFT 0 -#define REV_REVID_MASK (0xffff << REV_REVID_SHIFT) +#define REV_REVID_MASK (0xff << REV_REVID_SHIFT) /* Clock Control register */ #define PERF_CKCTL_REG 0x4 @@ -112,6 +112,39 @@ CKCTL_6358_USBSU_EN | \ CKCTL_6358_EPHY_EN) +#define CKCTL_6362_ADSL_QPROC_EN (1 << 1) +#define CKCTL_6362_ADSL_AFE_EN (1 << 2) +#define CKCTL_6362_ADSL_EN (1 << 3) +#define CKCTL_6362_MIPS_EN (1 << 4) +#define CKCTL_6362_WLAN_OCP_EN (1 << 5) +#define CKCTL_6362_SWPKT_USB_EN (1 << 7) +#define CKCTL_6362_SWPKT_SAR_EN (1 << 8) +#define CKCTL_6362_SAR_EN (1 << 9) +#define CKCTL_6362_ROBOSW_EN (1 << 10) +#define CKCTL_6362_PCM_EN (1 << 11) +#define CKCTL_6362_USBD_EN (1 << 12) +#define CKCTL_6362_USBH_EN (1 << 13) +#define CKCTL_6362_IPSEC_EN (1 << 14) +#define CKCTL_6362_SPI_EN (1 << 15) +#define CKCTL_6362_HSSPI_EN (1 << 16) +#define CKCTL_6362_PCIE_EN (1 << 17) +#define CKCTL_6362_FAP_EN (1 << 18) +#define CKCTL_6362_PHYMIPS_EN (1 << 19) +#define CKCTL_6362_NAND_EN (1 << 20) + +#define CKCTL_6362_ALL_SAFE_EN (CKCTL_6362_PHYMIPS_EN | \ + CKCTL_6362_ADSL_QPROC_EN | \ + CKCTL_6362_ADSL_AFE_EN | \ + CKCTL_6362_ADSL_EN | \ + CKCTL_6362_SAR_EN | \ + CKCTL_6362_PCM_EN | \ + CKCTL_6362_IPSEC_EN | \ + CKCTL_6362_USBD_EN | \ + CKCTL_6362_USBH_EN | \ + CKCTL_6362_ROBOSW_EN | \ + CKCTL_6362_PCIE_EN) + + #define CKCTL_6368_VDSL_QPROC_EN (1 << 2) #define CKCTL_6368_VDSL_AFE_EN (1 << 3) #define CKCTL_6368_VDSL_BONDING_EN (1 << 4) @@ -153,6 +186,7 @@ #define PERF_IRQMASK_6345_REG 0xc #define PERF_IRQMASK_6348_REG 0xc #define PERF_IRQMASK_6358_REG 0xc +#define PERF_IRQMASK_6362_REG 0x20 #define PERF_IRQMASK_6368_REG 0x20 /* Interrupt Status register */ @@ -161,6 +195,7 @@ #define PERF_IRQSTAT_6345_REG 0x10 #define PERF_IRQSTAT_6348_REG 0x10 #define PERF_IRQSTAT_6358_REG 0x10 +#define PERF_IRQSTAT_6362_REG 0x28 #define PERF_IRQSTAT_6368_REG 0x28 /* External Interrupt Configuration register */ @@ -169,6 +204,7 @@ #define PERF_EXTIRQ_CFG_REG_6345 0x14 #define PERF_EXTIRQ_CFG_REG_6348 0x14 #define PERF_EXTIRQ_CFG_REG_6358 0x14 +#define PERF_EXTIRQ_CFG_REG_6362 0x18 #define PERF_EXTIRQ_CFG_REG_6368 0x18 #define PERF_EXTIRQ_CFG_REG2_6368 0x1c @@ -197,6 +233,7 @@ #define PERF_SOFTRESET_REG 0x28 #define PERF_SOFTRESET_6328_REG 0x10 #define PERF_SOFTRESET_6358_REG 0x34 +#define PERF_SOFTRESET_6362_REG 0x10 #define PERF_SOFTRESET_6368_REG 0x10 #define SOFTRESET_6328_SPI_MASK (1 << 0) @@ -259,6 +296,22 @@ #define SOFTRESET_6358_PCM_MASK (1 << 13) #define SOFTRESET_6358_ADSL_MASK (1 << 14) +#define SOFTRESET_6362_SPI_MASK (1 << 0) +#define SOFTRESET_6362_IPSEC_MASK (1 << 1) +#define SOFTRESET_6362_EPHY_MASK (1 << 2) +#define SOFTRESET_6362_SAR_MASK (1 << 3) +#define SOFTRESET_6362_ENETSW_MASK (1 << 4) +#define SOFTRESET_6362_USBS_MASK (1 << 5) +#define SOFTRESET_6362_USBH_MASK (1 << 6) +#define SOFTRESET_6362_PCM_MASK (1 << 7) +#define SOFTRESET_6362_PCIE_CORE_MASK (1 << 8) +#define SOFTRESET_6362_PCIE_MASK (1 << 9) +#define SOFTRESET_6362_PCIE_EXT_MASK (1 << 10) +#define SOFTRESET_6362_WLAN_SHIM_MASK (1 << 11) +#define SOFTRESET_6362_DDR_PHY_MASK (1 << 12) +#define SOFTRESET_6362_FAP_MASK (1 << 13) +#define SOFTRESET_6362_WLAN_UBUS_MASK (1 << 14) + #define SOFTRESET_6368_SPI_MASK (1 << 0) #define SOFTRESET_6368_MPI_MASK (1 << 3) #define SOFTRESET_6368_EPHY_MASK (1 << 6) @@ -1223,24 +1276,7 @@ * _REG relative to RSET_SPI *************************************************************************/ -/* BCM 6338 SPI core */ -#define SPI_6338_CMD 0x00 /* 16-bits register */ -#define SPI_6338_INT_STATUS 0x02 -#define SPI_6338_INT_MASK_ST 0x03 -#define SPI_6338_INT_MASK 0x04 -#define SPI_6338_ST 0x05 -#define SPI_6338_CLK_CFG 0x06 -#define SPI_6338_FILL_BYTE 0x07 -#define SPI_6338_MSG_TAIL 0x09 -#define SPI_6338_RX_TAIL 0x0b -#define SPI_6338_MSG_CTL 0x40 /* 8-bits register */ -#define SPI_6338_MSG_CTL_WIDTH 8 -#define SPI_6338_MSG_DATA 0x41 -#define SPI_6338_MSG_DATA_SIZE 0x3f -#define SPI_6338_RX_DATA 0x80 -#define SPI_6338_RX_DATA_SIZE 0x3f - -/* BCM 6348 SPI core */ +/* BCM 6338/6348 SPI core */ #define SPI_6348_CMD 0x00 /* 16-bits register */ #define SPI_6348_INT_STATUS 0x02 #define SPI_6348_INT_MASK_ST 0x03 @@ -1257,7 +1293,7 @@ #define SPI_6348_RX_DATA 0x80 #define SPI_6348_RX_DATA_SIZE 0x3f -/* BCM 6358 SPI core */ +/* BCM 6358/6262/6368 SPI core */ #define SPI_6358_MSG_CTL 0x00 /* 16-bits register */ #define SPI_6358_MSG_CTL_WIDTH 16 #define SPI_6358_MSG_DATA 0x02 @@ -1274,23 +1310,6 @@ #define SPI_6358_MSG_TAIL 0x709 #define SPI_6358_RX_TAIL 0x70B -/* BCM 6358 SPI core */ -#define SPI_6368_MSG_CTL 0x00 /* 16-bits register */ -#define SPI_6368_MSG_CTL_WIDTH 16 -#define SPI_6368_MSG_DATA 0x02 -#define SPI_6368_MSG_DATA_SIZE 0x21e -#define SPI_6368_RX_DATA 0x400 -#define SPI_6368_RX_DATA_SIZE 0x220 -#define SPI_6368_CMD 0x700 /* 16-bits register */ -#define SPI_6368_INT_STATUS 0x702 -#define SPI_6368_INT_MASK_ST 0x703 -#define SPI_6368_INT_MASK 0x704 -#define SPI_6368_ST 0x705 -#define SPI_6368_CLK_CFG 0x706 -#define SPI_6368_FILL_BYTE 0x707 -#define SPI_6368_MSG_TAIL 0x709 -#define SPI_6368_RX_TAIL 0x70B - /* Shared SPI definitions */ /* Message configuration */ @@ -1298,10 +1317,8 @@ #define SPI_HD_W 0x01 #define SPI_HD_R 0x02 #define SPI_BYTE_CNT_SHIFT 0 -#define SPI_6338_MSG_TYPE_SHIFT 6 #define SPI_6348_MSG_TYPE_SHIFT 6 #define SPI_6358_MSG_TYPE_SHIFT 14 -#define SPI_6368_MSG_TYPE_SHIFT 14 /* Command */ #define SPI_CMD_NOOP 0x00 @@ -1348,10 +1365,18 @@ /************************************************************************* * _REG relative to RSET_MISC *************************************************************************/ -#define MISC_SERDES_CTRL_REG 0x0 +#define MISC_SERDES_CTRL_6328_REG 0x0 +#define MISC_SERDES_CTRL_6362_REG 0x4 #define SERDES_PCIE_EN (1 << 0) #define SERDES_PCIE_EXD_EN (1 << 15) +#define MISC_STRAPBUS_6362_REG 0x14 +#define STRAPBUS_6362_FCVO_SHIFT 1 +#define STRAPBUS_6362_HSSPI_CLK_FAST (1 << 13) +#define STRAPBUS_6362_FCVO_MASK (0x1f << STRAPBUS_6362_FCVO_SHIFT) +#define STRAPBUS_6362_BOOT_SEL_SERIAL (1 << 15) +#define STRAPBUS_6362_BOOT_SEL_NAND (0 << 15) + #define MISC_STRAPBUS_6328_REG 0x240 #define STRAPBUS_6328_FCVO_SHIFT 7 #define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT) diff --git a/arch/mips/include/asm/mach-bcm63xx/ioremap.h b/arch/mips/include/asm/mach-bcm63xx/ioremap.h index 30931c42379d..94e3011ba7df 100644 --- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h +++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h @@ -19,6 +19,7 @@ static inline int is_bcm63xx_internal_registers(phys_t offset) return 1; break; case BCM6328_CPU_ID: + case BCM6362_CPU_ID: case BCM6368_CPU_ID: if (offset >= 0xb0000000 && offset < 0xb1000000) return 1; diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h index 9c95177f7a7e..fe23034aaf72 100644 --- a/arch/mips/include/asm/mach-generic/dma-coherence.h +++ b/arch/mips/include/asm/mach-generic/dma-coherence.h @@ -61,9 +61,8 @@ static inline int plat_device_is_coherent(struct device *dev) { #ifdef CONFIG_DMA_COHERENT return 1; -#endif -#ifdef CONFIG_DMA_NONCOHERENT - return 0; +#else + return coherentio; #endif } diff --git a/arch/mips/include/asm/mach-generic/spaces.h b/arch/mips/include/asm/mach-generic/spaces.h index 73d717a75cb0..5b2f2e68e57f 100644 --- a/arch/mips/include/asm/mach-generic/spaces.h +++ b/arch/mips/include/asm/mach-generic/spaces.h @@ -20,14 +20,21 @@ #endif #ifdef CONFIG_32BIT - +#ifdef CONFIG_KVM_GUEST +#define CAC_BASE _AC(0x40000000, UL) +#else #define CAC_BASE _AC(0x80000000, UL) +#endif #define IO_BASE _AC(0xa0000000, UL) #define UNCAC_BASE _AC(0xa0000000, UL) #ifndef MAP_BASE +#ifdef CONFIG_KVM_GUEST +#define MAP_BASE _AC(0x60000000, UL) +#else #define MAP_BASE _AC(0xc0000000, UL) #endif +#endif /* * Memory above this physical address will be considered highmem. diff --git a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h index 75fd8c0f986e..c0f3ef45c2c1 100644 --- a/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h @@ -57,5 +57,6 @@ #define cpu_has_vint 0 #define cpu_has_vtag_icache 0 #define cpu_has_watch 1 +#define cpu_has_local_ebase 0 #endif /* __ASM_MACH_LOONGSON_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ralink/mt7620.h b/arch/mips/include/asm/mach-ralink/mt7620.h new file mode 100644 index 000000000000..9809972ea882 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/mt7620.h @@ -0,0 +1,84 @@ +/* + * 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. + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _MT7620_REGS_H_ +#define _MT7620_REGS_H_ + +#define MT7620_SYSC_BASE 0x10000000 + +#define SYSC_REG_CHIP_NAME0 0x00 +#define SYSC_REG_CHIP_NAME1 0x04 +#define SYSC_REG_CHIP_REV 0x0c +#define SYSC_REG_SYSTEM_CONFIG0 0x10 +#define SYSC_REG_SYSTEM_CONFIG1 0x14 +#define SYSC_REG_CPLL_CONFIG0 0x54 +#define SYSC_REG_CPLL_CONFIG1 0x58 + +#define MT7620N_CHIP_NAME0 0x33365452 +#define MT7620N_CHIP_NAME1 0x20203235 + +#define MT7620A_CHIP_NAME0 0x3637544d +#define MT7620A_CHIP_NAME1 0x20203032 + +#define CHIP_REV_PKG_MASK 0x1 +#define CHIP_REV_PKG_SHIFT 16 +#define CHIP_REV_VER_MASK 0xf +#define CHIP_REV_VER_SHIFT 8 +#define CHIP_REV_ECO_MASK 0xf + +#define CPLL_SW_CONFIG_SHIFT 31 +#define CPLL_SW_CONFIG_MASK 0x1 +#define CPLL_CPU_CLK_SHIFT 24 +#define CPLL_CPU_CLK_MASK 0x1 +#define CPLL_MULT_RATIO_SHIFT 16 +#define CPLL_MULT_RATIO 0x7 +#define CPLL_DIV_RATIO_SHIFT 10 +#define CPLL_DIV_RATIO 0x3 + +#define SYSCFG0_DRAM_TYPE_MASK 0x3 +#define SYSCFG0_DRAM_TYPE_SHIFT 4 +#define SYSCFG0_DRAM_TYPE_SDRAM 0 +#define SYSCFG0_DRAM_TYPE_DDR1 1 +#define SYSCFG0_DRAM_TYPE_DDR2 2 + +#define MT7620_DRAM_BASE 0x0 +#define MT7620_SDRAM_SIZE_MIN 2 +#define MT7620_SDRAM_SIZE_MAX 64 +#define MT7620_DDR1_SIZE_MIN 32 +#define MT7620_DDR1_SIZE_MAX 128 +#define MT7620_DDR2_SIZE_MIN 32 +#define MT7620_DDR2_SIZE_MAX 256 + +#define MT7620_GPIO_MODE_I2C BIT(0) +#define MT7620_GPIO_MODE_UART0_SHIFT 2 +#define MT7620_GPIO_MODE_UART0_MASK 0x7 +#define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT) +#define MT7620_GPIO_MODE_UARTF 0x0 +#define MT7620_GPIO_MODE_PCM_UARTF 0x1 +#define MT7620_GPIO_MODE_PCM_I2S 0x2 +#define MT7620_GPIO_MODE_I2S_UARTF 0x3 +#define MT7620_GPIO_MODE_PCM_GPIO 0x4 +#define MT7620_GPIO_MODE_GPIO_UARTF 0x5 +#define MT7620_GPIO_MODE_GPIO_I2S 0x6 +#define MT7620_GPIO_MODE_GPIO 0x7 +#define MT7620_GPIO_MODE_UART1 BIT(5) +#define MT7620_GPIO_MODE_MDIO BIT(8) +#define MT7620_GPIO_MODE_RGMII1 BIT(9) +#define MT7620_GPIO_MODE_RGMII2 BIT(10) +#define MT7620_GPIO_MODE_SPI BIT(11) +#define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12) +#define MT7620_GPIO_MODE_WLED BIT(13) +#define MT7620_GPIO_MODE_JTAG BIT(15) +#define MT7620_GPIO_MODE_EPHY BIT(15) +#define MT7620_GPIO_MODE_WDT BIT(22) + +#endif diff --git a/arch/mips/include/asm/mach-ralink/rt288x.h b/arch/mips/include/asm/mach-ralink/rt288x.h new file mode 100644 index 000000000000..03ad716acb42 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/rt288x.h @@ -0,0 +1,53 @@ +/* + * 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. + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _RT288X_REGS_H_ +#define _RT288X_REGS_H_ + +#define RT2880_SYSC_BASE 0x00300000 + +#define SYSC_REG_CHIP_NAME0 0x00 +#define SYSC_REG_CHIP_NAME1 0x04 +#define SYSC_REG_CHIP_ID 0x0c +#define SYSC_REG_SYSTEM_CONFIG 0x10 +#define SYSC_REG_CLKCFG 0x30 + +#define RT2880_CHIP_NAME0 0x38325452 +#define RT2880_CHIP_NAME1 0x20203038 + +#define CHIP_ID_ID_MASK 0xff +#define CHIP_ID_ID_SHIFT 8 +#define CHIP_ID_REV_MASK 0xff + +#define SYSTEM_CONFIG_CPUCLK_SHIFT 20 +#define SYSTEM_CONFIG_CPUCLK_MASK 0x3 +#define SYSTEM_CONFIG_CPUCLK_250 0x0 +#define SYSTEM_CONFIG_CPUCLK_266 0x1 +#define SYSTEM_CONFIG_CPUCLK_280 0x2 +#define SYSTEM_CONFIG_CPUCLK_300 0x3 + +#define RT2880_GPIO_MODE_I2C BIT(0) +#define RT2880_GPIO_MODE_UART0 BIT(1) +#define RT2880_GPIO_MODE_SPI BIT(2) +#define RT2880_GPIO_MODE_UART1 BIT(3) +#define RT2880_GPIO_MODE_JTAG BIT(4) +#define RT2880_GPIO_MODE_MDIO BIT(5) +#define RT2880_GPIO_MODE_SDRAM BIT(6) +#define RT2880_GPIO_MODE_PCI BIT(7) + +#define CLKCFG_SRAM_CS_N_WDT BIT(9) + +#define RT2880_SDRAM_BASE 0x08000000 +#define RT2880_MEM_SIZE_MIN 2 +#define RT2880_MEM_SIZE_MAX 128 + +#endif diff --git a/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h new file mode 100644 index 000000000000..72fc10669199 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/rt288x/cpu-feature-overrides.h @@ -0,0 +1,56 @@ +/* + * Ralink RT288x specific CPU feature overrides + * + * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + * This file was derived from: include/asm-mips/cpu-features.h + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ +#ifndef _RT288X_CPU_FEATURE_OVERRIDES_H +#define _RT288X_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_divec 1 + +#define cpu_has_prefetch 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +#define cpu_has_mips16 1 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 1 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 + +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +#define cpu_dcache_line_size() 16 +#define cpu_icache_line_size() 16 + +#endif /* _RT288X_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ralink/rt305x.h b/arch/mips/include/asm/mach-ralink/rt305x.h index 7d344f2d7d0a..069bf37a6010 100644 --- a/arch/mips/include/asm/mach-ralink/rt305x.h +++ b/arch/mips/include/asm/mach-ralink/rt305x.h @@ -97,6 +97,14 @@ static inline int soc_is_rt5350(void) #define RT5350_SYSCFG0_CPUCLK_320 0x2 #define RT5350_SYSCFG0_CPUCLK_300 0x3 +#define RT5350_SYSCFG0_DRAM_SIZE_SHIFT 12 +#define RT5350_SYSCFG0_DRAM_SIZE_MASK 7 +#define RT5350_SYSCFG0_DRAM_SIZE_2M 0 +#define RT5350_SYSCFG0_DRAM_SIZE_8M 1 +#define RT5350_SYSCFG0_DRAM_SIZE_16M 2 +#define RT5350_SYSCFG0_DRAM_SIZE_32M 3 +#define RT5350_SYSCFG0_DRAM_SIZE_64M 4 + /* multi function gpio pins */ #define RT305X_GPIO_I2C_SD 1 #define RT305X_GPIO_I2C_SCLK 2 @@ -136,4 +144,23 @@ static inline int soc_is_rt5350(void) #define RT305X_GPIO_MODE_SDRAM BIT(8) #define RT305X_GPIO_MODE_RGMII BIT(9) +#define RT3352_SYSC_REG_SYSCFG0 0x010 +#define RT3352_SYSC_REG_SYSCFG1 0x014 +#define RT3352_SYSC_REG_CLKCFG1 0x030 +#define RT3352_SYSC_REG_RSTCTRL 0x034 +#define RT3352_SYSC_REG_USB_PS 0x05c + +#define RT3352_CLKCFG0_XTAL_SEL BIT(20) +#define RT3352_CLKCFG1_UPHY0_CLK_EN BIT(18) +#define RT3352_CLKCFG1_UPHY1_CLK_EN BIT(20) +#define RT3352_RSTCTRL_UHST BIT(22) +#define RT3352_RSTCTRL_UDEV BIT(25) +#define RT3352_SYSCFG1_USB0_HOST_MODE BIT(10) + +#define RT305X_SDRAM_BASE 0x00000000 +#define RT305X_MEM_SIZE_MIN 2 +#define RT305X_MEM_SIZE_MAX 64 +#define RT3352_MEM_SIZE_MIN 2 +#define RT3352_MEM_SIZE_MAX 256 + #endif diff --git a/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h new file mode 100644 index 000000000000..917c28654552 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/rt305x/cpu-feature-overrides.h @@ -0,0 +1,56 @@ +/* + * Ralink RT305x specific CPU feature overrides + * + * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * + * This file was derived from: include/asm-mips/cpu-features.h + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ +#ifndef _RT305X_CPU_FEATURE_OVERRIDES_H +#define _RT305X_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_divec 1 + +#define cpu_has_prefetch 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +#define cpu_has_mips16 1 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 1 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_dsp 1 +#define cpu_has_mipsmt 0 + +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 + +#endif /* _RT305X_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-ralink/rt3883.h b/arch/mips/include/asm/mach-ralink/rt3883.h new file mode 100644 index 000000000000..058382f37f92 --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/rt3883.h @@ -0,0 +1,252 @@ +/* + * Ralink RT3662/RT3883 SoC register definitions + * + * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _RT3883_REGS_H_ +#define _RT3883_REGS_H_ + +#include <linux/bitops.h> + +#define RT3883_SDRAM_BASE 0x00000000 +#define RT3883_SYSC_BASE 0x10000000 +#define RT3883_TIMER_BASE 0x10000100 +#define RT3883_INTC_BASE 0x10000200 +#define RT3883_MEMC_BASE 0x10000300 +#define RT3883_UART0_BASE 0x10000500 +#define RT3883_PIO_BASE 0x10000600 +#define RT3883_FSCC_BASE 0x10000700 +#define RT3883_NANDC_BASE 0x10000810 +#define RT3883_I2C_BASE 0x10000900 +#define RT3883_I2S_BASE 0x10000a00 +#define RT3883_SPI_BASE 0x10000b00 +#define RT3883_UART1_BASE 0x10000c00 +#define RT3883_PCM_BASE 0x10002000 +#define RT3883_GDMA_BASE 0x10002800 +#define RT3883_CODEC1_BASE 0x10003000 +#define RT3883_CODEC2_BASE 0x10003800 +#define RT3883_FE_BASE 0x10100000 +#define RT3883_ROM_BASE 0x10118000 +#define RT3883_USBDEV_BASE 0x10112000 +#define RT3883_PCI_BASE 0x10140000 +#define RT3883_WLAN_BASE 0x10180000 +#define RT3883_USBHOST_BASE 0x101c0000 +#define RT3883_BOOT_BASE 0x1c000000 +#define RT3883_SRAM_BASE 0x1e000000 +#define RT3883_PCIMEM_BASE 0x20000000 + +#define RT3883_EHCI_BASE (RT3883_USBHOST_BASE) +#define RT3883_OHCI_BASE (RT3883_USBHOST_BASE + 0x1000) + +#define RT3883_SYSC_SIZE 0x100 +#define RT3883_TIMER_SIZE 0x100 +#define RT3883_INTC_SIZE 0x100 +#define RT3883_MEMC_SIZE 0x100 +#define RT3883_UART0_SIZE 0x100 +#define RT3883_UART1_SIZE 0x100 +#define RT3883_PIO_SIZE 0x100 +#define RT3883_FSCC_SIZE 0x100 +#define RT3883_NANDC_SIZE 0x0f0 +#define RT3883_I2C_SIZE 0x100 +#define RT3883_I2S_SIZE 0x100 +#define RT3883_SPI_SIZE 0x100 +#define RT3883_PCM_SIZE 0x800 +#define RT3883_GDMA_SIZE 0x800 +#define RT3883_CODEC1_SIZE 0x800 +#define RT3883_CODEC2_SIZE 0x800 +#define RT3883_FE_SIZE 0x10000 +#define RT3883_ROM_SIZE 0x4000 +#define RT3883_USBDEV_SIZE 0x4000 +#define RT3883_PCI_SIZE 0x40000 +#define RT3883_WLAN_SIZE 0x40000 +#define RT3883_USBHOST_SIZE 0x40000 +#define RT3883_BOOT_SIZE (32 * 1024 * 1024) +#define RT3883_SRAM_SIZE (32 * 1024 * 1024) + +/* SYSC registers */ +#define RT3883_SYSC_REG_CHIPID0_3 0x00 /* Chip ID 0 */ +#define RT3883_SYSC_REG_CHIPID4_7 0x04 /* Chip ID 1 */ +#define RT3883_SYSC_REG_REVID 0x0c /* Chip Revision Identification */ +#define RT3883_SYSC_REG_SYSCFG0 0x10 /* System Configuration 0 */ +#define RT3883_SYSC_REG_SYSCFG1 0x14 /* System Configuration 1 */ +#define RT3883_SYSC_REG_CLKCFG0 0x2c /* Clock Configuration 0 */ +#define RT3883_SYSC_REG_CLKCFG1 0x30 /* Clock Configuration 1 */ +#define RT3883_SYSC_REG_RSTCTRL 0x34 /* Reset Control*/ +#define RT3883_SYSC_REG_RSTSTAT 0x38 /* Reset Status*/ +#define RT3883_SYSC_REG_USB_PS 0x5c /* USB Power saving control */ +#define RT3883_SYSC_REG_GPIO_MODE 0x60 /* GPIO Purpose Select */ +#define RT3883_SYSC_REG_PCIE_CLK_GEN0 0x7c +#define RT3883_SYSC_REG_PCIE_CLK_GEN1 0x80 +#define RT3883_SYSC_REG_PCIE_CLK_GEN2 0x84 +#define RT3883_SYSC_REG_PMU 0x88 +#define RT3883_SYSC_REG_PMU1 0x8c + +#define RT3883_CHIP_NAME0 0x38335452 +#define RT3883_CHIP_NAME1 0x20203338 + +#define RT3883_REVID_VER_ID_MASK 0x0f +#define RT3883_REVID_VER_ID_SHIFT 8 +#define RT3883_REVID_ECO_ID_MASK 0x0f + +#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) +#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 +#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 +#define RT3883_SYSCFG0_CPUCLK_250 0x0 +#define RT3883_SYSCFG0_CPUCLK_384 0x1 +#define RT3883_SYSCFG0_CPUCLK_480 0x2 +#define RT3883_SYSCFG0_CPUCLK_500 0x3 + +#define RT3883_SYSCFG1_USB0_HOST_MODE BIT(10) +#define RT3883_SYSCFG1_PCIE_RC_MODE BIT(8) +#define RT3883_SYSCFG1_PCI_HOST_MODE BIT(7) +#define RT3883_SYSCFG1_PCI_66M_MODE BIT(6) +#define RT3883_SYSCFG1_GPIO2_AS_WDT_OUT BIT(2) + +#define RT3883_CLKCFG1_PCIE_CLK_EN BIT(21) +#define RT3883_CLKCFG1_UPHY1_CLK_EN BIT(20) +#define RT3883_CLKCFG1_PCI_CLK_EN BIT(19) +#define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18) + +#define RT3883_GPIO_MODE_I2C BIT(0) +#define RT3883_GPIO_MODE_SPI BIT(1) +#define RT3883_GPIO_MODE_UART0_SHIFT 2 +#define RT3883_GPIO_MODE_UART0_MASK 0x7 +#define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT) +#define RT3883_GPIO_MODE_UARTF 0x0 +#define RT3883_GPIO_MODE_PCM_UARTF 0x1 +#define RT3883_GPIO_MODE_PCM_I2S 0x2 +#define RT3883_GPIO_MODE_I2S_UARTF 0x3 +#define RT3883_GPIO_MODE_PCM_GPIO 0x4 +#define RT3883_GPIO_MODE_GPIO_UARTF 0x5 +#define RT3883_GPIO_MODE_GPIO_I2S 0x6 +#define RT3883_GPIO_MODE_GPIO 0x7 +#define RT3883_GPIO_MODE_UART1 BIT(5) +#define RT3883_GPIO_MODE_JTAG BIT(6) +#define RT3883_GPIO_MODE_MDIO BIT(7) +#define RT3883_GPIO_MODE_GE1 BIT(9) +#define RT3883_GPIO_MODE_GE2 BIT(10) +#define RT3883_GPIO_MODE_PCI_SHIFT 11 +#define RT3883_GPIO_MODE_PCI_MASK 0x7 +#define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT) +#define RT3883_GPIO_MODE_LNA_A_SHIFT 16 +#define RT3883_GPIO_MODE_LNA_A_MASK 0x3 +#define _RT3883_GPIO_MODE_LNA_A(_x) ((_x) << RT3883_GPIO_MODE_LNA_A_SHIFT) +#define RT3883_GPIO_MODE_LNA_A_GPIO 0x3 +#define RT3883_GPIO_MODE_LNA_A _RT3883_GPIO_MODE_LNA_A(RT3883_GPIO_MODE_LNA_A_MASK) +#define RT3883_GPIO_MODE_LNA_G_SHIFT 18 +#define RT3883_GPIO_MODE_LNA_G_MASK 0x3 +#define _RT3883_GPIO_MODE_LNA_G(_x) ((_x) << RT3883_GPIO_MODE_LNA_G_SHIFT) +#define RT3883_GPIO_MODE_LNA_G_GPIO 0x3 +#define RT3883_GPIO_MODE_LNA_G _RT3883_GPIO_MODE_LNA_G(RT3883_GPIO_MODE_LNA_G_MASK) + +#define RT3883_GPIO_I2C_SD 1 +#define RT3883_GPIO_I2C_SCLK 2 +#define RT3883_GPIO_SPI_CS0 3 +#define RT3883_GPIO_SPI_CLK 4 +#define RT3883_GPIO_SPI_MOSI 5 +#define RT3883_GPIO_SPI_MISO 6 +#define RT3883_GPIO_7 7 +#define RT3883_GPIO_10 10 +#define RT3883_GPIO_11 11 +#define RT3883_GPIO_14 14 +#define RT3883_GPIO_UART1_TXD 15 +#define RT3883_GPIO_UART1_RXD 16 +#define RT3883_GPIO_JTAG_TDO 17 +#define RT3883_GPIO_JTAG_TDI 18 +#define RT3883_GPIO_JTAG_TMS 19 +#define RT3883_GPIO_JTAG_TCLK 20 +#define RT3883_GPIO_JTAG_TRST_N 21 +#define RT3883_GPIO_MDIO_MDC 22 +#define RT3883_GPIO_MDIO_MDIO 23 +#define RT3883_GPIO_LNA_PE_A0 32 +#define RT3883_GPIO_LNA_PE_A1 33 +#define RT3883_GPIO_LNA_PE_A2 34 +#define RT3883_GPIO_LNA_PE_G0 35 +#define RT3883_GPIO_LNA_PE_G1 36 +#define RT3883_GPIO_LNA_PE_G2 37 +#define RT3883_GPIO_PCI_AD0 40 +#define RT3883_GPIO_PCI_AD31 71 +#define RT3883_GPIO_GE2_TXD0 72 +#define RT3883_GPIO_GE2_TXD1 73 +#define RT3883_GPIO_GE2_TXD2 74 +#define RT3883_GPIO_GE2_TXD3 75 +#define RT3883_GPIO_GE2_TXEN 76 +#define RT3883_GPIO_GE2_TXCLK 77 +#define RT3883_GPIO_GE2_RXD0 78 +#define RT3883_GPIO_GE2_RXD1 79 +#define RT3883_GPIO_GE2_RXD2 80 +#define RT3883_GPIO_GE2_RXD3 81 +#define RT3883_GPIO_GE2_RXDV 82 +#define RT3883_GPIO_GE2_RXCLK 83 +#define RT3883_GPIO_GE1_TXD0 84 +#define RT3883_GPIO_GE1_TXD1 85 +#define RT3883_GPIO_GE1_TXD2 86 +#define RT3883_GPIO_GE1_TXD3 87 +#define RT3883_GPIO_GE1_TXEN 88 +#define RT3883_GPIO_GE1_TXCLK 89 +#define RT3883_GPIO_GE1_RXD0 90 +#define RT3883_GPIO_GE1_RXD1 91 +#define RT3883_GPIO_GE1_RXD2 92 +#define RT3883_GPIO_GE1_RXD3 93 +#define RT3883_GPIO_GE1_RXDV 94 +#define RT3883_GPIO_GE1_RXCLK 95 + +#define RT3883_RSTCTRL_PCIE_PCI_PDM BIT(27) +#define RT3883_RSTCTRL_FLASH BIT(26) +#define RT3883_RSTCTRL_UDEV BIT(25) +#define RT3883_RSTCTRL_PCI BIT(24) +#define RT3883_RSTCTRL_PCIE BIT(23) +#define RT3883_RSTCTRL_UHST BIT(22) +#define RT3883_RSTCTRL_FE BIT(21) +#define RT3883_RSTCTRL_WLAN BIT(20) +#define RT3883_RSTCTRL_UART1 BIT(29) +#define RT3883_RSTCTRL_SPI BIT(18) +#define RT3883_RSTCTRL_I2S BIT(17) +#define RT3883_RSTCTRL_I2C BIT(16) +#define RT3883_RSTCTRL_NAND BIT(15) +#define RT3883_RSTCTRL_DMA BIT(14) +#define RT3883_RSTCTRL_PIO BIT(13) +#define RT3883_RSTCTRL_UART BIT(12) +#define RT3883_RSTCTRL_PCM BIT(11) +#define RT3883_RSTCTRL_MC BIT(10) +#define RT3883_RSTCTRL_INTC BIT(9) +#define RT3883_RSTCTRL_TIMER BIT(8) +#define RT3883_RSTCTRL_SYS BIT(0) + +#define RT3883_INTC_INT_SYSCTL BIT(0) +#define RT3883_INTC_INT_TIMER0 BIT(1) +#define RT3883_INTC_INT_TIMER1 BIT(2) +#define RT3883_INTC_INT_IA BIT(3) +#define RT3883_INTC_INT_PCM BIT(4) +#define RT3883_INTC_INT_UART0 BIT(5) +#define RT3883_INTC_INT_PIO BIT(6) +#define RT3883_INTC_INT_DMA BIT(7) +#define RT3883_INTC_INT_NAND BIT(8) +#define RT3883_INTC_INT_PERFC BIT(9) +#define RT3883_INTC_INT_I2S BIT(10) +#define RT3883_INTC_INT_UART1 BIT(12) +#define RT3883_INTC_INT_UHST BIT(18) +#define RT3883_INTC_INT_UDEV BIT(19) + +/* FLASH/SRAM/Codec Controller registers */ +#define RT3883_FSCC_REG_FLASH_CFG0 0x00 +#define RT3883_FSCC_REG_FLASH_CFG1 0x04 +#define RT3883_FSCC_REG_CODEC_CFG0 0x40 +#define RT3883_FSCC_REG_CODEC_CFG1 0x44 + +#define RT3883_FLASH_CFG_WIDTH_SHIFT 26 +#define RT3883_FLASH_CFG_WIDTH_MASK 0x3 +#define RT3883_FLASH_CFG_WIDTH_8BIT 0x0 +#define RT3883_FLASH_CFG_WIDTH_16BIT 0x1 +#define RT3883_FLASH_CFG_WIDTH_32BIT 0x2 + +#define RT3883_SDRAM_BASE 0x00000000 +#define RT3883_MEM_SIZE_MIN 2 +#define RT3883_MEM_SIZE_MAX 256 + +#endif /* _RT3883_REGS_H_ */ diff --git a/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h new file mode 100644 index 000000000000..181fbf4c976f --- /dev/null +++ b/arch/mips/include/asm/mach-ralink/rt3883/cpu-feature-overrides.h @@ -0,0 +1,55 @@ +/* + * Ralink RT3662/RT3883 specific CPU feature overrides + * + * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> + * + * This file was derived from: include/asm-mips/cpu-features.h + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ +#ifndef _RT3883_CPU_FEATURE_OVERRIDES_H +#define _RT3883_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_divec 1 + +#define cpu_has_prefetch 1 +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +#define cpu_has_mips16 1 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 1 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_dsp 1 +#define cpu_has_mipsmt 0 + +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 + +#endif /* _RT3883_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h index 193c0912d38e..bfbd7035d4c5 100644 --- a/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h @@ -28,7 +28,11 @@ /* #define cpu_has_prefetch ? */ #define cpu_has_mcheck 1 /* #define cpu_has_ejtag ? */ +#ifdef CONFIG_CPU_MICROMIPS +#define cpu_has_llsc 0 +#else #define cpu_has_llsc 1 +#endif /* #define cpu_has_vtag_icache ? */ /* #define cpu_has_dc_aliases ? */ /* #define cpu_has_ic_fills_f_dc ? */ diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h index 44a09a64160a..bd9746fbe4af 100644 --- a/arch/mips/include/asm/mips-boards/generic.h +++ b/arch/mips/include/asm/mips-boards/generic.h @@ -83,4 +83,7 @@ extern void mips_pcibios_init(void); #define mips_pcibios_init() do { } while (0) #endif +extern void mips_scroll_message(void); +extern void mips_display_message(const char *str); + #endif /* __ASM_MIPS_BOARDS_GENERIC_H */ diff --git a/arch/mips/include/asm/mips-boards/prom.h b/arch/mips/include/asm/mips-boards/prom.h deleted file mode 100644 index e7aed3e4ff58..000000000000 --- a/arch/mips/include/asm/mips-boards/prom.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute 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 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. - * - * ######################################################################## - * - * MIPS boards bootprom interface for the Linux kernel. - * - */ - -#ifndef _MIPS_PROM_H -#define _MIPS_PROM_H - -extern char *prom_getcmdline(void); -extern char *prom_getenv(char *name); -extern void prom_init_cmdline(void); -extern void prom_meminit(void); -extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem); -extern void mips_display_message(const char *str); -extern void mips_display_word(unsigned int num); -extern void mips_scroll_message(void); -extern int get_ethernet_addr(char *ethernet_addr); - -/* Memory descriptor management. */ -#define PROM_MAX_PMEMBLOCKS 32 -struct prom_pmemblock { - unsigned long base; /* Within KSEG0. */ - unsigned int size; /* In bytes. */ - unsigned int type; /* free or prom memory */ -}; - -#endif /* !(_MIPS_PROM_H) */ diff --git a/arch/mips/include/asm/mips_machine.h b/arch/mips/include/asm/mips_machine.h index 363bb352c7f7..9d00aebe9842 100644 --- a/arch/mips/include/asm/mips_machine.h +++ b/arch/mips/include/asm/mips_machine.h @@ -42,13 +42,9 @@ extern long __mips_machines_end; #ifdef CONFIG_MIPS_MACHINE int mips_machtype_setup(char *id) __init; void mips_machine_setup(void) __init; -void mips_set_machine_name(const char *name) __init; -char *mips_get_machine_name(void); #else static inline int mips_machtype_setup(char *id) { return 1; } static inline void mips_machine_setup(void) { } -static inline void mips_set_machine_name(const char *name) { } -static inline char *mips_get_machine_name(void) { return NULL; } #endif /* CONFIG_MIPS_MACHINE */ #endif /* __ASM_MIPS_MACHINE_H */ diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 0da44d422f5b..87e6207b05e4 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -596,6 +596,7 @@ #define MIPS_CONF3_RXI (_ULCAST_(1) << 12) #define MIPS_CONF3_ULRI (_ULCAST_(1) << 13) #define MIPS_CONF3_ISA (_ULCAST_(3) << 14) +#define MIPS_CONF3_ISA_OE (_ULCAST_(3) << 16) #define MIPS_CONF3_VZ (_ULCAST_(1) << 23) #define MIPS_CONF4_MMUSIZEEXT (_ULCAST_(255) << 0) @@ -623,6 +624,24 @@ #ifndef __ASSEMBLY__ /* + * Macros for handling the ISA mode bit for microMIPS. + */ +#define get_isa16_mode(x) ((x) & 0x1) +#define msk_isa16_mode(x) ((x) & ~0x1) +#define set_isa16_mode(x) do { (x) |= 0x1; } while(0) + +/* + * microMIPS instructions can be 16-bit or 32-bit in length. This + * returns a 1 if the instruction is 16-bit and a 0 if 32-bit. + */ +static inline int mm_insn_16bit(u16 insn) +{ + u16 opcode = (insn >> 10) & 0x7; + + return (opcode >= 1 && opcode <= 3) ? 1 : 0; +} + +/* * Functions to access the R10000 performance counters. These are basically * mfc0 and mtc0 instructions from and to coprocessor register with a 5-bit * performance counter number encoded into bits 1 ... 5 of the instruction. diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h index e81d719efcd1..820116067c10 100644 --- a/arch/mips/include/asm/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -26,10 +26,15 @@ #ifdef CONFIG_MIPS_PGD_C0_CONTEXT -#define TLBMISS_HANDLER_SETUP_PGD(pgd) \ - tlbmiss_handler_setup_pgd((unsigned long)(pgd)) - -extern void tlbmiss_handler_setup_pgd(unsigned long pgd); +#define TLBMISS_HANDLER_SETUP_PGD(pgd) \ +do { \ + void (*tlbmiss_handler_setup_pgd)(unsigned long); \ + extern u32 tlbmiss_handler_setup_pgd_array[16]; \ + \ + tlbmiss_handler_setup_pgd = \ + (__typeof__(tlbmiss_handler_setup_pgd)) tlbmiss_handler_setup_pgd_array; \ + tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \ +} while (0) #define TLBMISS_HANDLER_SETUP() \ do { \ @@ -106,15 +111,21 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) static inline void get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) { + extern void kvm_local_flush_tlb_all(void); unsigned long asid = asid_cache(cpu); if (! ((asid += ASID_INC) & ASID_MASK) ) { if (cpu_has_vtag_icache) flush_icache_all(); +#ifdef CONFIG_VIRTUALIZATION + kvm_local_flush_tlb_all(); /* start new asid cycle */ +#else local_flush_tlb_all(); /* start new asid cycle */ +#endif if (!asid) /* fix version if needed */ asid = ASID_FIRST_VERSION; } + cpu_context(cpu, mm) = asid_cache(cpu) = asid; } @@ -133,7 +144,7 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) { int i; - for_each_online_cpu(i) + for_each_possible_cpu(i) cpu_context(i, mm) = 0; return 0; diff --git a/arch/mips/include/asm/netlogic/haldefs.h b/arch/mips/include/asm/netlogic/haldefs.h index 419d8aef8569..79c7cccdc22c 100644 --- a/arch/mips/include/asm/netlogic/haldefs.h +++ b/arch/mips/include/asm/netlogic/haldefs.h @@ -35,42 +35,13 @@ #ifndef __NLM_HAL_HALDEFS_H__ #define __NLM_HAL_HALDEFS_H__ +#include <linux/irqflags.h> /* for local_irq_disable */ + /* * This file contains platform specific memory mapped IO implementation * and will provide a way to read 32/64 bit memory mapped registers in * all ABIs */ -#if !defined(CONFIG_64BIT) && defined(CONFIG_CPU_XLP) -#error "o32 compile not supported on XLP yet" -#endif -/* - * For o32 compilation, we have to disable interrupts and enable KX bit to - * access 64 bit addresses or data. - * - * We need to disable interrupts because we save just the lower 32 bits of - * registers in interrupt handling. So if we get hit by an interrupt while - * using the upper 32 bits of a register, we lose. - */ -static inline uint32_t nlm_save_flags_kx(void) -{ - return change_c0_status(ST0_KX | ST0_IE, ST0_KX); -} - -static inline uint32_t nlm_save_flags_cop2(void) -{ - return change_c0_status(ST0_CU2 | ST0_IE, ST0_CU2); -} - -static inline void nlm_restore_flags(uint32_t sr) -{ - write_c0_status(sr); -} - -/* - * The n64 implementations are simple, the o32 implementations when they - * are added, will have to disable interrupts and enable KX before doing - * 64 bit ops. - */ static inline uint32_t nlm_read_reg(uint64_t base, uint32_t reg) { @@ -87,13 +58,40 @@ nlm_write_reg(uint64_t base, uint32_t reg, uint32_t val) *addr = val; } +/* + * For o32 compilation, we have to disable interrupts to access 64 bit + * registers + * + * We need to disable interrupts because we save just the lower 32 bits of + * registers in interrupt handling. So if we get hit by an interrupt while + * using the upper 32 bits of a register, we lose. + */ + static inline uint64_t nlm_read_reg64(uint64_t base, uint32_t reg) { uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; - - return *ptr; + uint64_t val; + + if (sizeof(unsigned long) == 4) { + unsigned long flags; + + local_irq_save(flags); + __asm__ __volatile__( + ".set push" "\n\t" + ".set mips64" "\n\t" + "ld %L0, %1" "\n\t" + "dsra32 %M0, %L0, 0" "\n\t" + "sll %L0, %L0, 0" "\n\t" + ".set pop" "\n" + : "=r" (val) + : "m" (*ptr)); + local_irq_restore(flags); + } else + val = *ptr; + + return val; } static inline void @@ -102,7 +100,25 @@ nlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val) uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); volatile uint64_t *ptr = (volatile uint64_t *)(long)addr; - *ptr = val; + if (sizeof(unsigned long) == 4) { + unsigned long flags; + uint64_t tmp; + + local_irq_save(flags); + __asm__ __volatile__( + ".set push" "\n\t" + ".set mips64" "\n\t" + "dsll32 %L0, %L0, 0" "\n\t" + "dsrl32 %L0, %L0, 0" "\n\t" + "dsll32 %M0, %M0, 0" "\n\t" + "or %L0, %L0, %M0" "\n\t" + "sd %L0, %2" "\n\t" + ".set pop" "\n" + : "=r" (tmp) + : "0" (val), "m" (*ptr)); + local_irq_restore(flags); + } else + *ptr = val; } /* @@ -143,14 +159,6 @@ nlm_pcicfg_base(uint32_t devoffset) return nlm_io_base + devoffset; } -static inline uint64_t -nlm_xkphys_map_pcibar0(uint64_t pcibase) -{ - uint64_t paddr; - - paddr = nlm_read_reg(pcibase, 0x4) & ~0xfu; - return (uint64_t)0x9000000000000000 | paddr; -} #elif defined(CONFIG_CPU_XLR) static inline uint64_t diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h index 8ad2e0f81719..f299d31d7c1a 100644 --- a/arch/mips/include/asm/netlogic/mips-extns.h +++ b/arch/mips/include/asm/netlogic/mips-extns.h @@ -38,21 +38,16 @@ /* * XLR and XLP interrupt request and interrupt mask registers */ -#define read_c0_eirr() __read_64bit_c0_register($9, 6) -#define read_c0_eimr() __read_64bit_c0_register($9, 7) -#define write_c0_eirr(val) __write_64bit_c0_register($9, 6, val) - /* - * Writing EIMR in 32 bit is a special case, the lower 8 bit of the - * EIMR is shadowed in the status register, so we cannot save and - * restore status register for split read. + * NOTE: Do not save/restore flags around write_c0_eimr(). + * On non-R2 platforms the flags has part of EIMR that is shadowed in STATUS + * register. Restoring flags will overwrite the lower 8 bits of EIMR. + * + * Call with interrupts disabled. */ #define write_c0_eimr(val) \ do { \ if (sizeof(unsigned long) == 4) { \ - unsigned long __flags; \ - \ - local_irq_save(__flags); \ __asm__ __volatile__( \ ".set\tmips64\n\t" \ "dsll\t%L0, %L0, 32\n\t" \ @@ -62,8 +57,6 @@ do { \ "dmtc0\t%L0, $9, 7\n\t" \ ".set\tmips0" \ : : "r" (val)); \ - __flags = (__flags & 0xffff00ff) | (((val) & 0xff) << 8);\ - local_irq_restore(__flags); \ } else \ __write_64bit_c0_register($9, 7, (val)); \ } while (0) @@ -128,7 +121,7 @@ static inline uint64_t read_c0_eirr_and_eimr(void) uint64_t val; #ifdef CONFIG_64BIT - val = read_c0_eimr() & read_c0_eirr(); + val = __read_64bit_c0_register($9, 6) & __read_64bit_c0_register($9, 7); #else __asm__ __volatile__( ".set push\n\t" @@ -143,7 +136,6 @@ static inline uint64_t read_c0_eirr_and_eimr(void) ".set pop" : "=r" (val)); #endif - return val; } diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index 3df53017fe51..a981f4681a15 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -191,59 +191,6 @@ #define PIC_IRT_PCIE_LINK_2_INDEX 80 #define PIC_IRT_PCIE_LINK_3_INDEX 81 #define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX) -/* 78 to 81 */ -#define PIC_NUM_NA_IRTS 32 -/* 82 to 113 */ -#define PIC_IRT_NA_0_INDEX 82 -#define PIC_IRT_NA_INDEX(num) ((num) + PIC_IRT_NA_0_INDEX) -#define PIC_IRT_POE_INDEX 114 - -#define PIC_NUM_USB_IRTS 6 -#define PIC_IRT_USB_0_INDEX 115 -#define PIC_IRT_EHCI_0_INDEX 115 -#define PIC_IRT_OHCI_0_INDEX 116 -#define PIC_IRT_OHCI_1_INDEX 117 -#define PIC_IRT_EHCI_1_INDEX 118 -#define PIC_IRT_OHCI_2_INDEX 119 -#define PIC_IRT_OHCI_3_INDEX 120 -#define PIC_IRT_USB_INDEX(num) ((num) + PIC_IRT_USB_0_INDEX) -/* 115 to 120 */ -#define PIC_IRT_GDX_INDEX 121 -#define PIC_IRT_SEC_INDEX 122 -#define PIC_IRT_RSA_INDEX 123 - -#define PIC_NUM_COMP_IRTS 4 -#define PIC_IRT_COMP_0_INDEX 124 -#define PIC_IRT_COMP_INDEX(num) ((num) + PIC_IRT_COMP_0_INDEX) -/* 124 to 127 */ -#define PIC_IRT_GBU_INDEX 128 -#define PIC_IRT_ICC_0_INDEX 129 /* ICC - Inter Chip Coherency */ -#define PIC_IRT_ICC_1_INDEX 130 -#define PIC_IRT_ICC_2_INDEX 131 -#define PIC_IRT_CAM_INDEX 132 -#define PIC_IRT_UART_0_INDEX 133 -#define PIC_IRT_UART_1_INDEX 134 -#define PIC_IRT_I2C_0_INDEX 135 -#define PIC_IRT_I2C_1_INDEX 136 -#define PIC_IRT_SYS_0_INDEX 137 -#define PIC_IRT_SYS_1_INDEX 138 -#define PIC_IRT_JTAG_INDEX 139 -#define PIC_IRT_PIC_INDEX 140 -#define PIC_IRT_NBU_INDEX 141 -#define PIC_IRT_TCU_INDEX 142 -#define PIC_IRT_GCU_INDEX 143 /* GBC - Global Coherency */ -#define PIC_IRT_DMC_0_INDEX 144 -#define PIC_IRT_DMC_1_INDEX 145 - -#define PIC_NUM_GPIO_IRTS 4 -#define PIC_IRT_GPIO_0_INDEX 146 -#define PIC_IRT_GPIO_INDEX(num) ((num) + PIC_IRT_GPIO_0_INDEX) - -/* 146 to 149 */ -#define PIC_IRT_NOR_INDEX 150 -#define PIC_IRT_NAND_INDEX 151 -#define PIC_IRT_SPI_INDEX 152 -#define PIC_IRT_MMC_INDEX 153 #define PIC_CLOCK_TIMER 7 #define PIC_IRQ_BASE 8 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/usb.h b/arch/mips/include/asm/netlogic/xlp-hal/usb.h deleted file mode 100644 index a9cd350dfb6c..000000000000 --- a/arch/mips/include/asm/netlogic/xlp-hal/usb.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2003-2012 Broadcom Corporation - * All Rights Reserved - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the Broadcom - * license below: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NLM_HAL_USB_H__ -#define __NLM_HAL_USB_H__ - -#define USB_CTL_0 0x01 -#define USB_PHY_0 0x0A -#define USB_PHY_RESET 0x01 -#define USB_PHY_PORT_RESET_0 0x10 -#define USB_PHY_PORT_RESET_1 0x20 -#define USB_CONTROLLER_RESET 0x01 -#define USB_INT_STATUS 0x0E -#define USB_INT_EN 0x0F -#define USB_PHY_INTERRUPT_EN 0x01 -#define USB_OHCI_INTERRUPT_EN 0x02 -#define USB_OHCI_INTERRUPT1_EN 0x04 -#define USB_OHCI_INTERRUPT2_EN 0x08 -#define USB_CTRL_INTERRUPT_EN 0x10 - -#ifndef __ASSEMBLY__ - -#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r) -#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) -#define nlm_get_usb_pcibase(node, inst) \ - nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst)) -#define nlm_get_usb_hcd_base(node, inst) \ - nlm_xkphys_map_pcibar0(nlm_get_usb_pcibase(node, inst)) -#define nlm_get_usb_regbase(node, inst) \ - (nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) - -#endif -#endif /* __NLM_HAL_USB_H__ */ diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index eab99e536b5c..ec1ca537fbc1 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -46,7 +46,6 @@ #endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */ #include <linux/pfn.h> -#include <asm/io.h> extern void build_clear_page(void); extern void build_copy_page(void); @@ -151,6 +150,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) #endif #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) +#include <asm/io.h> /* * RELOC_HIDE was originally added by 6007b903dfe5f1d13e0c711ac2894bdd4a61b1ad diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index fdc62fb5630d..8b8f6b393363 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -8,6 +8,7 @@ #ifndef _ASM_PGTABLE_H #define _ASM_PGTABLE_H +#include <linux/mm_types.h> #include <linux/mmzone.h> #ifdef CONFIG_32BIT #include <asm/pgtable-32.h> diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 2a5fa7abb346..71686c897dea 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -44,11 +44,16 @@ extern unsigned int vced_count, vcei_count; #define SPECIAL_PAGES_SIZE PAGE_SIZE #ifdef CONFIG_32BIT +#ifdef CONFIG_KVM_GUEST +/* User space process size is limited to 1GB in KVM Guest Mode */ +#define TASK_SIZE 0x3fff8000UL +#else /* * User space process size: 2GB. This is hardcoded into a few places, * so don't change it unless you know what you are doing. */ #define TASK_SIZE 0x7fff8000UL +#endif #ifdef __KERNEL__ #define STACK_TOP_MAX TASK_SIZE diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h index 8808bf548b99..1e7e0961064b 100644 --- a/arch/mips/include/asm/prom.h +++ b/arch/mips/include/asm/prom.h @@ -48,4 +48,7 @@ extern void __dt_setup_arch(struct boot_param_header *bph); static inline void device_tree_init(void) { } #endif /* CONFIG_OF */ +extern char *mips_get_machine_name(void); +extern void mips_set_machine_name(const char *name); + #endif /* __ASM_PROM_H */ diff --git a/arch/mips/include/asm/sn/sn_private.h b/arch/mips/include/asm/sn/sn_private.h index 1a2c3025bf28..fdfae43d8b99 100644 --- a/arch/mips/include/asm/sn/sn_private.h +++ b/arch/mips/include/asm/sn/sn_private.h @@ -14,6 +14,6 @@ extern void install_cpu_nmi_handler(int slice); extern void install_ipi(void); extern void setup_replication_mask(void); extern void replicate_kernel_text(void); -extern pfn_t node_getfirstfree(cnodeid_t); +extern unsigned long node_getfirstfree(cnodeid_t); #endif /* __ASM_SN_SN_PRIVATE_H */ diff --git a/arch/mips/include/asm/sn/types.h b/arch/mips/include/asm/sn/types.h index c4813d67aec3..6d24d4e8b9ed 100644 --- a/arch/mips/include/asm/sn/types.h +++ b/arch/mips/include/asm/sn/types.h @@ -19,7 +19,6 @@ typedef signed char partid_t; /* partition ID type */ typedef signed short moduleid_t; /* user-visible module number type */ typedef signed short cmoduleid_t; /* kernel compact module id type */ typedef unsigned char clusterid_t; /* Clusterid of the cell */ -typedef unsigned long pfn_t; typedef dev_t vertex_hdl_t; /* hardware graph vertex handle */ diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h index 5130c88d6420..78d201fb6c87 100644 --- a/arch/mips/include/asm/spinlock.h +++ b/arch/mips/include/asm/spinlock.h @@ -71,7 +71,6 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) " nop \n" " srl %[my_ticket], %[ticket], 16 \n" " andi %[ticket], %[ticket], 0xffff \n" - " andi %[my_ticket], %[my_ticket], 0xffff \n" " bne %[ticket], %[my_ticket], 4f \n" " subu %[ticket], %[my_ticket], %[ticket] \n" "2: \n" @@ -105,7 +104,6 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) " beqz %[my_ticket], 1b \n" " srl %[my_ticket], %[ticket], 16 \n" " andi %[ticket], %[ticket], 0xffff \n" - " andi %[my_ticket], %[my_ticket], 0xffff \n" " bne %[ticket], %[my_ticket], 4f \n" " subu %[ticket], %[my_ticket], %[ticket] \n" "2: \n" @@ -153,7 +151,6 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock) " \n" "1: ll %[ticket], %[ticket_ptr] \n" " srl %[my_ticket], %[ticket], 16 \n" - " andi %[my_ticket], %[my_ticket], 0xffff \n" " andi %[now_serving], %[ticket], 0xffff \n" " bne %[my_ticket], %[now_serving], 3f \n" " addu %[ticket], %[ticket], %[inc] \n" @@ -178,7 +175,6 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock) " \n" "1: ll %[ticket], %[ticket_ptr] \n" " srl %[my_ticket], %[ticket], 16 \n" - " andi %[my_ticket], %[my_ticket], 0xffff \n" " andi %[now_serving], %[ticket], 0xffff \n" " bne %[my_ticket], %[now_serving], 3f \n" " addu %[ticket], %[ticket], %[inc] \n" @@ -242,25 +238,16 @@ static inline void arch_read_lock(arch_rwlock_t *rw) : "m" (rw->lock) : "memory"); } else { - __asm__ __volatile__( - " .set noreorder # arch_read_lock \n" - "1: ll %1, %2 \n" - " bltz %1, 3f \n" - " addu %1, 1 \n" - "2: sc %1, %0 \n" - " beqz %1, 1b \n" - " nop \n" - " .subsection 2 \n" - "3: ll %1, %2 \n" - " bltz %1, 3b \n" - " addu %1, 1 \n" - " b 2b \n" - " nop \n" - " .previous \n" - " .set reorder \n" - : "=m" (rw->lock), "=&r" (tmp) - : "m" (rw->lock) - : "memory"); + do { + __asm__ __volatile__( + "1: ll %1, %2 # arch_read_lock \n" + " bltz %1, 1b \n" + " addu %1, 1 \n" + "2: sc %1, %0 \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } while (unlikely(!tmp)); } smp_llsc_mb(); @@ -285,21 +272,15 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) : "m" (rw->lock) : "memory"); } else { - __asm__ __volatile__( - " .set noreorder # arch_read_unlock \n" - "1: ll %1, %2 \n" - " sub %1, 1 \n" - " sc %1, %0 \n" - " beqz %1, 2f \n" - " nop \n" - " .subsection 2 \n" - "2: b 1b \n" - " nop \n" - " .previous \n" - " .set reorder \n" - : "=m" (rw->lock), "=&r" (tmp) - : "m" (rw->lock) - : "memory"); + do { + __asm__ __volatile__( + "1: ll %1, %2 # arch_read_unlock \n" + " sub %1, 1 \n" + " sc %1, %0 \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } while (unlikely(!tmp)); } } @@ -321,25 +302,16 @@ static inline void arch_write_lock(arch_rwlock_t *rw) : "m" (rw->lock) : "memory"); } else { - __asm__ __volatile__( - " .set noreorder # arch_write_lock \n" - "1: ll %1, %2 \n" - " bnez %1, 3f \n" - " lui %1, 0x8000 \n" - "2: sc %1, %0 \n" - " beqz %1, 3f \n" - " nop \n" - " .subsection 2 \n" - "3: ll %1, %2 \n" - " bnez %1, 3b \n" - " lui %1, 0x8000 \n" - " b 2b \n" - " nop \n" - " .previous \n" - " .set reorder \n" - : "=m" (rw->lock), "=&r" (tmp) - : "m" (rw->lock) - : "memory"); + do { + __asm__ __volatile__( + "1: ll %1, %2 # arch_write_lock \n" + " bnez %1, 1b \n" + " lui %1, 0x8000 \n" + "2: sc %1, %0 \n" + : "=m" (rw->lock), "=&r" (tmp) + : "m" (rw->lock) + : "memory"); + } while (unlikely(!tmp)); } smp_llsc_mb(); @@ -424,25 +396,21 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) : "m" (rw->lock) : "memory"); } else { - __asm__ __volatile__( - " .set noreorder # arch_write_trylock \n" - " li %2, 0 \n" - "1: ll %1, %3 \n" - " bnez %1, 2f \n" - " lui %1, 0x8000 \n" - " sc %1, %0 \n" - " beqz %1, 3f \n" - " li %2, 1 \n" - "2: \n" - __WEAK_LLSC_MB - " .subsection 2 \n" - "3: b 1b \n" - " li %2, 0 \n" - " .previous \n" - " .set reorder \n" - : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) - : "m" (rw->lock) - : "memory"); + do { + __asm__ __volatile__( + " ll %1, %3 # arch_write_trylock \n" + " li %2, 0 \n" + " bnez %1, 2f \n" + " lui %1, 0x8000 \n" + " sc %1, %0 \n" + " li %2, 1 \n" + "2: \n" + : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret) + : "m" (rw->lock) + : "memory"); + } while (unlikely(!tmp)); + + smp_llsc_mb(); } return ret; diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h index c99384018161..a89d1b10d027 100644 --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -139,7 +139,7 @@ 1: move ra, k0 li k0, 3 mtc0 k0, $22 -#endif /* CONFIG_CPU_LOONGSON2F */ +#endif /* CONFIG_CPU_JUMP_WORKAROUNDS */ #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) lui k1, %hi(kernelsp) #else @@ -189,6 +189,7 @@ LONG_S $0, PT_R0(sp) mfc0 v1, CP0_STATUS LONG_S $2, PT_R2(sp) + LONG_S v1, PT_STATUS(sp) #ifdef CONFIG_MIPS_MT_SMTC /* * Ideally, these instructions would be shuffled in @@ -200,21 +201,20 @@ LONG_S k0, PT_TCSTATUS(sp) #endif /* CONFIG_MIPS_MT_SMTC */ LONG_S $4, PT_R4(sp) - LONG_S $5, PT_R5(sp) - LONG_S v1, PT_STATUS(sp) mfc0 v1, CP0_CAUSE - LONG_S $6, PT_R6(sp) - LONG_S $7, PT_R7(sp) + LONG_S $5, PT_R5(sp) LONG_S v1, PT_CAUSE(sp) + LONG_S $6, PT_R6(sp) MFC0 v1, CP0_EPC + LONG_S $7, PT_R7(sp) #ifdef CONFIG_64BIT LONG_S $8, PT_R8(sp) LONG_S $9, PT_R9(sp) #endif + LONG_S v1, PT_EPC(sp) LONG_S $25, PT_R25(sp) LONG_S $28, PT_R28(sp) LONG_S $31, PT_R31(sp) - LONG_S v1, PT_EPC(sp) ori $28, sp, _THREAD_MASK xori $28, _THREAD_MASK #ifdef CONFIG_CPU_CAVIUM_OCTEON diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 178f7924149a..895320e25662 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -58,8 +58,12 @@ struct thread_info { #define init_stack (init_thread_union.stack) /* How to get the thread information struct from C. */ -register struct thread_info *__current_thread_info __asm__("$28"); -#define current_thread_info() __current_thread_info +static inline struct thread_info *current_thread_info(void) +{ + register struct thread_info *__current_thread_info __asm__("$28"); + + return __current_thread_info; +} #endif /* !__ASSEMBLY__ */ diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h index debc8009bd58..2d7b9df4542d 100644 --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h @@ -52,13 +52,15 @@ extern int (*perf_irq)(void); */ extern unsigned int __weak get_c0_compare_int(void); extern int r4k_clockevent_init(void); +extern int smtc_clockevent_init(void); +extern int gic_clockevent_init(void); static inline int mips_clockevent_init(void) { #ifdef CONFIG_MIPS_MT_SMTC - extern int smtc_clockevent_init(void); - return smtc_clockevent_init(); +#elif defined(CONFIG_CEVT_GIC) + return (gic_clockevent_init() | r4k_clockevent_init()); #elif defined(CONFIG_CEVT_R4K) return r4k_clockevent_init(); #else @@ -69,9 +71,7 @@ static inline int mips_clockevent_init(void) /* * Initialize the count register as a clocksource */ -#ifdef CONFIG_CSRC_R4K extern int init_r4k_clocksource(void); -#endif static inline int init_mips_clocksource(void) { diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index bd87e36bf26a..f3fa3750f577 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -23,7 +23,11 @@ */ #ifdef CONFIG_32BIT -#define __UA_LIMIT 0x80000000UL +#ifdef CONFIG_KVM_GUEST +#define __UA_LIMIT 0x40000000UL +#else +#define __UA_LIMIT 0x80000000UL +#endif #define __UA_ADDR ".word" #define __UA_LA "la" @@ -55,8 +59,13 @@ extern u64 __ua_limit; * address in this range it's the process's problem, not ours :-) */ +#ifdef CONFIG_KVM_GUEST +#define KERNEL_DS ((mm_segment_t) { 0x80000000UL }) +#define USER_DS ((mm_segment_t) { 0xC0000000UL }) +#else #define KERNEL_DS ((mm_segment_t) { 0UL }) #define USER_DS ((mm_segment_t) { __UA_LIMIT }) +#endif #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -261,6 +270,7 @@ do { \ __asm__ __volatile__( \ "1: " insn " %1, %3 \n" \ "2: \n" \ + " .insn \n" \ " .section .fixup,\"ax\" \n" \ "3: li %0, %4 \n" \ " j 2b \n" \ @@ -287,7 +297,9 @@ do { \ __asm__ __volatile__( \ "1: lw %1, (%3) \n" \ "2: lw %D1, 4(%3) \n" \ - "3: .section .fixup,\"ax\" \n" \ + "3: \n" \ + " .insn \n" \ + " .section .fixup,\"ax\" \n" \ "4: li %0, %4 \n" \ " move %1, $0 \n" \ " move %D1, $0 \n" \ @@ -355,6 +367,7 @@ do { \ __asm__ __volatile__( \ "1: " insn " %z2, %3 # __put_user_asm\n" \ "2: \n" \ + " .insn \n" \ " .section .fixup,\"ax\" \n" \ "3: li %0, %4 \n" \ " j 2b \n" \ @@ -373,6 +386,7 @@ do { \ "1: sw %2, (%3) # __put_user_asm_ll32 \n" \ "2: sw %D2, 4(%3) \n" \ "3: \n" \ + " .insn \n" \ " .section .fixup,\"ax\" \n" \ "4: li %0, %4 \n" \ " j 3b \n" \ @@ -524,6 +538,7 @@ do { \ __asm__ __volatile__( \ "1: " insn " %1, %3 \n" \ "2: \n" \ + " .insn \n" \ " .section .fixup,\"ax\" \n" \ "3: li %0, %4 \n" \ " j 2b \n" \ @@ -549,7 +564,9 @@ do { \ "1: ulw %1, (%3) \n" \ "2: ulw %D1, 4(%3) \n" \ " move %0, $0 \n" \ - "3: .section .fixup,\"ax\" \n" \ + "3: \n" \ + " .insn \n" \ + " .section .fixup,\"ax\" \n" \ "4: li %0, %4 \n" \ " move %1, $0 \n" \ " move %D1, $0 \n" \ @@ -616,6 +633,7 @@ do { \ __asm__ __volatile__( \ "1: " insn " %z2, %3 # __put_user_unaligned_asm\n" \ "2: \n" \ + " .insn \n" \ " .section .fixup,\"ax\" \n" \ "3: li %0, %4 \n" \ " j 2b \n" \ @@ -634,6 +652,7 @@ do { \ "1: sw %2, (%3) # __put_user_unaligned_asm_ll32 \n" \ "2: sw %D2, 4(%3) \n" \ "3: \n" \ + " .insn \n" \ " .section .fixup,\"ax\" \n" \ "4: li %0, %4 \n" \ " j 3b \n" \ diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 058e941626a6..370d967725c2 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -6,7 +6,7 @@ * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer * Copyright (C) 2005 Maciej W. Rozycki * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2012 MIPS Technologies, Inc. + * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved. */ #include <linux/types.h> @@ -22,44 +22,75 @@ #define UASM_EXPORT_SYMBOL(sym) #endif +#define _UASM_ISA_CLASSIC 0 +#define _UASM_ISA_MICROMIPS 1 + +#ifndef UASM_ISA +#ifdef CONFIG_CPU_MICROMIPS +#define UASM_ISA _UASM_ISA_MICROMIPS +#else +#define UASM_ISA _UASM_ISA_CLASSIC +#endif +#endif + +#if (UASM_ISA == _UASM_ISA_CLASSIC) +#ifdef CONFIG_CPU_MICROMIPS +#define ISAOPC(op) CL_uasm_i##op +#define ISAFUNC(x) CL_##x +#else +#define ISAOPC(op) uasm_i##op +#define ISAFUNC(x) x +#endif +#elif (UASM_ISA == _UASM_ISA_MICROMIPS) +#ifdef CONFIG_CPU_MICROMIPS +#define ISAOPC(op) uasm_i##op +#define ISAFUNC(x) x +#else +#define ISAOPC(op) MM_uasm_i##op +#define ISAFUNC(x) MM_##x +#endif +#else +#error Unsupported micro-assembler ISA!!! +#endif + #define Ip_u1u2u3(op) \ void __uasminit \ -uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u2u1u3(op) \ void __uasminit \ -uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u3u1u2(op) \ void __uasminit \ -uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u1u2s3(op) \ void __uasminit \ -uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) +ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2s3u1(op) \ void __uasminit \ -uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c) +ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c) #define Ip_u2u1s3(op) \ void __uasminit \ -uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c) +ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2u1msbu3(op) \ void __uasminit \ -uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ +ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ unsigned int d) #define Ip_u1u2(op) \ -void __uasminit uasm_i##op(u32 **buf, unsigned int a, unsigned int b) +void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b) #define Ip_u1s2(op) \ -void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b) +void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, signed int b) -#define Ip_u1(op) void __uasminit uasm_i##op(u32 **buf, unsigned int a) +#define Ip_u1(op) void __uasminit ISAOPC(op)(u32 **buf, unsigned int a) -#define Ip_0(op) void __uasminit uasm_i##op(u32 **buf) +#define Ip_0(op) void __uasminit ISAOPC(op)(u32 **buf) Ip_u2u1s3(_addiu); Ip_u3u1u2(_addu); @@ -132,19 +163,20 @@ struct uasm_label { int lab; }; -void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid); +void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, + int lid); #ifdef CONFIG_64BIT -int uasm_in_compat_space_p(long addr); +int ISAFUNC(uasm_in_compat_space_p)(long addr); #endif -int uasm_rel_hi(long val); -int uasm_rel_lo(long val); -void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr); -void UASM_i_LA(u32 **buf, unsigned int rs, long addr); +int ISAFUNC(uasm_rel_hi)(long val); +int ISAFUNC(uasm_rel_lo)(long val); +void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr); +void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr); #define UASM_L_LA(lb) \ -static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ +static inline void __uasminit ISAFUNC(uasm_l##lb)(struct uasm_label **lab, u32 *addr) \ { \ - uasm_build_label(lab, addr, label##lb); \ + ISAFUNC(uasm_build_label)(lab, addr, label##lb); \ } /* convenience macros for instructions */ @@ -196,27 +228,27 @@ static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { if (a3 < 32) - uasm_i_drotr(p, a1, a2, a3); + ISAOPC(_drotr)(p, a1, a2, a3); else - uasm_i_drotr32(p, a1, a2, a3 - 32); + ISAOPC(_drotr32)(p, a1, a2, a3 - 32); } static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { if (a3 < 32) - uasm_i_dsll(p, a1, a2, a3); + ISAOPC(_dsll)(p, a1, a2, a3); else - uasm_i_dsll32(p, a1, a2, a3 - 32); + ISAOPC(_dsll32)(p, a1, a2, a3 - 32); } static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) { if (a3 < 32) - uasm_i_dsrl(p, a1, a2, a3); + ISAOPC(_dsrl)(p, a1, a2, a3); else - uasm_i_dsrl32(p, a1, a2, a3 - 32); + ISAOPC(_dsrl32)(p, a1, a2, a3 - 32); } /* Handle relocations. */ diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 4d078815eaa5..0f4aec2ad1e6 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -7,6 +7,7 @@ * * Copyright (C) 1996, 2000 by Ralf Baechle * Copyright (C) 2006 by Thiemo Seufer + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. */ #ifndef _UAPI_ASM_INST_H #define _UAPI_ASM_INST_H @@ -193,6 +194,282 @@ enum lx_func { }; /* + * (microMIPS) Major opcodes. + */ +enum mm_major_op { + mm_pool32a_op, mm_pool16a_op, mm_lbu16_op, mm_move16_op, + mm_addi32_op, mm_lbu32_op, mm_sb32_op, mm_lb32_op, + mm_pool32b_op, mm_pool16b_op, mm_lhu16_op, mm_andi16_op, + mm_addiu32_op, mm_lhu32_op, mm_sh32_op, mm_lh32_op, + mm_pool32i_op, mm_pool16c_op, mm_lwsp16_op, mm_pool16d_op, + mm_ori32_op, mm_pool32f_op, mm_reserved1_op, mm_reserved2_op, + mm_pool32c_op, mm_lwgp16_op, mm_lw16_op, mm_pool16e_op, + mm_xori32_op, mm_jals32_op, mm_addiupc_op, mm_reserved3_op, + mm_reserved4_op, mm_pool16f_op, mm_sb16_op, mm_beqz16_op, + mm_slti32_op, mm_beq32_op, mm_swc132_op, mm_lwc132_op, + mm_reserved5_op, mm_reserved6_op, mm_sh16_op, mm_bnez16_op, + mm_sltiu32_op, mm_bne32_op, mm_sdc132_op, mm_ldc132_op, + mm_reserved7_op, mm_reserved8_op, mm_swsp16_op, mm_b16_op, + mm_andi32_op, mm_j32_op, mm_sd32_op, mm_ld32_op, + mm_reserved11_op, mm_reserved12_op, mm_sw16_op, mm_li16_op, + mm_jalx32_op, mm_jal32_op, mm_sw32_op, mm_lw32_op, +}; + +/* + * (microMIPS) POOL32I minor opcodes. + */ +enum mm_32i_minor_op { + mm_bltz_op, mm_bltzal_op, mm_bgez_op, mm_bgezal_op, + mm_blez_op, mm_bnezc_op, mm_bgtz_op, mm_beqzc_op, + mm_tlti_op, mm_tgei_op, mm_tltiu_op, mm_tgeiu_op, + mm_tnei_op, mm_lui_op, mm_teqi_op, mm_reserved13_op, + mm_synci_op, mm_bltzals_op, mm_reserved14_op, mm_bgezals_op, + mm_bc2f_op, mm_bc2t_op, mm_reserved15_op, mm_reserved16_op, + mm_reserved17_op, mm_reserved18_op, mm_bposge64_op, mm_bposge32_op, + mm_bc1f_op, mm_bc1t_op, mm_reserved19_op, mm_reserved20_op, + mm_bc1any2f_op, mm_bc1any2t_op, mm_bc1any4f_op, mm_bc1any4t_op, +}; + +/* + * (microMIPS) POOL32A minor opcodes. + */ +enum mm_32a_minor_op { + mm_sll32_op = 0x000, + mm_ins_op = 0x00c, + mm_ext_op = 0x02c, + mm_pool32axf_op = 0x03c, + mm_srl32_op = 0x040, + mm_sra_op = 0x080, + mm_rotr_op = 0x0c0, + mm_lwxs_op = 0x118, + mm_addu32_op = 0x150, + mm_subu32_op = 0x1d0, + mm_and_op = 0x250, + mm_or32_op = 0x290, + mm_xor32_op = 0x310, +}; + +/* + * (microMIPS) POOL32B functions. + */ +enum mm_32b_func { + mm_lwc2_func = 0x0, + mm_lwp_func = 0x1, + mm_ldc2_func = 0x2, + mm_ldp_func = 0x4, + mm_lwm32_func = 0x5, + mm_cache_func = 0x6, + mm_ldm_func = 0x7, + mm_swc2_func = 0x8, + mm_swp_func = 0x9, + mm_sdc2_func = 0xa, + mm_sdp_func = 0xc, + mm_swm32_func = 0xd, + mm_sdm_func = 0xf, +}; + +/* + * (microMIPS) POOL32C functions. + */ +enum mm_32c_func { + mm_pref_func = 0x2, + mm_ll_func = 0x3, + mm_swr_func = 0x9, + mm_sc_func = 0xb, + mm_lwu_func = 0xe, +}; + +/* + * (microMIPS) POOL32AXF minor opcodes. + */ +enum mm_32axf_minor_op { + mm_mfc0_op = 0x003, + mm_mtc0_op = 0x00b, + mm_tlbp_op = 0x00d, + mm_jalr_op = 0x03c, + mm_tlbr_op = 0x04d, + mm_jalrhb_op = 0x07c, + mm_tlbwi_op = 0x08d, + mm_tlbwr_op = 0x0cd, + mm_jalrs_op = 0x13c, + mm_jalrshb_op = 0x17c, + mm_syscall_op = 0x22d, + mm_eret_op = 0x3cd, +}; + +/* + * (microMIPS) POOL32F minor opcodes. + */ +enum mm_32f_minor_op { + mm_32f_00_op = 0x00, + mm_32f_01_op = 0x01, + mm_32f_02_op = 0x02, + mm_32f_10_op = 0x08, + mm_32f_11_op = 0x09, + mm_32f_12_op = 0x0a, + mm_32f_20_op = 0x10, + mm_32f_30_op = 0x18, + mm_32f_40_op = 0x20, + mm_32f_41_op = 0x21, + mm_32f_42_op = 0x22, + mm_32f_50_op = 0x28, + mm_32f_51_op = 0x29, + mm_32f_52_op = 0x2a, + mm_32f_60_op = 0x30, + mm_32f_70_op = 0x38, + mm_32f_73_op = 0x3b, + mm_32f_74_op = 0x3c, +}; + +/* + * (microMIPS) POOL32F secondary minor opcodes. + */ +enum mm_32f_10_minor_op { + mm_lwxc1_op = 0x1, + mm_swxc1_op, + mm_ldxc1_op, + mm_sdxc1_op, + mm_luxc1_op, + mm_suxc1_op, +}; + +enum mm_32f_func { + mm_lwxc1_func = 0x048, + mm_swxc1_func = 0x088, + mm_ldxc1_func = 0x0c8, + mm_sdxc1_func = 0x108, +}; + +/* + * (microMIPS) POOL32F secondary minor opcodes. + */ +enum mm_32f_40_minor_op { + mm_fmovf_op, + mm_fmovt_op, +}; + +/* + * (microMIPS) POOL32F secondary minor opcodes. + */ +enum mm_32f_60_minor_op { + mm_fadd_op, + mm_fsub_op, + mm_fmul_op, + mm_fdiv_op, +}; + +/* + * (microMIPS) POOL32F secondary minor opcodes. + */ +enum mm_32f_70_minor_op { + mm_fmovn_op, + mm_fmovz_op, +}; + +/* + * (microMIPS) POOL32FXF secondary minor opcodes for POOL32F. + */ +enum mm_32f_73_minor_op { + mm_fmov0_op = 0x01, + mm_fcvtl_op = 0x04, + mm_movf0_op = 0x05, + mm_frsqrt_op = 0x08, + mm_ffloorl_op = 0x0c, + mm_fabs0_op = 0x0d, + mm_fcvtw_op = 0x24, + mm_movt0_op = 0x25, + mm_fsqrt_op = 0x28, + mm_ffloorw_op = 0x2c, + mm_fneg0_op = 0x2d, + mm_cfc1_op = 0x40, + mm_frecip_op = 0x48, + mm_fceill_op = 0x4c, + mm_fcvtd0_op = 0x4d, + mm_ctc1_op = 0x60, + mm_fceilw_op = 0x6c, + mm_fcvts0_op = 0x6d, + mm_mfc1_op = 0x80, + mm_fmov1_op = 0x81, + mm_movf1_op = 0x85, + mm_ftruncl_op = 0x8c, + mm_fabs1_op = 0x8d, + mm_mtc1_op = 0xa0, + mm_movt1_op = 0xa5, + mm_ftruncw_op = 0xac, + mm_fneg1_op = 0xad, + mm_froundl_op = 0xcc, + mm_fcvtd1_op = 0xcd, + mm_froundw_op = 0xec, + mm_fcvts1_op = 0xed, +}; + +/* + * (microMIPS) POOL16C minor opcodes. + */ +enum mm_16c_minor_op { + mm_lwm16_op = 0x04, + mm_swm16_op = 0x05, + mm_jr16_op = 0x18, + mm_jrc_op = 0x1a, + mm_jalr16_op = 0x1c, + mm_jalrs16_op = 0x1e, +}; + +/* + * (microMIPS) POOL16D minor opcodes. + */ +enum mm_16d_minor_op { + mm_addius5_func, + mm_addiusp_func, +}; + +/* + * (MIPS16e) opcodes. + */ +enum MIPS16e_ops { + MIPS16e_jal_op = 003, + MIPS16e_ld_op = 007, + MIPS16e_i8_op = 014, + MIPS16e_sd_op = 017, + MIPS16e_lb_op = 020, + MIPS16e_lh_op = 021, + MIPS16e_lwsp_op = 022, + MIPS16e_lw_op = 023, + MIPS16e_lbu_op = 024, + MIPS16e_lhu_op = 025, + MIPS16e_lwpc_op = 026, + MIPS16e_lwu_op = 027, + MIPS16e_sb_op = 030, + MIPS16e_sh_op = 031, + MIPS16e_swsp_op = 032, + MIPS16e_sw_op = 033, + MIPS16e_rr_op = 035, + MIPS16e_extend_op = 036, + MIPS16e_i64_op = 037, +}; + +enum MIPS16e_i64_func { + MIPS16e_ldsp_func, + MIPS16e_sdsp_func, + MIPS16e_sdrasp_func, + MIPS16e_dadjsp_func, + MIPS16e_ldpc_func, +}; + +enum MIPS16e_rr_func { + MIPS16e_jr_func, +}; + +enum MIPS6e_i8_func { + MIPS16e_swrasp_func = 02, +}; + +/* + * (microMIPS & MIPS16e) NOP instruction. + */ +#define MM_NOP16 0x0c00 + +/* * Damn ... bitfields depend from byteorder :-( */ #ifdef __MIPSEB__ @@ -311,6 +588,262 @@ struct v_format { /* MDMX vector format */ ;))))))) }; +/* + * microMIPS instruction formats (32-bit length) + * + * NOTE: + * Parenthesis denote whether the format is a microMIPS instruction or + * if it is MIPS32 instruction re-encoded for use in the microMIPS ASE. + */ +struct fb_format { /* FPU branch format (MIPS32) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int bc : 5, + BITFIELD_FIELD(unsigned int cc : 3, + BITFIELD_FIELD(unsigned int flag : 2, + BITFIELD_FIELD(signed int simmediate : 16, + ;))))) +}; + +struct fp0_format { /* FPU multiply and add format (MIPS32) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int fmt : 5, + BITFIELD_FIELD(unsigned int ft : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int fd : 5, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))) +}; + +struct mm_fp0_format { /* FPU multipy and add format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int ft : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int fd : 5, + BITFIELD_FIELD(unsigned int fmt : 3, + BITFIELD_FIELD(unsigned int op : 2, + BITFIELD_FIELD(unsigned int func : 6, + ;))))))) +}; + +struct fp1_format { /* FPU mfc1 and cfc1 format (MIPS32) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int op : 5, + BITFIELD_FIELD(unsigned int rt : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int fd : 5, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))) +}; + +struct mm_fp1_format { /* FPU mfc1 and cfc1 format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rt : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int fmt : 2, + BITFIELD_FIELD(unsigned int op : 8, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))) +}; + +struct mm_fp2_format { /* FPU movt and movf format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int fd : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int cc : 3, + BITFIELD_FIELD(unsigned int zero : 2, + BITFIELD_FIELD(unsigned int fmt : 2, + BITFIELD_FIELD(unsigned int op : 3, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))))) +}; + +struct mm_fp3_format { /* FPU abs and neg format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rt : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int fmt : 3, + BITFIELD_FIELD(unsigned int op : 7, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))) +}; + +struct mm_fp4_format { /* FPU c.cond format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rt : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int cc : 3, + BITFIELD_FIELD(unsigned int fmt : 3, + BITFIELD_FIELD(unsigned int cond : 4, + BITFIELD_FIELD(unsigned int func : 6, + ;))))))) +}; + +struct mm_fp5_format { /* FPU lwxc1 and swxc1 format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int index : 5, + BITFIELD_FIELD(unsigned int base : 5, + BITFIELD_FIELD(unsigned int fd : 5, + BITFIELD_FIELD(unsigned int op : 5, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))) +}; + +struct fp6_format { /* FPU madd and msub format (MIPS IV) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int fr : 5, + BITFIELD_FIELD(unsigned int ft : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int fd : 5, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))) +}; + +struct mm_fp6_format { /* FPU madd and msub format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int ft : 5, + BITFIELD_FIELD(unsigned int fs : 5, + BITFIELD_FIELD(unsigned int fd : 5, + BITFIELD_FIELD(unsigned int fr : 5, + BITFIELD_FIELD(unsigned int func : 6, + ;)))))) +}; + +struct mm_i_format { /* Immediate format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rt : 5, + BITFIELD_FIELD(unsigned int rs : 5, + BITFIELD_FIELD(signed int simmediate : 16, + ;)))) +}; + +struct mm_m_format { /* Multi-word load/store format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rd : 5, + BITFIELD_FIELD(unsigned int base : 5, + BITFIELD_FIELD(unsigned int func : 4, + BITFIELD_FIELD(signed int simmediate : 12, + ;))))) +}; + +struct mm_x_format { /* Scaled indexed load format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int index : 5, + BITFIELD_FIELD(unsigned int base : 5, + BITFIELD_FIELD(unsigned int rd : 5, + BITFIELD_FIELD(unsigned int func : 11, + ;))))) +}; + +/* + * microMIPS instruction formats (16-bit length) + */ +struct mm_b0_format { /* Unconditional branch format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(signed int simmediate : 10, + BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + ;))) +}; + +struct mm_b1_format { /* Conditional branch format (microMIPS) */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rs : 3, + BITFIELD_FIELD(signed int simmediate : 7, + BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + ;)))) +}; + +struct mm16_m_format { /* Multi-word load/store format */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int func : 4, + BITFIELD_FIELD(unsigned int rlist : 2, + BITFIELD_FIELD(unsigned int imm : 4, + BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + ;))))) +}; + +struct mm16_rb_format { /* Signed immediate format */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rt : 3, + BITFIELD_FIELD(unsigned int base : 3, + BITFIELD_FIELD(signed int simmediate : 4, + BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + ;))))) +}; + +struct mm16_r3_format { /* Load from global pointer format */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rt : 3, + BITFIELD_FIELD(signed int simmediate : 7, + BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + ;)))) +}; + +struct mm16_r5_format { /* Load/store from stack pointer format */ + BITFIELD_FIELD(unsigned int opcode : 6, + BITFIELD_FIELD(unsigned int rt : 5, + BITFIELD_FIELD(signed int simmediate : 5, + BITFIELD_FIELD(unsigned int : 16, /* Ignored */ + ;)))) +}; + +/* + * MIPS16e instruction formats (16-bit length) + */ +struct m16e_rr { + BITFIELD_FIELD(unsigned int opcode : 5, + BITFIELD_FIELD(unsigned int rx : 3, + BITFIELD_FIELD(unsigned int nd : 1, + BITFIELD_FIELD(unsigned int l : 1, + BITFIELD_FIELD(unsigned int ra : 1, + BITFIELD_FIELD(unsigned int func : 5, + ;)))))) +}; + +struct m16e_jal { + BITFIELD_FIELD(unsigned int opcode : 5, + BITFIELD_FIELD(unsigned int x : 1, + BITFIELD_FIELD(unsigned int imm20_16 : 5, + BITFIELD_FIELD(signed int imm25_21 : 5, + ;)))) +}; + +struct m16e_i64 { + BITFIELD_FIELD(unsigned int opcode : 5, + BITFIELD_FIELD(unsigned int func : 3, + BITFIELD_FIELD(unsigned int imm : 8, + ;))) +}; + +struct m16e_ri64 { + BITFIELD_FIELD(unsigned int opcode : 5, + BITFIELD_FIELD(unsigned int func : 3, + BITFIELD_FIELD(unsigned int ry : 3, + BITFIELD_FIELD(unsigned int imm : 5, + ;)))) +}; + +struct m16e_ri { + BITFIELD_FIELD(unsigned int opcode : 5, + BITFIELD_FIELD(unsigned int rx : 3, + BITFIELD_FIELD(unsigned int imm : 8, + ;))) +}; + +struct m16e_rri { + BITFIELD_FIELD(unsigned int opcode : 5, + BITFIELD_FIELD(unsigned int rx : 3, + BITFIELD_FIELD(unsigned int ry : 3, + BITFIELD_FIELD(unsigned int imm : 5, + ;)))) +}; + +struct m16e_i8 { + BITFIELD_FIELD(unsigned int opcode : 5, + BITFIELD_FIELD(unsigned int func : 3, + BITFIELD_FIELD(unsigned int imm : 8, + ;))) +}; + union mips_instruction { unsigned int word; unsigned short halfword[2]; @@ -326,6 +859,37 @@ union mips_instruction { struct b_format b_format; struct ps_format ps_format; struct v_format v_format; + struct fb_format fb_format; + struct fp0_format fp0_format; + struct mm_fp0_format mm_fp0_format; + struct fp1_format fp1_format; + struct mm_fp1_format mm_fp1_format; + struct mm_fp2_format mm_fp2_format; + struct mm_fp3_format mm_fp3_format; + struct mm_fp4_format mm_fp4_format; + struct mm_fp5_format mm_fp5_format; + struct fp6_format fp6_format; + struct mm_fp6_format mm_fp6_format; + struct mm_i_format mm_i_format; + struct mm_m_format mm_m_format; + struct mm_x_format mm_x_format; + struct mm_b0_format mm_b0_format; + struct mm_b1_format mm_b1_format; + struct mm16_m_format mm16_m_format ; + struct mm16_rb_format mm16_rb_format; + struct mm16_r3_format mm16_r3_format; + struct mm16_r5_format mm16_r5_format; +}; + +union mips16e_instruction { + unsigned int full : 16; + struct m16e_rr rr; + struct m16e_jal jal; + struct m16e_i64 i64; + struct m16e_ri64 ri64; + struct m16e_ri ri; + struct m16e_rri rri; + struct m16e_i8 i8; }; #endif /* _UAPI_ASM_INST_H */ diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 520a908d45d6..6ad9e04bdf62 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -5,7 +5,7 @@ extra-y := head.o vmlinux.lds obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ - ptrace.o reset.o setup.o signal.o syscall.o \ + prom.o ptrace.o reset.o setup.o signal.o syscall.o \ time.o topology.o traps.o unaligned.o watch.o vdso.o ifdef CONFIG_FUNCTION_TRACER @@ -19,15 +19,16 @@ obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o obj-$(CONFIG_MIPS_MT_SMTC) += cevt-smtc.o obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o +obj-$(CONFIG_CEVT_GIC) += cevt-gic.o obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o +obj-$(CONFIG_CSRC_GIC) += csrc-gic.o obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o obj-$(CONFIG_CSRC_POWERTV) += csrc-powertv.o obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o -obj-$(CONFIG_CSRC_GIC) += csrc-gic.o obj-$(CONFIG_SYNC_R4K) += sync-r4k.o obj-$(CONFIG_STACKTRACE) += stacktrace.o @@ -86,8 +87,6 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o -obj-$(CONFIG_OF) += prom.o - CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 50285b2c7ffe..0845091ba480 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -17,6 +17,8 @@ #include <asm/ptrace.h> #include <asm/processor.h> +#include <linux/kvm_host.h> + void output_ptreg_defines(void) { COMMENT("MIPS pt_regs offsets."); @@ -328,3 +330,67 @@ void output_pbe_defines(void) BLANK(); } #endif + +void output_kvm_defines(void) +{ + COMMENT(" KVM/MIPS Specfic offsets. "); + DEFINE(VCPU_ARCH_SIZE, sizeof(struct kvm_vcpu_arch)); + OFFSET(VCPU_RUN, kvm_vcpu, run); + OFFSET(VCPU_HOST_ARCH, kvm_vcpu, arch); + + OFFSET(VCPU_HOST_EBASE, kvm_vcpu_arch, host_ebase); + OFFSET(VCPU_GUEST_EBASE, kvm_vcpu_arch, guest_ebase); + + OFFSET(VCPU_HOST_STACK, kvm_vcpu_arch, host_stack); + OFFSET(VCPU_HOST_GP, kvm_vcpu_arch, host_gp); + + OFFSET(VCPU_HOST_CP0_BADVADDR, kvm_vcpu_arch, host_cp0_badvaddr); + OFFSET(VCPU_HOST_CP0_CAUSE, kvm_vcpu_arch, host_cp0_cause); + OFFSET(VCPU_HOST_EPC, kvm_vcpu_arch, host_cp0_epc); + OFFSET(VCPU_HOST_ENTRYHI, kvm_vcpu_arch, host_cp0_entryhi); + + OFFSET(VCPU_GUEST_INST, kvm_vcpu_arch, guest_inst); + + OFFSET(VCPU_R0, kvm_vcpu_arch, gprs[0]); + OFFSET(VCPU_R1, kvm_vcpu_arch, gprs[1]); + OFFSET(VCPU_R2, kvm_vcpu_arch, gprs[2]); + OFFSET(VCPU_R3, kvm_vcpu_arch, gprs[3]); + OFFSET(VCPU_R4, kvm_vcpu_arch, gprs[4]); + OFFSET(VCPU_R5, kvm_vcpu_arch, gprs[5]); + OFFSET(VCPU_R6, kvm_vcpu_arch, gprs[6]); + OFFSET(VCPU_R7, kvm_vcpu_arch, gprs[7]); + OFFSET(VCPU_R8, kvm_vcpu_arch, gprs[8]); + OFFSET(VCPU_R9, kvm_vcpu_arch, gprs[9]); + OFFSET(VCPU_R10, kvm_vcpu_arch, gprs[10]); + OFFSET(VCPU_R11, kvm_vcpu_arch, gprs[11]); + OFFSET(VCPU_R12, kvm_vcpu_arch, gprs[12]); + OFFSET(VCPU_R13, kvm_vcpu_arch, gprs[13]); + OFFSET(VCPU_R14, kvm_vcpu_arch, gprs[14]); + OFFSET(VCPU_R15, kvm_vcpu_arch, gprs[15]); + OFFSET(VCPU_R16, kvm_vcpu_arch, gprs[16]); + OFFSET(VCPU_R17, kvm_vcpu_arch, gprs[17]); + OFFSET(VCPU_R18, kvm_vcpu_arch, gprs[18]); + OFFSET(VCPU_R19, kvm_vcpu_arch, gprs[19]); + OFFSET(VCPU_R20, kvm_vcpu_arch, gprs[20]); + OFFSET(VCPU_R21, kvm_vcpu_arch, gprs[21]); + OFFSET(VCPU_R22, kvm_vcpu_arch, gprs[22]); + OFFSET(VCPU_R23, kvm_vcpu_arch, gprs[23]); + OFFSET(VCPU_R24, kvm_vcpu_arch, gprs[24]); + OFFSET(VCPU_R25, kvm_vcpu_arch, gprs[25]); + OFFSET(VCPU_R26, kvm_vcpu_arch, gprs[26]); + OFFSET(VCPU_R27, kvm_vcpu_arch, gprs[27]); + OFFSET(VCPU_R28, kvm_vcpu_arch, gprs[28]); + OFFSET(VCPU_R29, kvm_vcpu_arch, gprs[29]); + OFFSET(VCPU_R30, kvm_vcpu_arch, gprs[30]); + OFFSET(VCPU_R31, kvm_vcpu_arch, gprs[31]); + OFFSET(VCPU_LO, kvm_vcpu_arch, lo); + OFFSET(VCPU_HI, kvm_vcpu_arch, hi); + OFFSET(VCPU_PC, kvm_vcpu_arch, pc); + OFFSET(VCPU_COP0, kvm_vcpu_arch, cop0); + OFFSET(VCPU_GUEST_KERNEL_ASID, kvm_vcpu_arch, guest_kernel_asid); + OFFSET(VCPU_GUEST_USER_ASID, kvm_vcpu_arch, guest_user_asid); + + OFFSET(COP0_TLB_HI, mips_coproc, reg[MIPS_CP0_TLB_HI][0]); + OFFSET(COP0_STATUS, mips_coproc, reg[MIPS_CP0_STATUS][0]); + BLANK(); +} diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index 556a4357d7fc..97c5a1668e53 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -48,7 +48,11 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; __res; \ }) +#ifdef CONFIG_KVM_GUEST +#define TASK32_SIZE 0x3fff8000UL +#else #define TASK32_SIZE 0x7fff8000UL +#endif #undef ELF_ET_DYN_BASE #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 83ffe950f710..46c2ad0703a0 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -14,10 +14,186 @@ #include <asm/cpu.h> #include <asm/cpu-features.h> #include <asm/fpu.h> +#include <asm/fpu_emulator.h> #include <asm/inst.h> #include <asm/ptrace.h> #include <asm/uaccess.h> +/* + * Calculate and return exception PC in case of branch delay slot + * for microMIPS and MIPS16e. It does not clear the ISA mode bit. + */ +int __isa_exception_epc(struct pt_regs *regs) +{ + unsigned short inst; + long epc = regs->cp0_epc; + + /* Calculate exception PC in branch delay slot. */ + if (__get_user(inst, (u16 __user *) msk_isa16_mode(epc))) { + /* This should never happen because delay slot was checked. */ + force_sig(SIGSEGV, current); + return epc; + } + if (cpu_has_mips16) { + if (((union mips16e_instruction)inst).ri.opcode + == MIPS16e_jal_op) + epc += 4; + else + epc += 2; + } else if (mm_insn_16bit(inst)) + epc += 2; + else + epc += 4; + + return epc; +} + +/* + * Compute return address and emulate branch in microMIPS mode after an + * exception only. It does not handle compact branches/jumps and cannot + * be used in interrupt context. (Compact branches/jumps do not cause + * exceptions.) + */ +int __microMIPS_compute_return_epc(struct pt_regs *regs) +{ + u16 __user *pc16; + u16 halfword; + unsigned int word; + unsigned long contpc; + struct mm_decoded_insn mminsn = { 0 }; + + mminsn.micro_mips_mode = 1; + + /* This load never faults. */ + pc16 = (unsigned short __user *)msk_isa16_mode(regs->cp0_epc); + __get_user(halfword, pc16); + pc16++; + contpc = regs->cp0_epc + 2; + word = ((unsigned int)halfword << 16); + mminsn.pc_inc = 2; + + if (!mm_insn_16bit(halfword)) { + __get_user(halfword, pc16); + pc16++; + contpc = regs->cp0_epc + 4; + mminsn.pc_inc = 4; + word |= halfword; + } + mminsn.insn = word; + + if (get_user(halfword, pc16)) + goto sigsegv; + mminsn.next_pc_inc = 2; + word = ((unsigned int)halfword << 16); + + if (!mm_insn_16bit(halfword)) { + pc16++; + if (get_user(halfword, pc16)) + goto sigsegv; + mminsn.next_pc_inc = 4; + word |= halfword; + } + mminsn.next_insn = word; + + mm_isBranchInstr(regs, mminsn, &contpc); + + regs->cp0_epc = contpc; + + return 0; + +sigsegv: + force_sig(SIGSEGV, current); + return -EFAULT; +} + +/* + * Compute return address and emulate branch in MIPS16e mode after an + * exception only. It does not handle compact branches/jumps and cannot + * be used in interrupt context. (Compact branches/jumps do not cause + * exceptions.) + */ +int __MIPS16e_compute_return_epc(struct pt_regs *regs) +{ + u16 __user *addr; + union mips16e_instruction inst; + u16 inst2; + u32 fullinst; + long epc; + + epc = regs->cp0_epc; + + /* Read the instruction. */ + addr = (u16 __user *)msk_isa16_mode(epc); + if (__get_user(inst.full, addr)) { + force_sig(SIGSEGV, current); + return -EFAULT; + } + + switch (inst.ri.opcode) { + case MIPS16e_extend_op: + regs->cp0_epc += 4; + return 0; + + /* + * JAL and JALX in MIPS16e mode + */ + case MIPS16e_jal_op: + addr += 1; + if (__get_user(inst2, addr)) { + force_sig(SIGSEGV, current); + return -EFAULT; + } + fullinst = ((unsigned)inst.full << 16) | inst2; + regs->regs[31] = epc + 6; + epc += 4; + epc >>= 28; + epc <<= 28; + /* + * JAL:5 X:1 TARGET[20-16]:5 TARGET[25:21]:5 TARGET[15:0]:16 + * + * ......TARGET[15:0].................TARGET[20:16]........... + * ......TARGET[25:21] + */ + epc |= + ((fullinst & 0xffff) << 2) | ((fullinst & 0x3e00000) >> 3) | + ((fullinst & 0x1f0000) << 7); + if (!inst.jal.x) + set_isa16_mode(epc); /* Set ISA mode bit. */ + regs->cp0_epc = epc; + return 0; + + /* + * J(AL)R(C) + */ + case MIPS16e_rr_op: + if (inst.rr.func == MIPS16e_jr_func) { + + if (inst.rr.ra) + regs->cp0_epc = regs->regs[31]; + else + regs->cp0_epc = + regs->regs[reg16to32[inst.rr.rx]]; + + if (inst.rr.l) { + if (inst.rr.nd) + regs->regs[31] = epc + 2; + else + regs->regs[31] = epc + 4; + } + return 0; + } + break; + } + + /* + * All other cases have no branch delay slot and are 16-bits. + * Branches do not cause an exception. + */ + regs->cp0_epc += 2; + + return 0; +} + /** * __compute_return_epc_for_insn - Computes the return address and do emulate * branch simulation, if required. @@ -129,6 +305,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, epc <<= 28; epc |= (insn.j_format.target << 2); regs->cp0_epc = epc; + if (insn.i_format.opcode == jalx_op) + set_isa16_mode(regs->cp0_epc); break; /* diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c new file mode 100644 index 000000000000..730eaf92c018 --- /dev/null +++ b/arch/mips/kernel/cevt-gic.c @@ -0,0 +1,104 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Imagination Technologies Ltd. + */ +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/percpu.h> +#include <linux/smp.h> +#include <linux/irq.h> + +#include <asm/time.h> +#include <asm/gic.h> +#include <asm/mips-boards/maltaint.h> + +DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device); +int gic_timer_irq_installed; + + +static int gic_next_event(unsigned long delta, struct clock_event_device *evt) +{ + u64 cnt; + int res; + + cnt = gic_read_count(); + cnt += (u64)delta; + gic_write_compare(cnt); + res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0; + return res; +} + +void gic_set_clock_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + /* Nothing to do ... */ +} + +irqreturn_t gic_compare_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd; + int cpu = smp_processor_id(); + + gic_write_compare(gic_read_compare()); + cd = &per_cpu(gic_clockevent_device, cpu); + cd->event_handler(cd); + return IRQ_HANDLED; +} + +struct irqaction gic_compare_irqaction = { + .handler = gic_compare_interrupt, + .flags = IRQF_PERCPU | IRQF_TIMER, + .name = "timer", +}; + + +void gic_event_handler(struct clock_event_device *dev) +{ +} + +int __cpuinit gic_clockevent_init(void) +{ + unsigned int cpu = smp_processor_id(); + struct clock_event_device *cd; + unsigned int irq; + + if (!cpu_has_counter || !gic_frequency) + return -ENXIO; + + irq = MIPS_GIC_IRQ_BASE; + + cd = &per_cpu(gic_clockevent_device, cpu); + + cd->name = "MIPS GIC"; + cd->features = CLOCK_EVT_FEAT_ONESHOT; + + clockevent_set_clock(cd, gic_frequency); + + /* Calculate the min / max delta */ + cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); + cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + + cd->rating = 300; + cd->irq = irq; + cd->cpumask = cpumask_of(cpu); + cd->set_next_event = gic_next_event; + cd->set_mode = gic_set_clock_mode; + cd->event_handler = gic_event_handler; + + clockevents_register_device(cd); + + GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_MAP), 0x80000002); + GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_SMASK), GIC_VPE_SMASK_CMP_MSK); + + if (gic_timer_irq_installed) + return 0; + + gic_timer_irq_installed = 1; + + setup_irq(irq, &gic_compare_irqaction); + irq_set_handler(irq, handle_percpu_irq); + return 0; +} diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 07b847d77f5d..02033eaf8825 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -23,7 +23,6 @@ */ #ifndef CONFIG_MIPS_MT_SMTC - static int mips_next_event(unsigned long delta, struct clock_event_device *evt) { @@ -49,7 +48,6 @@ DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); int cp0_timer_irq_installed; #ifndef CONFIG_MIPS_MT_SMTC - irqreturn_t c0_compare_interrupt(int irq, void *dev_id) { const int r2 = cpu_has_mips_r2; @@ -74,6 +72,9 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id) /* Clear Count/Compare Interrupt */ write_c0_compare(read_c0_compare()); cd = &per_cpu(mips_clockevent_device, cpu); +#ifdef CONFIG_CEVT_GIC + if (!gic_present) +#endif cd->event_handler(cd); } @@ -118,6 +119,10 @@ int c0_compare_int_usable(void) unsigned int delta; unsigned int cnt; +#ifdef CONFIG_KVM_GUEST + return 1; +#endif + /* * IP7 already pending? Try to clear it by acking the timer. */ @@ -166,7 +171,6 @@ int c0_compare_int_usable(void) } #ifndef CONFIG_MIPS_MT_SMTC - int __cpuinit r4k_clockevent_init(void) { unsigned int cpu = smp_processor_id(); @@ -206,6 +210,9 @@ int __cpuinit r4k_clockevent_init(void) cd->set_mode = mips_set_clock_mode; cd->event_handler = mips_event_handler; +#ifdef CONFIG_CEVT_GIC + if (!gic_present) +#endif clockevents_register_device(cd); if (cp0_timer_irq_installed) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5fe66a0c3224..4bbffdb9024f 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -470,6 +470,9 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_ULRI; if (config3 & MIPS_CONF3_ISA) c->options |= MIPS_CPU_MICROMIPS; +#ifdef CONFIG_CPU_MICROMIPS + write_c0_config3(read_c0_config3() | MIPS_CONF3_ISA_OE); +#endif if (config3 & MIPS_CONF3_VZ) c->ases |= MIPS_ASE_VZ; diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c index 35bed0d2342c..3be9e7bb30ff 100644 --- a/arch/mips/kernel/crash_dump.c +++ b/arch/mips/kernel/crash_dump.c @@ -2,6 +2,7 @@ #include <linux/bootmem.h> #include <linux/crash_dump.h> #include <asm/uaccess.h> +#include <linux/slab.h> static int __init parse_savemaxmem(char *p) { diff --git a/arch/mips/kernel/csrc-gic.c b/arch/mips/kernel/csrc-gic.c index 5dca24bce51b..e02620901117 100644 --- a/arch/mips/kernel/csrc-gic.c +++ b/arch/mips/kernel/csrc-gic.c @@ -5,23 +5,14 @@ * * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. */ -#include <linux/clocksource.h> #include <linux/init.h> +#include <linux/time.h> -#include <asm/time.h> #include <asm/gic.h> static cycle_t gic_hpt_read(struct clocksource *cs) { - unsigned int hi, hi2, lo; - - do { - GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi); - GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo); - GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2); - } while (hi2 != hi); - - return (((cycle_t) hi) << 32) + lo; + return gic_read_count(); } static struct clocksource gic_clocksource = { diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index ecb347ce1b3d..9098829bfcb0 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -5,8 +5,8 @@ * * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Copyright (C) 2001 MIPS Technologies, Inc. * Copyright (C) 2002, 2007 Maciej W. Rozycki + * Copyright (C) 2001, 2012 MIPS Technologies, Inc. All rights reserved. */ #include <linux/init.h> @@ -21,8 +21,10 @@ #include <asm/war.h> #include <asm/thread_info.h> +#ifdef CONFIG_MIPS_MT_SMTC #define PANIC_PIC(msg) \ - .set push; \ + .set push; \ + .set nomicromips; \ .set reorder; \ PTR_LA a0,8f; \ .set noat; \ @@ -31,17 +33,10 @@ 9: b 9b; \ .set pop; \ TEXT(msg) +#endif __INIT -NESTED(except_vec0_generic, 0, sp) - PANIC_PIC("Exception vector 0 called") - END(except_vec0_generic) - -NESTED(except_vec1_generic, 0, sp) - PANIC_PIC("Exception vector 1 called") - END(except_vec1_generic) - /* * General exception vector for all other CPUs. * @@ -138,12 +133,19 @@ LEAF(r4k_wait) nop nop nop +#ifdef CONFIG_CPU_MICROMIPS + nop + nop + nop + nop +#endif .set mips3 wait /* end of rollback region (the region size must be power of two) */ - .set pop 1: jr ra + nop + .set pop END(r4k_wait) .macro BUILD_ROLLBACK_PROLOGUE handler @@ -201,7 +203,11 @@ NESTED(handle_int, PT_SIZE, sp) LONG_L s0, TI_REGS($28) LONG_S sp, TI_REGS($28) PTR_LA ra, ret_from_irq - j plat_irq_dispatch + PTR_LA v0, plat_irq_dispatch + jr v0 +#ifdef CONFIG_CPU_MICROMIPS + nop +#endif END(handle_int) __INIT @@ -222,11 +228,14 @@ NESTED(except_vec4, 0, sp) /* * EJTAG debug exception handler. * The EJTAG debug exception entry point is 0xbfc00480, which - * normally is in the boot PROM, so the boot PROM must do a + * normally is in the boot PROM, so the boot PROM must do an * unconditional jump to this vector. */ NESTED(except_vec_ejtag_debug, 0, sp) j ejtag_debug_handler +#ifdef CONFIG_CPU_MICROMIPS + nop +#endif END(except_vec_ejtag_debug) __FINIT @@ -251,9 +260,10 @@ NESTED(except_vec_vi, 0, sp) FEXPORT(except_vec_vi_mori) ori a0, $0, 0 #endif /* CONFIG_MIPS_MT_SMTC */ + PTR_LA v1, except_vec_vi_handler FEXPORT(except_vec_vi_lui) lui v0, 0 /* Patched */ - j except_vec_vi_handler + jr v1 FEXPORT(except_vec_vi_ori) ori v0, 0 /* Patched */ .set pop @@ -354,6 +364,9 @@ EXPORT(ejtag_debug_buffer) */ NESTED(except_vec_nmi, 0, sp) j nmi_handler +#ifdef CONFIG_CPU_MICROMIPS + nop +#endif END(except_vec_nmi) __FINIT @@ -500,13 +513,35 @@ NESTED(nmi_handler, PT_SIZE, sp) .set push .set noat .set noreorder - /* 0x7c03e83b: rdhwr v1,$29 */ + /* MIPS32: 0x7c03e83b: rdhwr v1,$29 */ + /* microMIPS: 0x007d6b3c: rdhwr v1,$29 */ MFC0 k1, CP0_EPC - lui k0, 0x7c03 - lw k1, (k1) - ori k0, 0xe83b - .set reorder +#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2) + and k0, k1, 1 + beqz k0, 1f + xor k1, k0 + lhu k0, (k1) + lhu k1, 2(k1) + ins k1, k0, 16, 16 + lui k0, 0x007d + b docheck + ori k0, 0x6b3c +1: + lui k0, 0x7c03 + lw k1, (k1) + ori k0, 0xe83b +#else + andi k0, k1, 1 + bnez k0, handle_ri + lui k0, 0x7c03 + lw k1, (k1) + ori k0, 0xe83b +#endif + .set reorder +docheck: bne k0, k1, handle_ri /* if not ours */ + +isrdhwr: /* The insn is rdhwr. No need to check CAUSE.BD here. */ get_saved_sp /* k1 := current_thread_info */ .set noreorder diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 485e6a961b31..c01b307317a9 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -10,6 +10,7 @@ #include <linux/init.h> #include <linux/smp.h> #include <linux/irq.h> +#include <linux/clocksource.h> #include <asm/io.h> #include <asm/gic.h> @@ -19,6 +20,8 @@ #include <linux/hardirq.h> #include <asm-generic/bitops/find.h> +unsigned int gic_frequency; +unsigned int gic_present; unsigned long _gic_base; unsigned int gic_irq_base; unsigned int gic_irq_flags[GIC_NUM_INTRS]; @@ -30,6 +33,39 @@ static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; static struct gic_pending_regs pending_regs[NR_CPUS]; static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; +#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC) +cycle_t gic_read_count(void) +{ + unsigned int hi, hi2, lo; + + do { + GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi); + GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo); + GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2); + } while (hi2 != hi); + + return (((cycle_t) hi) << 32) + lo; +} + +void gic_write_compare(cycle_t cnt) +{ + GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI), + (int)(cnt >> 32)); + GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO), + (int)(cnt & 0xffffffff)); +} + +cycle_t gic_read_compare(void) +{ + unsigned int hi, lo; + + GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI), hi); + GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO), lo); + + return (((cycle_t) hi) << 32) + lo; +} +#endif + unsigned int gic_get_timer_pending(void) { unsigned int vpe_pending; @@ -116,6 +152,17 @@ static void __init vpe_local_setup(unsigned int numvpes) } } +unsigned int gic_compare_int(void) +{ + unsigned int pending; + + GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_PEND), pending); + if (pending & GIC_VPE_PEND_CMP_MSK) + return 1; + else + return 0; +} + unsigned int gic_get_int(void) { unsigned int i; diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index d1d576b765f5..0b29646bcee7 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -165,10 +165,3 @@ asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2, return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3), merge_64(len_a4, len_a5)); } - -SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags, - u64, a3, u64, a4, int, dfd, const char __user *, pathname) -{ - return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4), - dfd, pathname); -} diff --git a/arch/mips/kernel/mips_machine.c b/arch/mips/kernel/mips_machine.c index 411a058d2c53..876097529697 100644 --- a/arch/mips/kernel/mips_machine.c +++ b/arch/mips/kernel/mips_machine.c @@ -11,9 +11,9 @@ #include <linux/slab.h> #include <asm/mips_machine.h> +#include <asm/prom.h> static struct mips_machine *mips_machine __initdata; -static char *mips_machine_name = "Unknown"; #define for_each_machine(mach) \ for ((mach) = (struct mips_machine *)&__mips_machines_start; \ @@ -21,25 +21,6 @@ static char *mips_machine_name = "Unknown"; (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \ (mach)++) -__init void mips_set_machine_name(const char *name) -{ - char *p; - - if (name == NULL) - return; - - p = kstrdup(name, GFP_KERNEL); - if (!p) - pr_err("MIPS: no memory for machine_name\n"); - - mips_machine_name = p; -} - -char *mips_get_machine_name(void) -{ - return mips_machine_name; -} - __init int mips_machtype_setup(char *id) { struct mips_machine *mach; @@ -79,7 +60,6 @@ __init void mips_machine_setup(void) return; mips_set_machine_name(mips_machine->mach_name); - pr_info("MIPS: machine is %s\n", mips_machine_name); if (mips_machine->mach_setup) mips_machine->mach_setup(); diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 7a54f74b7818..a3e461408b7e 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -12,7 +12,7 @@ #include <asm/cpu-features.h> #include <asm/mipsregs.h> #include <asm/processor.h> -#include <asm/mips_machine.h> +#include <asm/prom.h> unsigned int vced_count, vcei_count; @@ -99,6 +99,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (cpu_has_vz) seq_printf(m, "%s", " vz"); seq_printf(m, "\n"); + if (cpu_has_mmips) { + seq_printf(m, "micromips kernel\t: %s\n", + (read_c0_config3() & MIPS_CONF3_ISA_OE) ? "yes" : "no"); + } seq_printf(m, "shadow register sets\t: %d\n", cpu_data[n].srsets); seq_printf(m, "kscratch registers\t: %d\n", diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index cfc742d75b7f..a682a87bcc04 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -7,6 +7,7 @@ * Copyright (C) 2005, 2006 by Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 2004 Thiemo Seufer + * Copyright (C) 2013 Imagination Technologies Ltd. */ #include <linux/errno.h> #include <linux/sched.h> @@ -223,36 +224,122 @@ struct mips_frame_info { int pc_offset; }; +#define J_TARGET(pc,target) \ + (((unsigned long)(pc) & 0xf0000000) | ((target) << 2)) + static inline int is_ra_save_ins(union mips_instruction *ip) { +#ifdef CONFIG_CPU_MICROMIPS + union mips_instruction mmi; + + /* + * swsp ra,offset + * swm16 reglist,offset(sp) + * swm32 reglist,offset(sp) + * sw32 ra,offset(sp) + * jradiussp - NOT SUPPORTED + * + * microMIPS is way more fun... + */ + if (mm_insn_16bit(ip->halfword[0])) { + mmi.word = (ip->halfword[0] << 16); + return ((mmi.mm16_r5_format.opcode == mm_swsp16_op && + mmi.mm16_r5_format.rt == 31) || + (mmi.mm16_m_format.opcode == mm_pool16c_op && + mmi.mm16_m_format.func == mm_swm16_op)); + } + else { + mmi.halfword[0] = ip->halfword[1]; + mmi.halfword[1] = ip->halfword[0]; + return ((mmi.mm_m_format.opcode == mm_pool32b_op && + mmi.mm_m_format.rd > 9 && + mmi.mm_m_format.base == 29 && + mmi.mm_m_format.func == mm_swm32_func) || + (mmi.i_format.opcode == mm_sw32_op && + mmi.i_format.rs == 29 && + mmi.i_format.rt == 31)); + } +#else /* sw / sd $ra, offset($sp) */ return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) && ip->i_format.rs == 29 && ip->i_format.rt == 31; +#endif } -static inline int is_jal_jalr_jr_ins(union mips_instruction *ip) +static inline int is_jump_ins(union mips_instruction *ip) { +#ifdef CONFIG_CPU_MICROMIPS + /* + * jr16,jrc,jalr16,jalr16 + * jal + * jalr/jr,jalr.hb/jr.hb,jalrs,jalrs.hb + * jraddiusp - NOT SUPPORTED + * + * microMIPS is kind of more fun... + */ + union mips_instruction mmi; + + mmi.word = (ip->halfword[0] << 16); + + if ((mmi.mm16_r5_format.opcode == mm_pool16c_op && + (mmi.mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op) || + ip->j_format.opcode == mm_jal32_op) + return 1; + if (ip->r_format.opcode != mm_pool32a_op || + ip->r_format.func != mm_pool32axf_op) + return 0; + return (((ip->u_format.uimmediate >> 6) & mm_jalr_op) == mm_jalr_op); +#else + if (ip->j_format.opcode == j_op) + return 1; if (ip->j_format.opcode == jal_op) return 1; if (ip->r_format.opcode != spec_op) return 0; return ip->r_format.func == jalr_op || ip->r_format.func == jr_op; +#endif } static inline int is_sp_move_ins(union mips_instruction *ip) { +#ifdef CONFIG_CPU_MICROMIPS + /* + * addiusp -imm + * addius5 sp,-imm + * addiu32 sp,sp,-imm + * jradiussp - NOT SUPPORTED + * + * microMIPS is not more fun... + */ + if (mm_insn_16bit(ip->halfword[0])) { + union mips_instruction mmi; + + mmi.word = (ip->halfword[0] << 16); + return ((mmi.mm16_r3_format.opcode == mm_pool16d_op && + mmi.mm16_r3_format.simmediate && mm_addiusp_func) || + (mmi.mm16_r5_format.opcode == mm_pool16d_op && + mmi.mm16_r5_format.rt == 29)); + } + return (ip->mm_i_format.opcode == mm_addiu32_op && + ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29); +#else /* addiu/daddiu sp,sp,-imm */ if (ip->i_format.rs != 29 || ip->i_format.rt != 29) return 0; if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op) return 1; +#endif return 0; } static int get_frame_info(struct mips_frame_info *info) { +#ifdef CONFIG_CPU_MICROMIPS + union mips_instruction *ip = (void *) (((char *) info->func) - 1); +#else union mips_instruction *ip = info->func; +#endif unsigned max_insns = info->func_size / sizeof(union mips_instruction); unsigned i; @@ -268,11 +355,30 @@ static int get_frame_info(struct mips_frame_info *info) for (i = 0; i < max_insns; i++, ip++) { - if (is_jal_jalr_jr_ins(ip)) + if (is_jump_ins(ip)) break; if (!info->frame_size) { if (is_sp_move_ins(ip)) + { +#ifdef CONFIG_CPU_MICROMIPS + if (mm_insn_16bit(ip->halfword[0])) + { + unsigned short tmp; + + if (ip->halfword[0] & mm_addiusp_func) + { + tmp = (((ip->halfword[0] >> 1) & 0x1ff) << 2); + info->frame_size = -(signed short)(tmp | ((tmp & 0x100) ? 0xfe00 : 0)); + } else { + tmp = (ip->halfword[0] >> 1); + info->frame_size = -(signed short)(tmp & 0xf); + } + ip = (void *) &ip->halfword[1]; + ip--; + } else +#endif info->frame_size = - ip->i_format.simmediate; + } continue; } if (info->pc_offset == -1 && is_ra_save_ins(ip)) { @@ -292,15 +398,42 @@ err: static struct mips_frame_info schedule_mfi __read_mostly; +#ifdef CONFIG_KALLSYMS +static unsigned long get___schedule_addr(void) +{ + return kallsyms_lookup_name("__schedule"); +} +#else +static unsigned long get___schedule_addr(void) +{ + union mips_instruction *ip = (void *)schedule; + int max_insns = 8; + int i; + + for (i = 0; i < max_insns; i++, ip++) { + if (ip->j_format.opcode == j_op) + return J_TARGET(ip, ip->j_format.target); + } + return 0; +} +#endif + static int __init frame_info_init(void) { unsigned long size = 0; #ifdef CONFIG_KALLSYMS unsigned long ofs; +#endif + unsigned long addr; - kallsyms_lookup_size_offset((unsigned long)schedule, &size, &ofs); + addr = get___schedule_addr(); + if (!addr) + addr = (unsigned long)schedule; + +#ifdef CONFIG_KALLSYMS + kallsyms_lookup_size_offset(addr, &size, &ofs); #endif - schedule_mfi.func = schedule; + schedule_mfi.func = (void *)addr; schedule_mfi.func_size = size; get_frame_info(&schedule_mfi); diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 028f6f837ef9..5712bb532245 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -23,6 +23,23 @@ #include <asm/page.h> #include <asm/prom.h> +static char mips_machine_name[64] = "Unknown"; + +__init void mips_set_machine_name(const char *name) +{ + if (name == NULL) + return; + + strncpy(mips_machine_name, name, sizeof(mips_machine_name)); + pr_info("MIPS: machine is %s\n", mips_get_machine_name()); +} + +char *mips_get_machine_name(void) +{ + return mips_machine_name; +} + +#ifdef CONFIG_OF int __init early_init_dt_scan_memory_arch(unsigned long node, const char *uname, int depth, void *data) @@ -50,6 +67,18 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start, } #endif +int __init early_init_dt_scan_model(unsigned long node, const char *uname, + int depth, void *data) +{ + if (!depth) { + char *model = of_get_flat_dt_prop(node, "model", NULL); + + if (model) + mips_set_machine_name(model); + } + return 0; +} + void __init early_init_devtree(void *params) { /* Setup flat device-tree pointer */ @@ -65,6 +94,9 @@ void __init early_init_devtree(void *params) /* Scan memory nodes */ of_scan_flat_dt(early_init_dt_scan_root, NULL); of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL); + + /* try to load the mips machine name */ + of_scan_flat_dt(early_init_dt_scan_model, NULL); } void __init __dt_setup_arch(struct boot_param_header *bph) @@ -79,3 +111,4 @@ void __init __dt_setup_arch(struct boot_param_header *bph) early_init_devtree(initial_boot_params); } +#endif diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 9ea29649fc28..9b36424b03c5 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -138,9 +138,18 @@ stackargs: 5: jr t1 sw t5, 16(sp) # argument #5 to ksp +#ifdef CONFIG_CPU_MICROMIPS sw t8, 28(sp) # argument #8 to ksp + nop sw t7, 24(sp) # argument #7 to ksp + nop sw t6, 20(sp) # argument #6 to ksp + nop +#else + sw t8, 28(sp) # argument #8 to ksp + sw t7, 24(sp) # argument #7 to ksp + sw t6, 20(sp) # argument #6 to ksp +#endif 6: j stack_done # go back nop .set pop diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 103bfe570fe8..74f485d3c0ef 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -529,7 +529,7 @@ sys_call_table: PTR sys_accept4 PTR compat_sys_recvmmsg /* 4335 */ PTR sys_fanotify_init - PTR sys_32_fanotify_mark + PTR compat_sys_fanotify_mark PTR sys_prlimit64 PTR sys_name_to_handle_at PTR compat_sys_open_by_handle_at /* 4340 */ diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 4c774d5d5087..c7f90519e58c 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -23,6 +23,7 @@ #include <linux/pfn.h> #include <linux/debugfs.h> #include <linux/kexec.h> +#include <linux/sizes.h> #include <asm/addrspace.h> #include <asm/bootinfo.h> @@ -77,6 +78,8 @@ EXPORT_SYMBOL(mips_io_port_base); static struct resource code_resource = { .name = "Kernel code", }; static struct resource data_resource = { .name = "Kernel data", }; +static void *detect_magic __initdata = detect_memory_region; + void __init add_memory_region(phys_t start, phys_t size, long type) { int x = boot_mem_map.nr_map; @@ -122,6 +125,25 @@ void __init add_memory_region(phys_t start, phys_t size, long type) boot_mem_map.nr_map++; } +void __init detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max) +{ + void *dm = &detect_magic; + phys_t size; + + for (size = sz_min; size < sz_max; size <<= 1) { + if (!memcmp(dm, dm + size, sizeof(detect_magic))) + break; + } + + pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n", + ((unsigned long long) size) / SZ_1M, + (unsigned long long) start, + ((unsigned long long) sz_min) / SZ_1M, + ((unsigned long long) sz_max) / SZ_1M); + + add_memory_region(start, size, BOOT_MEM_RAM); +} + static void __init print_memory_map(void) { int i; diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index b5e88fd83277..fd3ef2c2afbc 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -35,6 +35,7 @@ #include <asm/war.h> #include <asm/vdso.h> #include <asm/dsp.h> +#include <asm/inst.h> #include "signal-common.h" @@ -480,7 +481,15 @@ static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset = sigmask_to_save(); int ret; struct mips_abi *abi = current->thread.abi; +#ifdef CONFIG_CPU_MICROMIPS + void *vdso; + unsigned int tmp = (unsigned int)current->mm->context.vdso; + + set_isa16_mode(tmp); + vdso = (void *)tmp; +#else void *vdso = current->mm->context.vdso; +#endif if (regs->regs[0]) { switch(regs->regs[2]) { diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index bfede063d96a..3e5164c11cac 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -34,6 +34,7 @@ #include <asm/mipsregs.h> #include <asm/mipsmtregs.h> #include <asm/mips_mt.h> +#include <asm/gic.h> static void __init smvp_copy_vpe_config(void) { @@ -151,8 +152,6 @@ static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action) static void __cpuinit vsmp_init_secondary(void) { #ifdef CONFIG_IRQ_GIC - extern int gic_present; - /* This is Malta specific: IPI,performance and timer interrupts */ if (gic_present) change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index aee04af213c5..c17619fe18e3 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -83,6 +83,7 @@ static inline void set_cpu_sibling_map(int cpu) } struct plat_smp_ops *mp_ops; +EXPORT_SYMBOL(mp_ops); __cpuinit void register_smp_ops(struct plat_smp_ops *ops) { diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S index 76016ac0a9c8..2866863a39df 100644 --- a/arch/mips/kernel/smtc-asm.S +++ b/arch/mips/kernel/smtc-asm.S @@ -49,6 +49,9 @@ CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED?? .text .align 5 FEXPORT(__smtc_ipi_vector) +#ifdef CONFIG_CPU_MICROMIPS + nop +#endif .set noat /* Disable thread scheduling to make Status update atomic */ DMT 27 # dmt k1 diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 25225515451f..cb14db3c5764 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -8,8 +8,8 @@ * Copyright (C) 1998 Ulf Carlsson * Copyright (C) 1999 Silicon Graphics, Inc. * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000, 01 MIPS Technologies, Inc. * Copyright (C) 2002, 2003, 2004, 2005, 2007 Maciej W. Rozycki + * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc. All rights reserved. */ #include <linux/bug.h> #include <linux/compiler.h> @@ -60,9 +60,9 @@ extern void check_wait(void); extern asmlinkage void r4k_wait(void); extern asmlinkage void rollback_handle_int(void); extern asmlinkage void handle_int(void); -extern asmlinkage void handle_tlbm(void); -extern asmlinkage void handle_tlbl(void); -extern asmlinkage void handle_tlbs(void); +extern u32 handle_tlbl[]; +extern u32 handle_tlbs[]; +extern u32 handle_tlbm[]; extern asmlinkage void handle_adel(void); extern asmlinkage void handle_ades(void); extern asmlinkage void handle_ibe(void); @@ -83,10 +83,6 @@ extern asmlinkage void handle_dsp(void); extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); -extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, - struct mips_fpu_struct *ctx, int has_fpu, - void *__user *fault_addr); - void (*board_be_init)(void); int (*board_be_handler)(struct pt_regs *regs, int is_fixup); void (*board_nmi_handler_setup)(void); @@ -482,6 +478,12 @@ asmlinkage void do_be(struct pt_regs *regs) #define SYNC 0x0000000f #define RDHWR 0x0000003b +/* microMIPS definitions */ +#define MM_POOL32A_FUNC 0xfc00ffff +#define MM_RDHWR 0x00006b3c +#define MM_RS 0x001f0000 +#define MM_RT 0x03e00000 + /* * The ll_bit is cleared by r*_switch.S */ @@ -596,42 +598,62 @@ static int simulate_llsc(struct pt_regs *regs, unsigned int opcode) * Simulate trapping 'rdhwr' instructions to provide user accessible * registers not implemented in hardware. */ -static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode) +static int simulate_rdhwr(struct pt_regs *regs, int rd, int rt) { struct thread_info *ti = task_thread_info(current); + perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, + 1, regs, 0); + switch (rd) { + case 0: /* CPU number */ + regs->regs[rt] = smp_processor_id(); + return 0; + case 1: /* SYNCI length */ + regs->regs[rt] = min(current_cpu_data.dcache.linesz, + current_cpu_data.icache.linesz); + return 0; + case 2: /* Read count register */ + regs->regs[rt] = read_c0_count(); + return 0; + case 3: /* Count register resolution */ + switch (current_cpu_data.cputype) { + case CPU_20KC: + case CPU_25KF: + regs->regs[rt] = 1; + break; + default: + regs->regs[rt] = 2; + } + return 0; + case 29: + regs->regs[rt] = ti->tp_value; + return 0; + default: + return -1; + } +} + +static int simulate_rdhwr_normal(struct pt_regs *regs, unsigned int opcode) +{ if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) { int rd = (opcode & RD) >> 11; int rt = (opcode & RT) >> 16; - perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, - 1, regs, 0); - switch (rd) { - case 0: /* CPU number */ - regs->regs[rt] = smp_processor_id(); - return 0; - case 1: /* SYNCI length */ - regs->regs[rt] = min(current_cpu_data.dcache.linesz, - current_cpu_data.icache.linesz); - return 0; - case 2: /* Read count register */ - regs->regs[rt] = read_c0_count(); - return 0; - case 3: /* Count register resolution */ - switch (current_cpu_data.cputype) { - case CPU_20KC: - case CPU_25KF: - regs->regs[rt] = 1; - break; - default: - regs->regs[rt] = 2; - } - return 0; - case 29: - regs->regs[rt] = ti->tp_value; - return 0; - default: - return -1; - } + + simulate_rdhwr(regs, rd, rt); + return 0; + } + + /* Not ours. */ + return -1; +} + +static int simulate_rdhwr_mm(struct pt_regs *regs, unsigned short opcode) +{ + if ((opcode & MM_POOL32A_FUNC) == MM_RDHWR) { + int rd = (opcode & MM_RS) >> 16; + int rt = (opcode & MM_RT) >> 21; + simulate_rdhwr(regs, rd, rt); + return 0; } /* Not ours. */ @@ -662,7 +684,7 @@ asmlinkage void do_ov(struct pt_regs *regs) force_sig_info(SIGFPE, &info, current); } -static int process_fpemu_return(int sig, void __user *fault_addr) +int process_fpemu_return(int sig, void __user *fault_addr) { if (sig == SIGSEGV || sig == SIGBUS) { struct siginfo si = {0}; @@ -813,9 +835,29 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, asmlinkage void do_bp(struct pt_regs *regs) { unsigned int opcode, bcode; - - if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) - goto out_sigsegv; + unsigned long epc; + u16 instr[2]; + + if (get_isa16_mode(regs->cp0_epc)) { + /* Calculate EPC. */ + epc = exception_epc(regs); + if (cpu_has_mmips) { + if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) || + (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2))))) + goto out_sigsegv; + opcode = (instr[0] << 16) | instr[1]; + } else { + /* MIPS16e mode */ + if (__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc))) + goto out_sigsegv; + bcode = (instr[0] >> 6) & 0x3f; + do_trap_or_bp(regs, bcode, "Break"); + return; + } + } else { + if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) + goto out_sigsegv; + } /* * There is the ancient bug in the MIPS assemblers that the break @@ -856,13 +898,22 @@ out_sigsegv: asmlinkage void do_tr(struct pt_regs *regs) { unsigned int opcode, tcode = 0; + u16 instr[2]; + unsigned long epc = exception_epc(regs); - if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) - goto out_sigsegv; + if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc))) || + (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))) + goto out_sigsegv; + opcode = (instr[0] << 16) | instr[1]; /* Immediate versions don't provide a code. */ - if (!(opcode & OPCODE)) - tcode = ((opcode >> 6) & ((1 << 10) - 1)); + if (!(opcode & OPCODE)) { + if (get_isa16_mode(regs->cp0_epc)) + /* microMIPS */ + tcode = (opcode >> 12) & 0x1f; + else + tcode = ((opcode >> 6) & ((1 << 10) - 1)); + } do_trap_or_bp(regs, tcode, "Trap"); return; @@ -875,6 +926,7 @@ asmlinkage void do_ri(struct pt_regs *regs) { unsigned int __user *epc = (unsigned int __user *)exception_epc(regs); unsigned long old_epc = regs->cp0_epc; + unsigned long old31 = regs->regs[31]; unsigned int opcode = 0; int status = -1; @@ -887,23 +939,37 @@ asmlinkage void do_ri(struct pt_regs *regs) if (unlikely(compute_return_epc(regs) < 0)) return; - if (unlikely(get_user(opcode, epc) < 0)) - status = SIGSEGV; + if (get_isa16_mode(regs->cp0_epc)) { + unsigned short mmop[2] = { 0 }; + + if (unlikely(get_user(mmop[0], epc) < 0)) + status = SIGSEGV; + if (unlikely(get_user(mmop[1], epc) < 0)) + status = SIGSEGV; + opcode = (mmop[0] << 16) | mmop[1]; - if (!cpu_has_llsc && status < 0) - status = simulate_llsc(regs, opcode); + if (status < 0) + status = simulate_rdhwr_mm(regs, opcode); + } else { + if (unlikely(get_user(opcode, epc) < 0)) + status = SIGSEGV; - if (status < 0) - status = simulate_rdhwr(regs, opcode); + if (!cpu_has_llsc && status < 0) + status = simulate_llsc(regs, opcode); - if (status < 0) - status = simulate_sync(regs, opcode); + if (status < 0) + status = simulate_rdhwr_normal(regs, opcode); + + if (status < 0) + status = simulate_sync(regs, opcode); + } if (status < 0) status = SIGILL; if (unlikely(status > 0)) { regs->cp0_epc = old_epc; /* Undo skip-over. */ + regs->regs[31] = old31; force_sig(status, current); } } @@ -973,7 +1039,7 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, asmlinkage void do_cpu(struct pt_regs *regs) { unsigned int __user *epc; - unsigned long old_epc; + unsigned long old_epc, old31; unsigned int opcode; unsigned int cpid; int status; @@ -987,26 +1053,41 @@ asmlinkage void do_cpu(struct pt_regs *regs) case 0: epc = (unsigned int __user *)exception_epc(regs); old_epc = regs->cp0_epc; + old31 = regs->regs[31]; opcode = 0; status = -1; if (unlikely(compute_return_epc(regs) < 0)) return; - if (unlikely(get_user(opcode, epc) < 0)) - status = SIGSEGV; + if (get_isa16_mode(regs->cp0_epc)) { + unsigned short mmop[2] = { 0 }; - if (!cpu_has_llsc && status < 0) - status = simulate_llsc(regs, opcode); + if (unlikely(get_user(mmop[0], epc) < 0)) + status = SIGSEGV; + if (unlikely(get_user(mmop[1], epc) < 0)) + status = SIGSEGV; + opcode = (mmop[0] << 16) | mmop[1]; - if (status < 0) - status = simulate_rdhwr(regs, opcode); + if (status < 0) + status = simulate_rdhwr_mm(regs, opcode); + } else { + if (unlikely(get_user(opcode, epc) < 0)) + status = SIGSEGV; + + if (!cpu_has_llsc && status < 0) + status = simulate_llsc(regs, opcode); + + if (status < 0) + status = simulate_rdhwr_normal(regs, opcode); + } if (status < 0) status = SIGILL; if (unlikely(status > 0)) { regs->cp0_epc = old_epc; /* Undo skip-over. */ + regs->regs[31] = old31; force_sig(status, current); } @@ -1320,7 +1401,7 @@ asmlinkage void cache_parity_error(void) void ejtag_exception_handler(struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); - unsigned long depc, old_epc; + unsigned long depc, old_epc, old_ra; unsigned int debug; printk(KERN_DEBUG "SDBBP EJTAG debug exception - not handled yet, just ignored!\n"); @@ -1335,10 +1416,12 @@ void ejtag_exception_handler(struct pt_regs *regs) * calculation. */ old_epc = regs->cp0_epc; + old_ra = regs->regs[31]; regs->cp0_epc = depc; - __compute_return_epc(regs); + compute_return_epc(regs); depc = regs->cp0_epc; regs->cp0_epc = old_epc; + regs->regs[31] = old_ra; } else depc += 4; write_c0_depc(depc); @@ -1377,11 +1460,27 @@ unsigned long vi_handlers[64]; void __init *set_except_vector(int n, void *addr) { unsigned long handler = (unsigned long) addr; - unsigned long old_handler = exception_handlers[n]; + unsigned long old_handler; + +#ifdef CONFIG_CPU_MICROMIPS + /* + * Only the TLB handlers are cache aligned with an even + * address. All other handlers are on an odd address and + * require no modification. Otherwise, MIPS32 mode will + * be entered when handling any TLB exceptions. That + * would be bad...since we must stay in microMIPS mode. + */ + if (!(handler & 0x1)) + handler |= 1; +#endif + old_handler = xchg(&exception_handlers[n], handler); - exception_handlers[n] = handler; if (n == 0 && cpu_has_divec) { +#ifdef CONFIG_CPU_MICROMIPS + unsigned long jump_mask = ~((1 << 27) - 1); +#else unsigned long jump_mask = ~((1 << 28) - 1); +#endif u32 *buf = (u32 *)(ebase + 0x200); unsigned int k0 = 26; if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) { @@ -1397,7 +1496,7 @@ void __init *set_except_vector(int n, void *addr) return (void *)old_handler; } -static asmlinkage void do_default_vi(void) +static void do_default_vi(void) { show_regs(get_irq_regs()); panic("Caught unexpected vectored interrupt."); @@ -1408,17 +1507,18 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) unsigned long handler; unsigned long old_handler = vi_handlers[n]; int srssets = current_cpu_data.srsets; - u32 *w; + u16 *h; unsigned char *b; BUG_ON(!cpu_has_veic && !cpu_has_vint); + BUG_ON((n < 0) && (n > 9)); if (addr == NULL) { handler = (unsigned long) do_default_vi; srs = 0; } else handler = (unsigned long) addr; - vi_handlers[n] = (unsigned long) addr; + vi_handlers[n] = handler; b = (unsigned char *)(ebase + 0x200 + n*VECTORSPACING); @@ -1437,9 +1537,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) if (srs == 0) { /* * If no shadow set is selected then use the default handler - * that does normal register saving and a standard interrupt exit + * that does normal register saving and standard interrupt exit */ - extern char except_vec_vi, except_vec_vi_lui; extern char except_vec_vi_ori, except_vec_vi_end; extern char rollback_except_vec_vi; @@ -1452,11 +1551,20 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) * Status.IM bit to be masked before going there. */ extern char except_vec_vi_mori; +#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN) + const int mori_offset = &except_vec_vi_mori - vec_start + 2; +#else const int mori_offset = &except_vec_vi_mori - vec_start; +#endif #endif /* CONFIG_MIPS_MT_SMTC */ - const int handler_len = &except_vec_vi_end - vec_start; +#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN) + const int lui_offset = &except_vec_vi_lui - vec_start + 2; + const int ori_offset = &except_vec_vi_ori - vec_start + 2; +#else const int lui_offset = &except_vec_vi_lui - vec_start; const int ori_offset = &except_vec_vi_ori - vec_start; +#endif + const int handler_len = &except_vec_vi_end - vec_start; if (handler_len > VECTORSPACING) { /* @@ -1466,30 +1574,44 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) panic("VECTORSPACING too small"); } - memcpy(b, vec_start, handler_len); + set_handler(((unsigned long)b - ebase), vec_start, +#ifdef CONFIG_CPU_MICROMIPS + (handler_len - 1)); +#else + handler_len); +#endif #ifdef CONFIG_MIPS_MT_SMTC BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ - w = (u32 *)(b + mori_offset); - *w = (*w & 0xffff0000) | (0x100 << n); + h = (u16 *)(b + mori_offset); + *h = (0x100 << n); #endif /* CONFIG_MIPS_MT_SMTC */ - w = (u32 *)(b + lui_offset); - *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff); - w = (u32 *)(b + ori_offset); - *w = (*w & 0xffff0000) | ((u32)handler & 0xffff); + h = (u16 *)(b + lui_offset); + *h = (handler >> 16) & 0xffff; + h = (u16 *)(b + ori_offset); + *h = (handler & 0xffff); local_flush_icache_range((unsigned long)b, (unsigned long)(b+handler_len)); } else { /* - * In other cases jump directly to the interrupt handler - * - * It is the handlers responsibility to save registers if required - * (eg hi/lo) and return from the exception using "eret" + * In other cases jump directly to the interrupt handler. It + * is the handler's responsibility to save registers if required + * (eg hi/lo) and return from the exception using "eret". */ - w = (u32 *)b; - *w++ = 0x08000000 | (((u32)handler >> 2) & 0x03fffff); /* j handler */ - *w = 0; + u32 insn; + + h = (u16 *)b; + /* j handler */ +#ifdef CONFIG_CPU_MICROMIPS + insn = 0xd4000000 | (((u32)handler & 0x07ffffff) >> 1); +#else + insn = 0x08000000 | (((u32)handler & 0x0fffffff) >> 2); +#endif + h[0] = (insn >> 16) & 0xffff; + h[1] = insn & 0xffff; + h[2] = 0; + h[3] = 0; local_flush_icache_range((unsigned long)b, (unsigned long)(b+8)); } @@ -1648,7 +1770,11 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu) /* Install CPU exception handler */ void __cpuinit set_handler(unsigned long offset, void *addr, unsigned long size) { +#ifdef CONFIG_CPU_MICROMIPS + memcpy((void *)(ebase + offset), ((unsigned char *)addr - 1), size); +#else memcpy((void *)(ebase + offset), addr, size); +#endif local_flush_icache_range(ebase + offset, ebase + offset + size); } @@ -1682,8 +1808,9 @@ __setup("rdhwr_noopt", set_rdhwr_noopt); void __init trap_init(void) { - extern char except_vec3_generic, except_vec3_r4000; + extern char except_vec3_generic; extern char except_vec4; + extern char except_vec3_r4000; unsigned long i; int rollback; @@ -1700,7 +1827,12 @@ void __init trap_init(void) ebase = (unsigned long) __alloc_bootmem(size, 1 << fls(size), 0); } else { - ebase = CKSEG0; +#ifdef CONFIG_KVM_GUEST +#define KVM_GUEST_KSEG0 0x40000000 + ebase = KVM_GUEST_KSEG0; +#else + ebase = CKSEG0; +#endif if (cpu_has_mips_r2) ebase += (read_c0_ebase() & 0x3ffff000); } @@ -1816,11 +1948,11 @@ void __init trap_init(void) if (cpu_has_vce) /* Special exception: R4[04]00 uses also the divec space. */ - memcpy((void *)(ebase + 0x180), &except_vec3_r4000, 0x100); + set_handler(0x180, &except_vec3_r4000, 0x100); else if (cpu_has_4kex) - memcpy((void *)(ebase + 0x180), &except_vec3_generic, 0x80); + set_handler(0x180, &except_vec3_generic, 0x80); else - memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80); + set_handler(0x080, &except_vec3_generic, 0x80); local_flush_icache_range(ebase, ebase + 0x400); flush_tlb_handlers(); diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 6087a54c86a0..203d8857070d 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -83,8 +83,12 @@ #include <asm/branch.h> #include <asm/byteorder.h> #include <asm/cop2.h> +#include <asm/fpu.h> +#include <asm/fpu_emulator.h> #include <asm/inst.h> #include <asm/uaccess.h> +#include <asm/fpu.h> +#include <asm/fpu_emulator.h> #define STR(x) __STR(x) #define __STR(x) #x @@ -102,12 +106,332 @@ static u32 unaligned_action; #endif extern void show_registers(struct pt_regs *regs); +#ifdef __BIG_ENDIAN +#define LoadHW(addr, value, res) \ + __asm__ __volatile__ (".set\tnoat\n" \ + "1:\tlb\t%0, 0(%2)\n" \ + "2:\tlbu\t$1, 1(%2)\n\t" \ + "sll\t%0, 0x8\n\t" \ + "or\t%0, $1\n\t" \ + "li\t%1, 0\n" \ + "3:\t.set\tat\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tlwl\t%0, (%2)\n" \ + "2:\tlwr\t%0, 3(%2)\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadHWU(addr, value, res) \ + __asm__ __volatile__ ( \ + ".set\tnoat\n" \ + "1:\tlbu\t%0, 0(%2)\n" \ + "2:\tlbu\t$1, 1(%2)\n\t" \ + "sll\t%0, 0x8\n\t" \ + "or\t%0, $1\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".set\tat\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadWU(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tlwl\t%0, (%2)\n" \ + "2:\tlwr\t%0, 3(%2)\n\t" \ + "dsll\t%0, %0, 32\n\t" \ + "dsrl\t%0, %0, 32\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + "\t.section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadDW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tldl\t%0, (%2)\n" \ + "2:\tldr\t%0, 7(%2)\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + "\t.section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define StoreHW(addr, value, res) \ + __asm__ __volatile__ ( \ + ".set\tnoat\n" \ + "1:\tsb\t%1, 1(%2)\n\t" \ + "srl\t$1, %1, 0x8\n" \ + "2:\tsb\t$1, 0(%2)\n\t" \ + ".set\tat\n\t" \ + "li\t%0, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%0, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); + +#define StoreW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tswl\t%1,(%2)\n" \ + "2:\tswr\t%1, 3(%2)\n\t" \ + "li\t%0, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%0, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); + +#define StoreDW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tsdl\t%1,(%2)\n" \ + "2:\tsdr\t%1, 7(%2)\n\t" \ + "li\t%0, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%0, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); +#endif + +#ifdef __LITTLE_ENDIAN +#define LoadHW(addr, value, res) \ + __asm__ __volatile__ (".set\tnoat\n" \ + "1:\tlb\t%0, 1(%2)\n" \ + "2:\tlbu\t$1, 0(%2)\n\t" \ + "sll\t%0, 0x8\n\t" \ + "or\t%0, $1\n\t" \ + "li\t%1, 0\n" \ + "3:\t.set\tat\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tlwl\t%0, 3(%2)\n" \ + "2:\tlwr\t%0, (%2)\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadHWU(addr, value, res) \ + __asm__ __volatile__ ( \ + ".set\tnoat\n" \ + "1:\tlbu\t%0, 1(%2)\n" \ + "2:\tlbu\t$1, 0(%2)\n\t" \ + "sll\t%0, 0x8\n\t" \ + "or\t%0, $1\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".set\tat\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadWU(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tlwl\t%0, 3(%2)\n" \ + "2:\tlwr\t%0, (%2)\n\t" \ + "dsll\t%0, %0, 32\n\t" \ + "dsrl\t%0, %0, 32\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + "\t.section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define LoadDW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tldl\t%0, 7(%2)\n" \ + "2:\tldr\t%0, (%2)\n\t" \ + "li\t%1, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + "\t.section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%1, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=&r" (value), "=r" (res) \ + : "r" (addr), "i" (-EFAULT)); + +#define StoreHW(addr, value, res) \ + __asm__ __volatile__ ( \ + ".set\tnoat\n" \ + "1:\tsb\t%1, 0(%2)\n\t" \ + "srl\t$1,%1, 0x8\n" \ + "2:\tsb\t$1, 1(%2)\n\t" \ + ".set\tat\n\t" \ + "li\t%0, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%0, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); + +#define StoreW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tswl\t%1, 3(%2)\n" \ + "2:\tswr\t%1, (%2)\n\t" \ + "li\t%0, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%0, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); + +#define StoreDW(addr, value, res) \ + __asm__ __volatile__ ( \ + "1:\tsdl\t%1, 7(%2)\n" \ + "2:\tsdr\t%1, (%2)\n\t" \ + "li\t%0, 0\n" \ + "3:\n\t" \ + ".insn\n\t" \ + ".section\t.fixup,\"ax\"\n\t" \ + "4:\tli\t%0, %3\n\t" \ + "j\t3b\n\t" \ + ".previous\n\t" \ + ".section\t__ex_table,\"a\"\n\t" \ + STR(PTR)"\t1b, 4b\n\t" \ + STR(PTR)"\t2b, 4b\n\t" \ + ".previous" \ + : "=r" (res) \ + : "r" (value), "r" (addr), "i" (-EFAULT)); +#endif + static void emulate_load_store_insn(struct pt_regs *regs, void __user *addr, unsigned int __user *pc) { union mips_instruction insn; unsigned long value; unsigned int res; + unsigned long origpc; + unsigned long orig31; + void __user *fault_addr = NULL; + + origpc = (unsigned long)pc; + orig31 = regs->regs[31]; perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0); @@ -117,22 +441,22 @@ static void emulate_load_store_insn(struct pt_regs *regs, __get_user(insn.word, pc); switch (insn.i_format.opcode) { - /* - * These are instructions that a compiler doesn't generate. We - * can assume therefore that the code is MIPS-aware and - * really buggy. Emulating these instructions would break the - * semantics anyway. - */ + /* + * These are instructions that a compiler doesn't generate. We + * can assume therefore that the code is MIPS-aware and + * really buggy. Emulating these instructions would break the + * semantics anyway. + */ case ll_op: case lld_op: case sc_op: case scd_op: - /* - * For these instructions the only way to create an address - * error is an attempted access to kernel/supervisor address - * space. - */ + /* + * For these instructions the only way to create an address + * error is an attempted access to kernel/supervisor address + * space. + */ case ldl_op: case ldr_op: case lwl_op: @@ -146,36 +470,15 @@ static void emulate_load_store_insn(struct pt_regs *regs, case sb_op: goto sigbus; - /* - * The remaining opcodes are the ones that are really of interest. - */ + /* + * The remaining opcodes are the ones that are really of + * interest. + */ case lh_op: if (!access_ok(VERIFY_READ, addr, 2)) goto sigbus; - __asm__ __volatile__ (".set\tnoat\n" -#ifdef __BIG_ENDIAN - "1:\tlb\t%0, 0(%2)\n" - "2:\tlbu\t$1, 1(%2)\n\t" -#endif -#ifdef __LITTLE_ENDIAN - "1:\tlb\t%0, 1(%2)\n" - "2:\tlbu\t$1, 0(%2)\n\t" -#endif - "sll\t%0, 0x8\n\t" - "or\t%0, $1\n\t" - "li\t%1, 0\n" - "3:\t.set\tat\n\t" - ".section\t.fixup,\"ax\"\n\t" - "4:\tli\t%1, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=&r" (value), "=r" (res) - : "r" (addr), "i" (-EFAULT)); + LoadHW(addr, value, res); if (res) goto fault; compute_return_epc(regs); @@ -186,26 +489,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_READ, addr, 4)) goto sigbus; - __asm__ __volatile__ ( -#ifdef __BIG_ENDIAN - "1:\tlwl\t%0, (%2)\n" - "2:\tlwr\t%0, 3(%2)\n\t" -#endif -#ifdef __LITTLE_ENDIAN - "1:\tlwl\t%0, 3(%2)\n" - "2:\tlwr\t%0, (%2)\n\t" -#endif - "li\t%1, 0\n" - "3:\t.section\t.fixup,\"ax\"\n\t" - "4:\tli\t%1, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=&r" (value), "=r" (res) - : "r" (addr), "i" (-EFAULT)); + LoadW(addr, value, res); if (res) goto fault; compute_return_epc(regs); @@ -216,30 +500,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_READ, addr, 2)) goto sigbus; - __asm__ __volatile__ ( - ".set\tnoat\n" -#ifdef __BIG_ENDIAN - "1:\tlbu\t%0, 0(%2)\n" - "2:\tlbu\t$1, 1(%2)\n\t" -#endif -#ifdef __LITTLE_ENDIAN - "1:\tlbu\t%0, 1(%2)\n" - "2:\tlbu\t$1, 0(%2)\n\t" -#endif - "sll\t%0, 0x8\n\t" - "or\t%0, $1\n\t" - "li\t%1, 0\n" - "3:\t.set\tat\n\t" - ".section\t.fixup,\"ax\"\n\t" - "4:\tli\t%1, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=&r" (value), "=r" (res) - : "r" (addr), "i" (-EFAULT)); + LoadHWU(addr, value, res); if (res) goto fault; compute_return_epc(regs); @@ -258,28 +519,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_READ, addr, 4)) goto sigbus; - __asm__ __volatile__ ( -#ifdef __BIG_ENDIAN - "1:\tlwl\t%0, (%2)\n" - "2:\tlwr\t%0, 3(%2)\n\t" -#endif -#ifdef __LITTLE_ENDIAN - "1:\tlwl\t%0, 3(%2)\n" - "2:\tlwr\t%0, (%2)\n\t" -#endif - "dsll\t%0, %0, 32\n\t" - "dsrl\t%0, %0, 32\n\t" - "li\t%1, 0\n" - "3:\t.section\t.fixup,\"ax\"\n\t" - "4:\tli\t%1, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=&r" (value), "=r" (res) - : "r" (addr), "i" (-EFAULT)); + LoadWU(addr, value, res); if (res) goto fault; compute_return_epc(regs); @@ -302,26 +542,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_READ, addr, 8)) goto sigbus; - __asm__ __volatile__ ( -#ifdef __BIG_ENDIAN - "1:\tldl\t%0, (%2)\n" - "2:\tldr\t%0, 7(%2)\n\t" -#endif -#ifdef __LITTLE_ENDIAN - "1:\tldl\t%0, 7(%2)\n" - "2:\tldr\t%0, (%2)\n\t" -#endif - "li\t%1, 0\n" - "3:\t.section\t.fixup,\"ax\"\n\t" - "4:\tli\t%1, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=&r" (value), "=r" (res) - : "r" (addr), "i" (-EFAULT)); + LoadDW(addr, value, res); if (res) goto fault; compute_return_epc(regs); @@ -336,68 +557,22 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_WRITE, addr, 2)) goto sigbus; + compute_return_epc(regs); value = regs->regs[insn.i_format.rt]; - __asm__ __volatile__ ( -#ifdef __BIG_ENDIAN - ".set\tnoat\n" - "1:\tsb\t%1, 1(%2)\n\t" - "srl\t$1, %1, 0x8\n" - "2:\tsb\t$1, 0(%2)\n\t" - ".set\tat\n\t" -#endif -#ifdef __LITTLE_ENDIAN - ".set\tnoat\n" - "1:\tsb\t%1, 0(%2)\n\t" - "srl\t$1,%1, 0x8\n" - "2:\tsb\t$1, 1(%2)\n\t" - ".set\tat\n\t" -#endif - "li\t%0, 0\n" - "3:\n\t" - ".section\t.fixup,\"ax\"\n\t" - "4:\tli\t%0, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=r" (res) - : "r" (value), "r" (addr), "i" (-EFAULT)); + StoreHW(addr, value, res); if (res) goto fault; - compute_return_epc(regs); break; case sw_op: if (!access_ok(VERIFY_WRITE, addr, 4)) goto sigbus; + compute_return_epc(regs); value = regs->regs[insn.i_format.rt]; - __asm__ __volatile__ ( -#ifdef __BIG_ENDIAN - "1:\tswl\t%1,(%2)\n" - "2:\tswr\t%1, 3(%2)\n\t" -#endif -#ifdef __LITTLE_ENDIAN - "1:\tswl\t%1, 3(%2)\n" - "2:\tswr\t%1, (%2)\n\t" -#endif - "li\t%0, 0\n" - "3:\n\t" - ".section\t.fixup,\"ax\"\n\t" - "4:\tli\t%0, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=r" (res) - : "r" (value), "r" (addr), "i" (-EFAULT)); + StoreW(addr, value, res); if (res) goto fault; - compute_return_epc(regs); break; case sd_op: @@ -412,31 +587,11 @@ static void emulate_load_store_insn(struct pt_regs *regs, if (!access_ok(VERIFY_WRITE, addr, 8)) goto sigbus; + compute_return_epc(regs); value = regs->regs[insn.i_format.rt]; - __asm__ __volatile__ ( -#ifdef __BIG_ENDIAN - "1:\tsdl\t%1,(%2)\n" - "2:\tsdr\t%1, 7(%2)\n\t" -#endif -#ifdef __LITTLE_ENDIAN - "1:\tsdl\t%1, 7(%2)\n" - "2:\tsdr\t%1, (%2)\n\t" -#endif - "li\t%0, 0\n" - "3:\n\t" - ".section\t.fixup,\"ax\"\n\t" - "4:\tli\t%0, %3\n\t" - "j\t3b\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b, 4b\n\t" - STR(PTR)"\t2b, 4b\n\t" - ".previous" - : "=r" (res) - : "r" (value), "r" (addr), "i" (-EFAULT)); + StoreDW(addr, value, res); if (res) goto fault; - compute_return_epc(regs); break; #endif /* CONFIG_64BIT */ @@ -447,10 +602,21 @@ static void emulate_load_store_insn(struct pt_regs *regs, case ldc1_op: case swc1_op: case sdc1_op: - /* - * I herewith declare: this does not happen. So send SIGBUS. - */ - goto sigbus; + die_if_kernel("Unaligned FP access in kernel code", regs); + BUG_ON(!used_math()); + BUG_ON(!is_fpu_owner()); + + lose_fpu(1); /* Save FPU state for the emulator. */ + res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, + &fault_addr); + own_fpu(1); /* Restore FPU state. */ + + /* Signal if something went wrong. */ + process_fpemu_return(res, fault_addr); + + if (res == 0) + break; + return; /* * COP2 is available to implementor for application specific use. @@ -488,6 +654,9 @@ static void emulate_load_store_insn(struct pt_regs *regs, return; fault: + /* roll back jump/branch */ + regs->cp0_epc = origpc; + regs->regs[31] = orig31; /* Did we have an exception handler installed? */ if (fixup_exception(regs)) return; @@ -504,10 +673,881 @@ sigbus: return; sigill: - die_if_kernel("Unhandled kernel unaligned access or invalid instruction", regs); + die_if_kernel + ("Unhandled kernel unaligned access or invalid instruction", regs); force_sig(SIGILL, current); } +/* Recode table from 16-bit register notation to 32-bit GPR. */ +const int reg16to32[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; + +/* Recode table from 16-bit STORE register notation to 32-bit GPR. */ +const int reg16to32st[] = { 0, 17, 2, 3, 4, 5, 6, 7 }; + +void emulate_load_store_microMIPS(struct pt_regs *regs, void __user * addr) +{ + unsigned long value; + unsigned int res; + int i; + unsigned int reg = 0, rvar; + unsigned long orig31; + u16 __user *pc16; + u16 halfword; + unsigned int word; + unsigned long origpc, contpc; + union mips_instruction insn; + struct mm_decoded_insn mminsn; + void __user *fault_addr = NULL; + + origpc = regs->cp0_epc; + orig31 = regs->regs[31]; + + mminsn.micro_mips_mode = 1; + + /* + * This load never faults. + */ + pc16 = (unsigned short __user *)msk_isa16_mode(regs->cp0_epc); + __get_user(halfword, pc16); + pc16++; + contpc = regs->cp0_epc + 2; + word = ((unsigned int)halfword << 16); + mminsn.pc_inc = 2; + + if (!mm_insn_16bit(halfword)) { + __get_user(halfword, pc16); + pc16++; + contpc = regs->cp0_epc + 4; + mminsn.pc_inc = 4; + word |= halfword; + } + mminsn.insn = word; + + if (get_user(halfword, pc16)) + goto fault; + mminsn.next_pc_inc = 2; + word = ((unsigned int)halfword << 16); + + if (!mm_insn_16bit(halfword)) { + pc16++; + if (get_user(halfword, pc16)) + goto fault; + mminsn.next_pc_inc = 4; + word |= halfword; + } + mminsn.next_insn = word; + + insn = (union mips_instruction)(mminsn.insn); + if (mm_isBranchInstr(regs, mminsn, &contpc)) + insn = (union mips_instruction)(mminsn.next_insn); + + /* Parse instruction to find what to do */ + + switch (insn.mm_i_format.opcode) { + + case mm_pool32a_op: + switch (insn.mm_x_format.func) { + case mm_lwxs_op: + reg = insn.mm_x_format.rd; + goto loadW; + } + + goto sigbus; + + case mm_pool32b_op: + switch (insn.mm_m_format.func) { + case mm_lwp_func: + reg = insn.mm_m_format.rd; + if (reg == 31) + goto sigbus; + + if (!access_ok(VERIFY_READ, addr, 8)) + goto sigbus; + + LoadW(addr, value, res); + if (res) + goto fault; + regs->regs[reg] = value; + addr += 4; + LoadW(addr, value, res); + if (res) + goto fault; + regs->regs[reg + 1] = value; + goto success; + + case mm_swp_func: + reg = insn.mm_m_format.rd; + if (reg == 31) + goto sigbus; + + if (!access_ok(VERIFY_WRITE, addr, 8)) + goto sigbus; + + value = regs->regs[reg]; + StoreW(addr, value, res); + if (res) + goto fault; + addr += 4; + value = regs->regs[reg + 1]; + StoreW(addr, value, res); + if (res) + goto fault; + goto success; + + case mm_ldp_func: +#ifdef CONFIG_64BIT + reg = insn.mm_m_format.rd; + if (reg == 31) + goto sigbus; + + if (!access_ok(VERIFY_READ, addr, 16)) + goto sigbus; + + LoadDW(addr, value, res); + if (res) + goto fault; + regs->regs[reg] = value; + addr += 8; + LoadDW(addr, value, res); + if (res) + goto fault; + regs->regs[reg + 1] = value; + goto success; +#endif /* CONFIG_64BIT */ + + goto sigill; + + case mm_sdp_func: +#ifdef CONFIG_64BIT + reg = insn.mm_m_format.rd; + if (reg == 31) + goto sigbus; + + if (!access_ok(VERIFY_WRITE, addr, 16)) + goto sigbus; + + value = regs->regs[reg]; + StoreDW(addr, value, res); + if (res) + goto fault; + addr += 8; + value = regs->regs[reg + 1]; + StoreDW(addr, value, res); + if (res) + goto fault; + goto success; +#endif /* CONFIG_64BIT */ + + goto sigill; + + case mm_lwm32_func: + reg = insn.mm_m_format.rd; + rvar = reg & 0xf; + if ((rvar > 9) || !reg) + goto sigill; + if (reg & 0x10) { + if (!access_ok + (VERIFY_READ, addr, 4 * (rvar + 1))) + goto sigbus; + } else { + if (!access_ok(VERIFY_READ, addr, 4 * rvar)) + goto sigbus; + } + if (rvar == 9) + rvar = 8; + for (i = 16; rvar; rvar--, i++) { + LoadW(addr, value, res); + if (res) + goto fault; + addr += 4; + regs->regs[i] = value; + } + if ((reg & 0xf) == 9) { + LoadW(addr, value, res); + if (res) + goto fault; + addr += 4; + regs->regs[30] = value; + } + if (reg & 0x10) { + LoadW(addr, value, res); + if (res) + goto fault; + regs->regs[31] = value; + } + goto success; + + case mm_swm32_func: + reg = insn.mm_m_format.rd; + rvar = reg & 0xf; + if ((rvar > 9) || !reg) + goto sigill; + if (reg & 0x10) { + if (!access_ok + (VERIFY_WRITE, addr, 4 * (rvar + 1))) + goto sigbus; + } else { + if (!access_ok(VERIFY_WRITE, addr, 4 * rvar)) + goto sigbus; + } + if (rvar == 9) + rvar = 8; + for (i = 16; rvar; rvar--, i++) { + value = regs->regs[i]; + StoreW(addr, value, res); + if (res) + goto fault; + addr += 4; + } + if ((reg & 0xf) == 9) { + value = regs->regs[30]; + StoreW(addr, value, res); + if (res) + goto fault; + addr += 4; + } + if (reg & 0x10) { + value = regs->regs[31]; + StoreW(addr, value, res); + if (res) + goto fault; + } + goto success; + + case mm_ldm_func: +#ifdef CONFIG_64BIT + reg = insn.mm_m_format.rd; + rvar = reg & 0xf; + if ((rvar > 9) || !reg) + goto sigill; + if (reg & 0x10) { + if (!access_ok + (VERIFY_READ, addr, 8 * (rvar + 1))) + goto sigbus; + } else { + if (!access_ok(VERIFY_READ, addr, 8 * rvar)) + goto sigbus; + } + if (rvar == 9) + rvar = 8; + + for (i = 16; rvar; rvar--, i++) { + LoadDW(addr, value, res); + if (res) + goto fault; + addr += 4; + regs->regs[i] = value; + } + if ((reg & 0xf) == 9) { + LoadDW(addr, value, res); + if (res) + goto fault; + addr += 8; + regs->regs[30] = value; + } + if (reg & 0x10) { + LoadDW(addr, value, res); + if (res) + goto fault; + regs->regs[31] = value; + } + goto success; +#endif /* CONFIG_64BIT */ + + goto sigill; + + case mm_sdm_func: +#ifdef CONFIG_64BIT + reg = insn.mm_m_format.rd; + rvar = reg & 0xf; + if ((rvar > 9) || !reg) + goto sigill; + if (reg & 0x10) { + if (!access_ok + (VERIFY_WRITE, addr, 8 * (rvar + 1))) + goto sigbus; + } else { + if (!access_ok(VERIFY_WRITE, addr, 8 * rvar)) + goto sigbus; + } + if (rvar == 9) + rvar = 8; + + for (i = 16; rvar; rvar--, i++) { + value = regs->regs[i]; + StoreDW(addr, value, res); + if (res) + goto fault; + addr += 8; + } + if ((reg & 0xf) == 9) { + value = regs->regs[30]; + StoreDW(addr, value, res); + if (res) + goto fault; + addr += 8; + } + if (reg & 0x10) { + value = regs->regs[31]; + StoreDW(addr, value, res); + if (res) + goto fault; + } + goto success; +#endif /* CONFIG_64BIT */ + + goto sigill; + + /* LWC2, SWC2, LDC2, SDC2 are not serviced */ + } + + goto sigbus; + + case mm_pool32c_op: + switch (insn.mm_m_format.func) { + case mm_lwu_func: + reg = insn.mm_m_format.rd; + goto loadWU; + } + + /* LL,SC,LLD,SCD are not serviced */ + goto sigbus; + + case mm_pool32f_op: + switch (insn.mm_x_format.func) { + case mm_lwxc1_func: + case mm_swxc1_func: + case mm_ldxc1_func: + case mm_sdxc1_func: + goto fpu_emul; + } + + goto sigbus; + + case mm_ldc132_op: + case mm_sdc132_op: + case mm_lwc132_op: + case mm_swc132_op: +fpu_emul: + /* roll back jump/branch */ + regs->cp0_epc = origpc; + regs->regs[31] = orig31; + + die_if_kernel("Unaligned FP access in kernel code", regs); + BUG_ON(!used_math()); + BUG_ON(!is_fpu_owner()); + + lose_fpu(1); /* save the FPU state for the emulator */ + res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, + &fault_addr); + own_fpu(1); /* restore FPU state */ + + /* If something went wrong, signal */ + process_fpemu_return(res, fault_addr); + + if (res == 0) + goto success; + return; + + case mm_lh32_op: + reg = insn.mm_i_format.rt; + goto loadHW; + + case mm_lhu32_op: + reg = insn.mm_i_format.rt; + goto loadHWU; + + case mm_lw32_op: + reg = insn.mm_i_format.rt; + goto loadW; + + case mm_sh32_op: + reg = insn.mm_i_format.rt; + goto storeHW; + + case mm_sw32_op: + reg = insn.mm_i_format.rt; + goto storeW; + + case mm_ld32_op: + reg = insn.mm_i_format.rt; + goto loadDW; + + case mm_sd32_op: + reg = insn.mm_i_format.rt; + goto storeDW; + + case mm_pool16c_op: + switch (insn.mm16_m_format.func) { + case mm_lwm16_op: + reg = insn.mm16_m_format.rlist; + rvar = reg + 1; + if (!access_ok(VERIFY_READ, addr, 4 * rvar)) + goto sigbus; + + for (i = 16; rvar; rvar--, i++) { + LoadW(addr, value, res); + if (res) + goto fault; + addr += 4; + regs->regs[i] = value; + } + LoadW(addr, value, res); + if (res) + goto fault; + regs->regs[31] = value; + + goto success; + + case mm_swm16_op: + reg = insn.mm16_m_format.rlist; + rvar = reg + 1; + if (!access_ok(VERIFY_WRITE, addr, 4 * rvar)) + goto sigbus; + + for (i = 16; rvar; rvar--, i++) { + value = regs->regs[i]; + StoreW(addr, value, res); + if (res) + goto fault; + addr += 4; + } + value = regs->regs[31]; + StoreW(addr, value, res); + if (res) + goto fault; + + goto success; + + } + + goto sigbus; + + case mm_lhu16_op: + reg = reg16to32[insn.mm16_rb_format.rt]; + goto loadHWU; + + case mm_lw16_op: + reg = reg16to32[insn.mm16_rb_format.rt]; + goto loadW; + + case mm_sh16_op: + reg = reg16to32st[insn.mm16_rb_format.rt]; + goto storeHW; + + case mm_sw16_op: + reg = reg16to32st[insn.mm16_rb_format.rt]; + goto storeW; + + case mm_lwsp16_op: + reg = insn.mm16_r5_format.rt; + goto loadW; + + case mm_swsp16_op: + reg = insn.mm16_r5_format.rt; + goto storeW; + + case mm_lwgp16_op: + reg = reg16to32[insn.mm16_r3_format.rt]; + goto loadW; + + default: + goto sigill; + } + +loadHW: + if (!access_ok(VERIFY_READ, addr, 2)) + goto sigbus; + + LoadHW(addr, value, res); + if (res) + goto fault; + regs->regs[reg] = value; + goto success; + +loadHWU: + if (!access_ok(VERIFY_READ, addr, 2)) + goto sigbus; + + LoadHWU(addr, value, res); + if (res) + goto fault; + regs->regs[reg] = value; + goto success; + +loadW: + if (!access_ok(VERIFY_READ, addr, 4)) + goto sigbus; + + LoadW(addr, value, res); + if (res) + goto fault; + regs->regs[reg] = value; + goto success; + +loadWU: +#ifdef CONFIG_64BIT + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (!access_ok(VERIFY_READ, addr, 4)) + goto sigbus; + + LoadWU(addr, value, res); + if (res) + goto fault; + regs->regs[reg] = value; + goto success; +#endif /* CONFIG_64BIT */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; + +loadDW: +#ifdef CONFIG_64BIT + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (!access_ok(VERIFY_READ, addr, 8)) + goto sigbus; + + LoadDW(addr, value, res); + if (res) + goto fault; + regs->regs[reg] = value; + goto success; +#endif /* CONFIG_64BIT */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; + +storeHW: + if (!access_ok(VERIFY_WRITE, addr, 2)) + goto sigbus; + + value = regs->regs[reg]; + StoreHW(addr, value, res); + if (res) + goto fault; + goto success; + +storeW: + if (!access_ok(VERIFY_WRITE, addr, 4)) + goto sigbus; + + value = regs->regs[reg]; + StoreW(addr, value, res); + if (res) + goto fault; + goto success; + +storeDW: +#ifdef CONFIG_64BIT + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (!access_ok(VERIFY_WRITE, addr, 8)) + goto sigbus; + + value = regs->regs[reg]; + StoreDW(addr, value, res); + if (res) + goto fault; + goto success; +#endif /* CONFIG_64BIT */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; + +success: + regs->cp0_epc = contpc; /* advance or branch */ + +#ifdef CONFIG_DEBUG_FS + unaligned_instructions++; +#endif + return; + +fault: + /* roll back jump/branch */ + regs->cp0_epc = origpc; + regs->regs[31] = orig31; + /* Did we have an exception handler installed? */ + if (fixup_exception(regs)) + return; + + die_if_kernel("Unhandled kernel unaligned access", regs); + force_sig(SIGSEGV, current); + + return; + +sigbus: + die_if_kernel("Unhandled kernel unaligned access", regs); + force_sig(SIGBUS, current); + + return; + +sigill: + die_if_kernel + ("Unhandled kernel unaligned access or invalid instruction", regs); + force_sig(SIGILL, current); +} + +static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr) +{ + unsigned long value; + unsigned int res; + int reg; + unsigned long orig31; + u16 __user *pc16; + unsigned long origpc; + union mips16e_instruction mips16inst, oldinst; + + origpc = regs->cp0_epc; + orig31 = regs->regs[31]; + pc16 = (unsigned short __user *)msk_isa16_mode(origpc); + /* + * This load never faults. + */ + __get_user(mips16inst.full, pc16); + oldinst = mips16inst; + + /* skip EXTEND instruction */ + if (mips16inst.ri.opcode == MIPS16e_extend_op) { + pc16++; + __get_user(mips16inst.full, pc16); + } else if (delay_slot(regs)) { + /* skip jump instructions */ + /* JAL/JALX are 32 bits but have OPCODE in first short int */ + if (mips16inst.ri.opcode == MIPS16e_jal_op) + pc16++; + pc16++; + if (get_user(mips16inst.full, pc16)) + goto sigbus; + } + + switch (mips16inst.ri.opcode) { + case MIPS16e_i64_op: /* I64 or RI64 instruction */ + switch (mips16inst.i64.func) { /* I64/RI64 func field check */ + case MIPS16e_ldpc_func: + case MIPS16e_ldsp_func: + reg = reg16to32[mips16inst.ri64.ry]; + goto loadDW; + + case MIPS16e_sdsp_func: + reg = reg16to32[mips16inst.ri64.ry]; + goto writeDW; + + case MIPS16e_sdrasp_func: + reg = 29; /* GPRSP */ + goto writeDW; + } + + goto sigbus; + + case MIPS16e_swsp_op: + case MIPS16e_lwpc_op: + case MIPS16e_lwsp_op: + reg = reg16to32[mips16inst.ri.rx]; + break; + + case MIPS16e_i8_op: + if (mips16inst.i8.func != MIPS16e_swrasp_func) + goto sigbus; + reg = 29; /* GPRSP */ + break; + + default: + reg = reg16to32[mips16inst.rri.ry]; + break; + } + + switch (mips16inst.ri.opcode) { + + case MIPS16e_lb_op: + case MIPS16e_lbu_op: + case MIPS16e_sb_op: + goto sigbus; + + case MIPS16e_lh_op: + if (!access_ok(VERIFY_READ, addr, 2)) + goto sigbus; + + LoadHW(addr, value, res); + if (res) + goto fault; + MIPS16e_compute_return_epc(regs, &oldinst); + regs->regs[reg] = value; + break; + + case MIPS16e_lhu_op: + if (!access_ok(VERIFY_READ, addr, 2)) + goto sigbus; + + LoadHWU(addr, value, res); + if (res) + goto fault; + MIPS16e_compute_return_epc(regs, &oldinst); + regs->regs[reg] = value; + break; + + case MIPS16e_lw_op: + case MIPS16e_lwpc_op: + case MIPS16e_lwsp_op: + if (!access_ok(VERIFY_READ, addr, 4)) + goto sigbus; + + LoadW(addr, value, res); + if (res) + goto fault; + MIPS16e_compute_return_epc(regs, &oldinst); + regs->regs[reg] = value; + break; + + case MIPS16e_lwu_op: +#ifdef CONFIG_64BIT + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (!access_ok(VERIFY_READ, addr, 4)) + goto sigbus; + + LoadWU(addr, value, res); + if (res) + goto fault; + MIPS16e_compute_return_epc(regs, &oldinst); + regs->regs[reg] = value; + break; +#endif /* CONFIG_64BIT */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; + + case MIPS16e_ld_op: +loadDW: +#ifdef CONFIG_64BIT + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (!access_ok(VERIFY_READ, addr, 8)) + goto sigbus; + + LoadDW(addr, value, res); + if (res) + goto fault; + MIPS16e_compute_return_epc(regs, &oldinst); + regs->regs[reg] = value; + break; +#endif /* CONFIG_64BIT */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; + + case MIPS16e_sh_op: + if (!access_ok(VERIFY_WRITE, addr, 2)) + goto sigbus; + + MIPS16e_compute_return_epc(regs, &oldinst); + value = regs->regs[reg]; + StoreHW(addr, value, res); + if (res) + goto fault; + break; + + case MIPS16e_sw_op: + case MIPS16e_swsp_op: + case MIPS16e_i8_op: /* actually - MIPS16e_swrasp_func */ + if (!access_ok(VERIFY_WRITE, addr, 4)) + goto sigbus; + + MIPS16e_compute_return_epc(regs, &oldinst); + value = regs->regs[reg]; + StoreW(addr, value, res); + if (res) + goto fault; + break; + + case MIPS16e_sd_op: +writeDW: +#ifdef CONFIG_64BIT + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (!access_ok(VERIFY_WRITE, addr, 8)) + goto sigbus; + + MIPS16e_compute_return_epc(regs, &oldinst); + value = regs->regs[reg]; + StoreDW(addr, value, res); + if (res) + goto fault; + break; +#endif /* CONFIG_64BIT */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; + + default: + /* + * Pheeee... We encountered an yet unknown instruction or + * cache coherence problem. Die sucker, die ... + */ + goto sigill; + } + +#ifdef CONFIG_DEBUG_FS + unaligned_instructions++; +#endif + + return; + +fault: + /* roll back jump/branch */ + regs->cp0_epc = origpc; + regs->regs[31] = orig31; + /* Did we have an exception handler installed? */ + if (fixup_exception(regs)) + return; + + die_if_kernel("Unhandled kernel unaligned access", regs); + force_sig(SIGSEGV, current); + + return; + +sigbus: + die_if_kernel("Unhandled kernel unaligned access", regs); + force_sig(SIGBUS, current); + + return; + +sigill: + die_if_kernel + ("Unhandled kernel unaligned access or invalid instruction", regs); + force_sig(SIGILL, current); +} asmlinkage void do_ade(struct pt_regs *regs) { unsigned int __user *pc; @@ -517,23 +1557,62 @@ asmlinkage void do_ade(struct pt_regs *regs) 1, regs, regs->cp0_badvaddr); /* * Did we catch a fault trying to load an instruction? - * Or are we running in MIPS16 mode? */ - if ((regs->cp0_badvaddr == regs->cp0_epc) || (regs->cp0_epc & 0x1)) + if (regs->cp0_badvaddr == regs->cp0_epc) goto sigbus; - pc = (unsigned int __user *) exception_epc(regs); if (user_mode(regs) && !test_thread_flag(TIF_FIXADE)) goto sigbus; if (unaligned_action == UNALIGNED_ACTION_SIGNAL) goto sigbus; - else if (unaligned_action == UNALIGNED_ACTION_SHOW) - show_registers(regs); /* * Do branch emulation only if we didn't forward the exception. * This is all so but ugly ... */ + + /* + * Are we running in microMIPS mode? + */ + if (get_isa16_mode(regs->cp0_epc)) { + /* + * Did we catch a fault trying to load an instruction in + * 16-bit mode? + */ + if (regs->cp0_badvaddr == msk_isa16_mode(regs->cp0_epc)) + goto sigbus; + if (unaligned_action == UNALIGNED_ACTION_SHOW) + show_registers(regs); + + if (cpu_has_mmips) { + seg = get_fs(); + if (!user_mode(regs)) + set_fs(KERNEL_DS); + emulate_load_store_microMIPS(regs, + (void __user *)regs->cp0_badvaddr); + set_fs(seg); + + return; + } + + if (cpu_has_mips16) { + seg = get_fs(); + if (!user_mode(regs)) + set_fs(KERNEL_DS); + emulate_load_store_MIPS16e(regs, + (void __user *)regs->cp0_badvaddr); + set_fs(seg); + + return; + } + + goto sigbus; + } + + if (unaligned_action == UNALIGNED_ACTION_SHOW) + show_registers(regs); + pc = (unsigned int __user *)exception_epc(regs); + seg = get_fs(); if (!user_mode(regs)) set_fs(KERNEL_DS); diff --git a/arch/mips/kvm/00README.txt b/arch/mips/kvm/00README.txt new file mode 100644 index 000000000000..51617e481aa3 --- /dev/null +++ b/arch/mips/kvm/00README.txt @@ -0,0 +1,31 @@ +KVM/MIPS Trap & Emulate Release Notes +===================================== + +(1) KVM/MIPS should support MIPS32R2 and beyond. It has been tested on the following platforms: + Malta Board with FPGA based 34K + Sigma Designs TangoX board with a 24K based 8654 SoC. + Malta Board with 74K @ 1GHz + +(2) Both Guest kernel and Guest Userspace execute in UM. + Guest User address space: 0x00000000 -> 0x40000000 + Guest Kernel Unmapped: 0x40000000 -> 0x60000000 + Guest Kernel Mapped: 0x60000000 -> 0x80000000 + + Guest Usermode virtual memory is limited to 1GB. + +(2) 16K Page Sizes: Both Host Kernel and Guest Kernel should have the same page size, currently at least 16K. + Note that due to cache aliasing issues, 4K page sizes are NOT supported. + +(3) No HugeTLB Support + Both the host kernel and Guest kernel should have the page size set to 16K. + This will be implemented in a future release. + +(4) KVM/MIPS does not have support for SMP Guests + Linux-3.7-rc2 based SMP guest hangs due to the following code sequence in the generated TLB handlers: + LL/TLBP/SC. Since the TLBP instruction causes a trap the reservation gets cleared + when we ERET back to the guest. This causes the guest to hang in an infinite loop. + This will be fixed in a future release. + +(5) Use Host FPU + Currently KVM/MIPS emulates a 24K CPU without a FPU. + This will be fixed in a future release diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig new file mode 100644 index 000000000000..2c15590e55f7 --- /dev/null +++ b/arch/mips/kvm/Kconfig @@ -0,0 +1,49 @@ +# +# KVM configuration +# +source "virt/kvm/Kconfig" + +menuconfig VIRTUALIZATION + bool "Virtualization" + depends on HAVE_KVM + ---help--- + Say Y here to get to see options for using your Linux host to run + other operating systems inside virtual machines (guests). + This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and disabled. + +if VIRTUALIZATION + +config KVM + tristate "Kernel-based Virtual Machine (KVM) support" + depends on HAVE_KVM + select PREEMPT_NOTIFIERS + select ANON_INODES + select KVM_MMIO + ---help--- + Support for hosting Guest kernels. + Currently supported on MIPS32 processors. + +config KVM_MIPS_DYN_TRANS + bool "KVM/MIPS: Dynamic binary translation to reduce traps" + depends on KVM + ---help--- + When running in Trap & Emulate mode patch privileged + instructions to reduce the number of traps. + + If unsure, say Y. + +config KVM_MIPS_DEBUG_COP0_COUNTERS + bool "Maintain counters for COP0 accesses" + depends on KVM + ---help--- + Maintain statistics for Guest COP0 accesses. + A histogram of COP0 accesses is printed when the VM is + shutdown. + + If unsure, say N. + +source drivers/vhost/Kconfig + +endif # VIRTUALIZATION diff --git a/arch/mips/kvm/Makefile b/arch/mips/kvm/Makefile new file mode 100644 index 000000000000..78d87bbc99db --- /dev/null +++ b/arch/mips/kvm/Makefile @@ -0,0 +1,13 @@ +# Makefile for KVM support for MIPS +# + +common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) + +EXTRA_CFLAGS += -Ivirt/kvm -Iarch/mips/kvm + +kvm-objs := $(common-objs) kvm_mips.o kvm_mips_emul.o kvm_locore.o \ + kvm_mips_int.o kvm_mips_stats.o kvm_mips_commpage.o \ + kvm_mips_dyntrans.o kvm_trap_emul.o + +obj-$(CONFIG_KVM) += kvm.o +obj-y += kvm_cb.o kvm_tlb.o diff --git a/arch/mips/kvm/kvm_cb.c b/arch/mips/kvm/kvm_cb.c new file mode 100644 index 000000000000..313c2e37b978 --- /dev/null +++ b/arch/mips/kvm/kvm_cb.c @@ -0,0 +1,14 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Authors: Yann Le Du <ledu@kymasys.com> + */ + +#include <linux/export.h> +#include <linux/kvm_host.h> + +struct kvm_mips_callbacks *kvm_mips_callbacks; +EXPORT_SYMBOL(kvm_mips_callbacks); diff --git a/arch/mips/kvm/kvm_locore.S b/arch/mips/kvm/kvm_locore.S new file mode 100644 index 000000000000..dca2aa665993 --- /dev/null +++ b/arch/mips/kvm/kvm_locore.S @@ -0,0 +1,650 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* Main entry point for the guest, exception handling. +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <asm/asm.h> +#include <asm/asmmacro.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/stackframe.h> +#include <asm/asm-offsets.h> + + +#define _C_LABEL(x) x +#define MIPSX(name) mips32_ ## name +#define CALLFRAME_SIZ 32 + +/* + * VECTOR + * exception vector entrypoint + */ +#define VECTOR(x, regmask) \ + .ent _C_LABEL(x),0; \ + EXPORT(x); + +#define VECTOR_END(x) \ + EXPORT(x); + +/* Overload, Danger Will Robinson!! */ +#define PT_HOST_ASID PT_BVADDR +#define PT_HOST_USERLOCAL PT_EPC + +#define CP0_DDATA_LO $28,3 +#define CP0_EBASE $15,1 + +#define CP0_INTCTL $12,1 +#define CP0_SRSCTL $12,2 +#define CP0_SRSMAP $12,3 +#define CP0_HWRENA $7,0 + +/* Resume Flags */ +#define RESUME_FLAG_HOST (1<<1) /* Resume host? */ + +#define RESUME_GUEST 0 +#define RESUME_HOST RESUME_FLAG_HOST + +/* + * __kvm_mips_vcpu_run: entry point to the guest + * a0: run + * a1: vcpu + */ + +FEXPORT(__kvm_mips_vcpu_run) + .set push + .set noreorder + .set noat + + /* k0/k1 not being used in host kernel context */ + addiu k1,sp, -PT_SIZE + LONG_S $0, PT_R0(k1) + LONG_S $1, PT_R1(k1) + LONG_S $2, PT_R2(k1) + LONG_S $3, PT_R3(k1) + + LONG_S $4, PT_R4(k1) + LONG_S $5, PT_R5(k1) + LONG_S $6, PT_R6(k1) + LONG_S $7, PT_R7(k1) + + LONG_S $8, PT_R8(k1) + LONG_S $9, PT_R9(k1) + LONG_S $10, PT_R10(k1) + LONG_S $11, PT_R11(k1) + LONG_S $12, PT_R12(k1) + LONG_S $13, PT_R13(k1) + LONG_S $14, PT_R14(k1) + LONG_S $15, PT_R15(k1) + LONG_S $16, PT_R16(k1) + LONG_S $17, PT_R17(k1) + + LONG_S $18, PT_R18(k1) + LONG_S $19, PT_R19(k1) + LONG_S $20, PT_R20(k1) + LONG_S $21, PT_R21(k1) + LONG_S $22, PT_R22(k1) + LONG_S $23, PT_R23(k1) + LONG_S $24, PT_R24(k1) + LONG_S $25, PT_R25(k1) + + /* XXXKYMA k0/k1 not saved, not being used if we got here through an ioctl() */ + + LONG_S $28, PT_R28(k1) + LONG_S $29, PT_R29(k1) + LONG_S $30, PT_R30(k1) + LONG_S $31, PT_R31(k1) + + /* Save hi/lo */ + mflo v0 + LONG_S v0, PT_LO(k1) + mfhi v1 + LONG_S v1, PT_HI(k1) + + /* Save host status */ + mfc0 v0, CP0_STATUS + LONG_S v0, PT_STATUS(k1) + + /* Save host ASID, shove it into the BVADDR location */ + mfc0 v1,CP0_ENTRYHI + andi v1, 0xff + LONG_S v1, PT_HOST_ASID(k1) + + /* Save DDATA_LO, will be used to store pointer to vcpu */ + mfc0 v1, CP0_DDATA_LO + LONG_S v1, PT_HOST_USERLOCAL(k1) + + /* DDATA_LO has pointer to vcpu */ + mtc0 a1,CP0_DDATA_LO + + /* Offset into vcpu->arch */ + addiu k1, a1, VCPU_HOST_ARCH + + /* Save the host stack to VCPU, used for exception processing when we exit from the Guest */ + LONG_S sp, VCPU_HOST_STACK(k1) + + /* Save the kernel gp as well */ + LONG_S gp, VCPU_HOST_GP(k1) + + /* Setup status register for running the guest in UM, interrupts are disabled */ + li k0,(ST0_EXL | KSU_USER| ST0_BEV) + mtc0 k0,CP0_STATUS + ehb + + /* load up the new EBASE */ + LONG_L k0, VCPU_GUEST_EBASE(k1) + mtc0 k0,CP0_EBASE + + /* Now that the new EBASE has been loaded, unset BEV, set interrupt mask as it was + * but make sure that timer interrupts are enabled + */ + li k0,(ST0_EXL | KSU_USER | ST0_IE) + andi v0, v0, ST0_IM + or k0, k0, v0 + mtc0 k0,CP0_STATUS + ehb + + + /* Set Guest EPC */ + LONG_L t0, VCPU_PC(k1) + mtc0 t0, CP0_EPC + +FEXPORT(__kvm_mips_load_asid) + /* Set the ASID for the Guest Kernel */ + sll t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */ + /* addresses shift to 0x80000000 */ + bltz t0, 1f /* If kernel */ + addiu t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */ + addiu t1, k1, VCPU_GUEST_USER_ASID /* else user */ +1: + /* t1: contains the base of the ASID array, need to get the cpu id */ + LONG_L t2, TI_CPU($28) /* smp_processor_id */ + sll t2, t2, 2 /* x4 */ + addu t3, t1, t2 + LONG_L k0, (t3) + andi k0, k0, 0xff + mtc0 k0,CP0_ENTRYHI + ehb + + /* Disable RDHWR access */ + mtc0 zero, CP0_HWRENA + + /* Now load up the Guest Context from VCPU */ + LONG_L $1, VCPU_R1(k1) + LONG_L $2, VCPU_R2(k1) + LONG_L $3, VCPU_R3(k1) + + LONG_L $4, VCPU_R4(k1) + LONG_L $5, VCPU_R5(k1) + LONG_L $6, VCPU_R6(k1) + LONG_L $7, VCPU_R7(k1) + + LONG_L $8, VCPU_R8(k1) + LONG_L $9, VCPU_R9(k1) + LONG_L $10, VCPU_R10(k1) + LONG_L $11, VCPU_R11(k1) + LONG_L $12, VCPU_R12(k1) + LONG_L $13, VCPU_R13(k1) + LONG_L $14, VCPU_R14(k1) + LONG_L $15, VCPU_R15(k1) + LONG_L $16, VCPU_R16(k1) + LONG_L $17, VCPU_R17(k1) + LONG_L $18, VCPU_R18(k1) + LONG_L $19, VCPU_R19(k1) + LONG_L $20, VCPU_R20(k1) + LONG_L $21, VCPU_R21(k1) + LONG_L $22, VCPU_R22(k1) + LONG_L $23, VCPU_R23(k1) + LONG_L $24, VCPU_R24(k1) + LONG_L $25, VCPU_R25(k1) + + /* k0/k1 loaded up later */ + + LONG_L $28, VCPU_R28(k1) + LONG_L $29, VCPU_R29(k1) + LONG_L $30, VCPU_R30(k1) + LONG_L $31, VCPU_R31(k1) + + /* Restore hi/lo */ + LONG_L k0, VCPU_LO(k1) + mtlo k0 + + LONG_L k0, VCPU_HI(k1) + mthi k0 + +FEXPORT(__kvm_mips_load_k0k1) + /* Restore the guest's k0/k1 registers */ + LONG_L k0, VCPU_R26(k1) + LONG_L k1, VCPU_R27(k1) + + /* Jump to guest */ + eret + .set pop + +VECTOR(MIPSX(exception), unknown) +/* + * Find out what mode we came from and jump to the proper handler. + */ + .set push + .set noat + .set noreorder + mtc0 k0, CP0_ERROREPC #01: Save guest k0 + ehb #02: + + mfc0 k0, CP0_EBASE #02: Get EBASE + srl k0, k0, 10 #03: Get rid of CPUNum + sll k0, k0, 10 #04 + LONG_S k1, 0x3000(k0) #05: Save k1 @ offset 0x3000 + addiu k0, k0, 0x2000 #06: Exception handler is installed @ offset 0x2000 + j k0 #07: jump to the function + nop #08: branch delay slot + .set push +VECTOR_END(MIPSX(exceptionEnd)) +.end MIPSX(exception) + +/* + * Generic Guest exception handler. We end up here when the guest + * does something that causes a trap to kernel mode. + * + */ +NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra) + .set push + .set noat + .set noreorder + + /* Get the VCPU pointer from DDTATA_LO */ + mfc0 k1, CP0_DDATA_LO + addiu k1, k1, VCPU_HOST_ARCH + + /* Start saving Guest context to VCPU */ + LONG_S $0, VCPU_R0(k1) + LONG_S $1, VCPU_R1(k1) + LONG_S $2, VCPU_R2(k1) + LONG_S $3, VCPU_R3(k1) + LONG_S $4, VCPU_R4(k1) + LONG_S $5, VCPU_R5(k1) + LONG_S $6, VCPU_R6(k1) + LONG_S $7, VCPU_R7(k1) + LONG_S $8, VCPU_R8(k1) + LONG_S $9, VCPU_R9(k1) + LONG_S $10, VCPU_R10(k1) + LONG_S $11, VCPU_R11(k1) + LONG_S $12, VCPU_R12(k1) + LONG_S $13, VCPU_R13(k1) + LONG_S $14, VCPU_R14(k1) + LONG_S $15, VCPU_R15(k1) + LONG_S $16, VCPU_R16(k1) + LONG_S $17,VCPU_R17(k1) + LONG_S $18, VCPU_R18(k1) + LONG_S $19, VCPU_R19(k1) + LONG_S $20, VCPU_R20(k1) + LONG_S $21, VCPU_R21(k1) + LONG_S $22, VCPU_R22(k1) + LONG_S $23, VCPU_R23(k1) + LONG_S $24, VCPU_R24(k1) + LONG_S $25, VCPU_R25(k1) + + /* Guest k0/k1 saved later */ + + LONG_S $28, VCPU_R28(k1) + LONG_S $29, VCPU_R29(k1) + LONG_S $30, VCPU_R30(k1) + LONG_S $31, VCPU_R31(k1) + + /* We need to save hi/lo and restore them on + * the way out + */ + mfhi t0 + LONG_S t0, VCPU_HI(k1) + + mflo t0 + LONG_S t0, VCPU_LO(k1) + + /* Finally save guest k0/k1 to VCPU */ + mfc0 t0, CP0_ERROREPC + LONG_S t0, VCPU_R26(k1) + + /* Get GUEST k1 and save it in VCPU */ + la t1, ~0x2ff + mfc0 t0, CP0_EBASE + and t0, t0, t1 + LONG_L t0, 0x3000(t0) + LONG_S t0, VCPU_R27(k1) + + /* Now that context has been saved, we can use other registers */ + + /* Restore vcpu */ + mfc0 a1, CP0_DDATA_LO + move s1, a1 + + /* Restore run (vcpu->run) */ + LONG_L a0, VCPU_RUN(a1) + /* Save pointer to run in s0, will be saved by the compiler */ + move s0, a0 + + + /* Save Host level EPC, BadVaddr and Cause to VCPU, useful to process the exception */ + mfc0 k0,CP0_EPC + LONG_S k0, VCPU_PC(k1) + + mfc0 k0, CP0_BADVADDR + LONG_S k0, VCPU_HOST_CP0_BADVADDR(k1) + + mfc0 k0, CP0_CAUSE + LONG_S k0, VCPU_HOST_CP0_CAUSE(k1) + + mfc0 k0, CP0_ENTRYHI + LONG_S k0, VCPU_HOST_ENTRYHI(k1) + + /* Now restore the host state just enough to run the handlers */ + + /* Swtich EBASE to the one used by Linux */ + /* load up the host EBASE */ + mfc0 v0, CP0_STATUS + + .set at + or k0, v0, ST0_BEV + .set noat + + mtc0 k0, CP0_STATUS + ehb + + LONG_L k0, VCPU_HOST_EBASE(k1) + mtc0 k0,CP0_EBASE + + + /* Now that the new EBASE has been loaded, unset BEV and KSU_USER */ + .set at + and v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE) + or v0, v0, ST0_CU0 + .set noat + mtc0 v0, CP0_STATUS + ehb + + /* Load up host GP */ + LONG_L gp, VCPU_HOST_GP(k1) + + /* Need a stack before we can jump to "C" */ + LONG_L sp, VCPU_HOST_STACK(k1) + + /* Saved host state */ + addiu sp,sp, -PT_SIZE + + /* XXXKYMA do we need to load the host ASID, maybe not because the + * kernel entries are marked GLOBAL, need to verify + */ + + /* Restore host DDATA_LO */ + LONG_L k0, PT_HOST_USERLOCAL(sp) + mtc0 k0, CP0_DDATA_LO + + /* Restore RDHWR access */ + la k0, 0x2000000F + mtc0 k0, CP0_HWRENA + + /* Jump to handler */ +FEXPORT(__kvm_mips_jump_to_handler) + /* XXXKYMA: not sure if this is safe, how large is the stack?? */ + /* Now jump to the kvm_mips_handle_exit() to see if we can deal with this in the kernel */ + la t9,kvm_mips_handle_exit + jalr.hb t9 + addiu sp,sp, -CALLFRAME_SIZ /* BD Slot */ + + /* Return from handler Make sure interrupts are disabled */ + di + ehb + + /* XXXKYMA: k0/k1 could have been blown away if we processed an exception + * while we were handling the exception from the guest, reload k1 + */ + move k1, s1 + addiu k1, k1, VCPU_HOST_ARCH + + /* Check return value, should tell us if we are returning to the host (handle I/O etc) + * or resuming the guest + */ + andi t0, v0, RESUME_HOST + bnez t0, __kvm_mips_return_to_host + nop + +__kvm_mips_return_to_guest: + /* Put the saved pointer to vcpu (s1) back into the DDATA_LO Register */ + mtc0 s1, CP0_DDATA_LO + + /* Load up the Guest EBASE to minimize the window where BEV is set */ + LONG_L t0, VCPU_GUEST_EBASE(k1) + + /* Switch EBASE back to the one used by KVM */ + mfc0 v1, CP0_STATUS + .set at + or k0, v1, ST0_BEV + .set noat + mtc0 k0, CP0_STATUS + ehb + mtc0 t0,CP0_EBASE + + /* Setup status register for running guest in UM */ + .set at + or v1, v1, (ST0_EXL | KSU_USER | ST0_IE) + and v1, v1, ~ST0_CU0 + .set noat + mtc0 v1, CP0_STATUS + ehb + + + /* Set Guest EPC */ + LONG_L t0, VCPU_PC(k1) + mtc0 t0, CP0_EPC + + /* Set the ASID for the Guest Kernel */ + sll t0, t0, 1 /* with kseg0 @ 0x40000000, kernel */ + /* addresses shift to 0x80000000 */ + bltz t0, 1f /* If kernel */ + addiu t1, k1, VCPU_GUEST_KERNEL_ASID /* (BD) */ + addiu t1, k1, VCPU_GUEST_USER_ASID /* else user */ +1: + /* t1: contains the base of the ASID array, need to get the cpu id */ + LONG_L t2, TI_CPU($28) /* smp_processor_id */ + sll t2, t2, 2 /* x4 */ + addu t3, t1, t2 + LONG_L k0, (t3) + andi k0, k0, 0xff + mtc0 k0,CP0_ENTRYHI + ehb + + /* Disable RDHWR access */ + mtc0 zero, CP0_HWRENA + + /* load the guest context from VCPU and return */ + LONG_L $0, VCPU_R0(k1) + LONG_L $1, VCPU_R1(k1) + LONG_L $2, VCPU_R2(k1) + LONG_L $3, VCPU_R3(k1) + LONG_L $4, VCPU_R4(k1) + LONG_L $5, VCPU_R5(k1) + LONG_L $6, VCPU_R6(k1) + LONG_L $7, VCPU_R7(k1) + LONG_L $8, VCPU_R8(k1) + LONG_L $9, VCPU_R9(k1) + LONG_L $10, VCPU_R10(k1) + LONG_L $11, VCPU_R11(k1) + LONG_L $12, VCPU_R12(k1) + LONG_L $13, VCPU_R13(k1) + LONG_L $14, VCPU_R14(k1) + LONG_L $15, VCPU_R15(k1) + LONG_L $16, VCPU_R16(k1) + LONG_L $17, VCPU_R17(k1) + LONG_L $18, VCPU_R18(k1) + LONG_L $19, VCPU_R19(k1) + LONG_L $20, VCPU_R20(k1) + LONG_L $21, VCPU_R21(k1) + LONG_L $22, VCPU_R22(k1) + LONG_L $23, VCPU_R23(k1) + LONG_L $24, VCPU_R24(k1) + LONG_L $25, VCPU_R25(k1) + + /* $/k1 loaded later */ + LONG_L $28, VCPU_R28(k1) + LONG_L $29, VCPU_R29(k1) + LONG_L $30, VCPU_R30(k1) + LONG_L $31, VCPU_R31(k1) + +FEXPORT(__kvm_mips_skip_guest_restore) + LONG_L k0, VCPU_HI(k1) + mthi k0 + + LONG_L k0, VCPU_LO(k1) + mtlo k0 + + LONG_L k0, VCPU_R26(k1) + LONG_L k1, VCPU_R27(k1) + + eret + +__kvm_mips_return_to_host: + /* EBASE is already pointing to Linux */ + LONG_L k1, VCPU_HOST_STACK(k1) + addiu k1,k1, -PT_SIZE + + /* Restore host DDATA_LO */ + LONG_L k0, PT_HOST_USERLOCAL(k1) + mtc0 k0, CP0_DDATA_LO + + /* Restore host ASID */ + LONG_L k0, PT_HOST_ASID(sp) + andi k0, 0xff + mtc0 k0,CP0_ENTRYHI + ehb + + /* Load context saved on the host stack */ + LONG_L $0, PT_R0(k1) + LONG_L $1, PT_R1(k1) + + /* r2/v0 is the return code, shift it down by 2 (arithmetic) to recover the err code */ + sra k0, v0, 2 + move $2, k0 + + LONG_L $3, PT_R3(k1) + LONG_L $4, PT_R4(k1) + LONG_L $5, PT_R5(k1) + LONG_L $6, PT_R6(k1) + LONG_L $7, PT_R7(k1) + LONG_L $8, PT_R8(k1) + LONG_L $9, PT_R9(k1) + LONG_L $10, PT_R10(k1) + LONG_L $11, PT_R11(k1) + LONG_L $12, PT_R12(k1) + LONG_L $13, PT_R13(k1) + LONG_L $14, PT_R14(k1) + LONG_L $15, PT_R15(k1) + LONG_L $16, PT_R16(k1) + LONG_L $17, PT_R17(k1) + LONG_L $18, PT_R18(k1) + LONG_L $19, PT_R19(k1) + LONG_L $20, PT_R20(k1) + LONG_L $21, PT_R21(k1) + LONG_L $22, PT_R22(k1) + LONG_L $23, PT_R23(k1) + LONG_L $24, PT_R24(k1) + LONG_L $25, PT_R25(k1) + + /* Host k0/k1 were not saved */ + + LONG_L $28, PT_R28(k1) + LONG_L $29, PT_R29(k1) + LONG_L $30, PT_R30(k1) + + LONG_L k0, PT_HI(k1) + mthi k0 + + LONG_L k0, PT_LO(k1) + mtlo k0 + + /* Restore RDHWR access */ + la k0, 0x2000000F + mtc0 k0, CP0_HWRENA + + + /* Restore RA, which is the address we will return to */ + LONG_L ra, PT_R31(k1) + j ra + nop + + .set pop +VECTOR_END(MIPSX(GuestExceptionEnd)) +.end MIPSX(GuestException) + +MIPSX(exceptions): + #### + ##### The exception handlers. + ##### + .word _C_LABEL(MIPSX(GuestException)) # 0 + .word _C_LABEL(MIPSX(GuestException)) # 1 + .word _C_LABEL(MIPSX(GuestException)) # 2 + .word _C_LABEL(MIPSX(GuestException)) # 3 + .word _C_LABEL(MIPSX(GuestException)) # 4 + .word _C_LABEL(MIPSX(GuestException)) # 5 + .word _C_LABEL(MIPSX(GuestException)) # 6 + .word _C_LABEL(MIPSX(GuestException)) # 7 + .word _C_LABEL(MIPSX(GuestException)) # 8 + .word _C_LABEL(MIPSX(GuestException)) # 9 + .word _C_LABEL(MIPSX(GuestException)) # 10 + .word _C_LABEL(MIPSX(GuestException)) # 11 + .word _C_LABEL(MIPSX(GuestException)) # 12 + .word _C_LABEL(MIPSX(GuestException)) # 13 + .word _C_LABEL(MIPSX(GuestException)) # 14 + .word _C_LABEL(MIPSX(GuestException)) # 15 + .word _C_LABEL(MIPSX(GuestException)) # 16 + .word _C_LABEL(MIPSX(GuestException)) # 17 + .word _C_LABEL(MIPSX(GuestException)) # 18 + .word _C_LABEL(MIPSX(GuestException)) # 19 + .word _C_LABEL(MIPSX(GuestException)) # 20 + .word _C_LABEL(MIPSX(GuestException)) # 21 + .word _C_LABEL(MIPSX(GuestException)) # 22 + .word _C_LABEL(MIPSX(GuestException)) # 23 + .word _C_LABEL(MIPSX(GuestException)) # 24 + .word _C_LABEL(MIPSX(GuestException)) # 25 + .word _C_LABEL(MIPSX(GuestException)) # 26 + .word _C_LABEL(MIPSX(GuestException)) # 27 + .word _C_LABEL(MIPSX(GuestException)) # 28 + .word _C_LABEL(MIPSX(GuestException)) # 29 + .word _C_LABEL(MIPSX(GuestException)) # 30 + .word _C_LABEL(MIPSX(GuestException)) # 31 + + +/* This routine makes changes to the instruction stream effective to the hardware. + * It should be called after the instruction stream is written. + * On return, the new instructions are effective. + * Inputs: + * a0 = Start address of new instruction stream + * a1 = Size, in bytes, of new instruction stream + */ + +#define HW_SYNCI_Step $1 +LEAF(MIPSX(SyncICache)) + .set push + .set mips32r2 + beq a1, zero, 20f + nop + addu a1, a0, a1 + rdhwr v0, HW_SYNCI_Step + beq v0, zero, 20f + nop + +10: + synci 0(a0) + addu a0, a0, v0 + sltu v1, a0, a1 + bne v1, zero, 10b + nop + sync +20: + jr.hb ra + nop + .set pop +END(MIPSX(SyncICache)) diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c new file mode 100644 index 000000000000..e0dad0289797 --- /dev/null +++ b/arch/mips/kvm/kvm_mips.c @@ -0,0 +1,958 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * KVM/MIPS: MIPS specific KVM APIs + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + * Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/bootmem.h> +#include <asm/page.h> +#include <asm/cacheflush.h> +#include <asm/mmu_context.h> + +#include <linux/kvm_host.h> + +#include "kvm_mips_int.h" +#include "kvm_mips_comm.h" + +#define CREATE_TRACE_POINTS +#include "trace.h" + +#ifndef VECTORSPACING +#define VECTORSPACING 0x100 /* for EI/VI mode */ +#endif + +#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU +struct kvm_stats_debugfs_item debugfs_entries[] = { + { "wait", VCPU_STAT(wait_exits) }, + { "cache", VCPU_STAT(cache_exits) }, + { "signal", VCPU_STAT(signal_exits) }, + { "interrupt", VCPU_STAT(int_exits) }, + { "cop_unsuable", VCPU_STAT(cop_unusable_exits) }, + { "tlbmod", VCPU_STAT(tlbmod_exits) }, + { "tlbmiss_ld", VCPU_STAT(tlbmiss_ld_exits) }, + { "tlbmiss_st", VCPU_STAT(tlbmiss_st_exits) }, + { "addrerr_st", VCPU_STAT(addrerr_st_exits) }, + { "addrerr_ld", VCPU_STAT(addrerr_ld_exits) }, + { "syscall", VCPU_STAT(syscall_exits) }, + { "resvd_inst", VCPU_STAT(resvd_inst_exits) }, + { "break_inst", VCPU_STAT(break_inst_exits) }, + { "flush_dcache", VCPU_STAT(flush_dcache_exits) }, + { "halt_wakeup", VCPU_STAT(halt_wakeup) }, + {NULL} +}; + +static int kvm_mips_reset_vcpu(struct kvm_vcpu *vcpu) +{ + int i; + for_each_possible_cpu(i) { + vcpu->arch.guest_kernel_asid[i] = 0; + vcpu->arch.guest_user_asid[i] = 0; + } + return 0; +} + +gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) +{ + return gfn; +} + +/* XXXKYMA: We are simulatoring a processor that has the WII bit set in Config7, so we + * are "runnable" if interrupts are pending + */ +int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) +{ + return !!(vcpu->arch.pending_exceptions); +} + +int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) +{ + return 1; +} + +int kvm_arch_hardware_enable(void *garbage) +{ + return 0; +} + +void kvm_arch_hardware_disable(void *garbage) +{ +} + +int kvm_arch_hardware_setup(void) +{ + return 0; +} + +void kvm_arch_hardware_unsetup(void) +{ +} + +void kvm_arch_check_processor_compat(void *rtn) +{ + int *r = (int *)rtn; + *r = 0; + return; +} + +static void kvm_mips_init_tlbs(struct kvm *kvm) +{ + unsigned long wired; + + /* Add a wired entry to the TLB, it is used to map the commpage to the Guest kernel */ + wired = read_c0_wired(); + write_c0_wired(wired + 1); + mtc0_tlbw_hazard(); + kvm->arch.commpage_tlb = wired; + + kvm_debug("[%d] commpage TLB: %d\n", smp_processor_id(), + kvm->arch.commpage_tlb); +} + +static void kvm_mips_init_vm_percpu(void *arg) +{ + struct kvm *kvm = (struct kvm *)arg; + + kvm_mips_init_tlbs(kvm); + kvm_mips_callbacks->vm_init(kvm); + +} + +int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) +{ + if (atomic_inc_return(&kvm_mips_instance) == 1) { + kvm_info("%s: 1st KVM instance, setup host TLB parameters\n", + __func__); + on_each_cpu(kvm_mips_init_vm_percpu, kvm, 1); + } + + + return 0; +} + +void kvm_mips_free_vcpus(struct kvm *kvm) +{ + unsigned int i; + struct kvm_vcpu *vcpu; + + /* Put the pages we reserved for the guest pmap */ + for (i = 0; i < kvm->arch.guest_pmap_npages; i++) { + if (kvm->arch.guest_pmap[i] != KVM_INVALID_PAGE) + kvm_mips_release_pfn_clean(kvm->arch.guest_pmap[i]); + } + + if (kvm->arch.guest_pmap) + kfree(kvm->arch.guest_pmap); + + kvm_for_each_vcpu(i, vcpu, kvm) { + kvm_arch_vcpu_free(vcpu); + } + + mutex_lock(&kvm->lock); + + for (i = 0; i < atomic_read(&kvm->online_vcpus); i++) + kvm->vcpus[i] = NULL; + + atomic_set(&kvm->online_vcpus, 0); + + mutex_unlock(&kvm->lock); +} + +void kvm_arch_sync_events(struct kvm *kvm) +{ +} + +static void kvm_mips_uninit_tlbs(void *arg) +{ + /* Restore wired count */ + write_c0_wired(0); + mtc0_tlbw_hazard(); + /* Clear out all the TLBs */ + kvm_local_flush_tlb_all(); +} + +void kvm_arch_destroy_vm(struct kvm *kvm) +{ + kvm_mips_free_vcpus(kvm); + + /* If this is the last instance, restore wired count */ + if (atomic_dec_return(&kvm_mips_instance) == 0) { + kvm_info("%s: last KVM instance, restoring TLB parameters\n", + __func__); + on_each_cpu(kvm_mips_uninit_tlbs, NULL, 1); + } +} + +long +kvm_arch_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) +{ + return -EINVAL; +} + +void kvm_arch_free_memslot(struct kvm_memory_slot *free, + struct kvm_memory_slot *dont) +{ +} + +int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages) +{ + return 0; +} + +int kvm_arch_prepare_memory_region(struct kvm *kvm, + struct kvm_memory_slot *memslot, + struct kvm_userspace_memory_region *mem, + enum kvm_mr_change change) +{ + return 0; +} + +void kvm_arch_commit_memory_region(struct kvm *kvm, + struct kvm_userspace_memory_region *mem, + const struct kvm_memory_slot *old, + enum kvm_mr_change change) +{ + unsigned long npages = 0; + int i, err = 0; + + kvm_debug("%s: kvm: %p slot: %d, GPA: %llx, size: %llx, QVA: %llx\n", + __func__, kvm, mem->slot, mem->guest_phys_addr, + mem->memory_size, mem->userspace_addr); + + /* Setup Guest PMAP table */ + if (!kvm->arch.guest_pmap) { + if (mem->slot == 0) + npages = mem->memory_size >> PAGE_SHIFT; + + if (npages) { + kvm->arch.guest_pmap_npages = npages; + kvm->arch.guest_pmap = + kzalloc(npages * sizeof(unsigned long), GFP_KERNEL); + + if (!kvm->arch.guest_pmap) { + kvm_err("Failed to allocate guest PMAP"); + err = -ENOMEM; + goto out; + } + + kvm_info + ("Allocated space for Guest PMAP Table (%ld pages) @ %p\n", + npages, kvm->arch.guest_pmap); + + /* Now setup the page table */ + for (i = 0; i < npages; i++) { + kvm->arch.guest_pmap[i] = KVM_INVALID_PAGE; + } + } + } +out: + return; +} + +void kvm_arch_flush_shadow_all(struct kvm *kvm) +{ +} + +void kvm_arch_flush_shadow_memslot(struct kvm *kvm, + struct kvm_memory_slot *slot) +{ +} + +void kvm_arch_flush_shadow(struct kvm *kvm) +{ +} + +struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) +{ + extern char mips32_exception[], mips32_exceptionEnd[]; + extern char mips32_GuestException[], mips32_GuestExceptionEnd[]; + int err, size, offset; + void *gebase; + int i; + + struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL); + + if (!vcpu) { + err = -ENOMEM; + goto out; + } + + err = kvm_vcpu_init(vcpu, kvm, id); + + if (err) + goto out_free_cpu; + + kvm_info("kvm @ %p: create cpu %d at %p\n", kvm, id, vcpu); + + /* Allocate space for host mode exception handlers that handle + * guest mode exits + */ + if (cpu_has_veic || cpu_has_vint) { + size = 0x200 + VECTORSPACING * 64; + } else { + size = 0x200; + } + + /* Save Linux EBASE */ + vcpu->arch.host_ebase = (void *)read_c0_ebase(); + + gebase = kzalloc(ALIGN(size, PAGE_SIZE), GFP_KERNEL); + + if (!gebase) { + err = -ENOMEM; + goto out_free_cpu; + } + kvm_info("Allocated %d bytes for KVM Exception Handlers @ %p\n", + ALIGN(size, PAGE_SIZE), gebase); + + /* Save new ebase */ + vcpu->arch.guest_ebase = gebase; + + /* Copy L1 Guest Exception handler to correct offset */ + + /* TLB Refill, EXL = 0 */ + memcpy(gebase, mips32_exception, + mips32_exceptionEnd - mips32_exception); + + /* General Exception Entry point */ + memcpy(gebase + 0x180, mips32_exception, + mips32_exceptionEnd - mips32_exception); + + /* For vectored interrupts poke the exception code @ all offsets 0-7 */ + for (i = 0; i < 8; i++) { + kvm_debug("L1 Vectored handler @ %p\n", + gebase + 0x200 + (i * VECTORSPACING)); + memcpy(gebase + 0x200 + (i * VECTORSPACING), mips32_exception, + mips32_exceptionEnd - mips32_exception); + } + + /* General handler, relocate to unmapped space for sanity's sake */ + offset = 0x2000; + kvm_info("Installing KVM Exception handlers @ %p, %#x bytes\n", + gebase + offset, + mips32_GuestExceptionEnd - mips32_GuestException); + + memcpy(gebase + offset, mips32_GuestException, + mips32_GuestExceptionEnd - mips32_GuestException); + + /* Invalidate the icache for these ranges */ + mips32_SyncICache((unsigned long) gebase, ALIGN(size, PAGE_SIZE)); + + /* Allocate comm page for guest kernel, a TLB will be reserved for mapping GVA @ 0xFFFF8000 to this page */ + vcpu->arch.kseg0_commpage = kzalloc(PAGE_SIZE << 1, GFP_KERNEL); + + if (!vcpu->arch.kseg0_commpage) { + err = -ENOMEM; + goto out_free_gebase; + } + + kvm_info("Allocated COMM page @ %p\n", vcpu->arch.kseg0_commpage); + kvm_mips_commpage_init(vcpu); + + /* Init */ + vcpu->arch.last_sched_cpu = -1; + + /* Start off the timer */ + kvm_mips_emulate_count(vcpu); + + return vcpu; + +out_free_gebase: + kfree(gebase); + +out_free_cpu: + kfree(vcpu); + +out: + return ERR_PTR(err); +} + +void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) +{ + hrtimer_cancel(&vcpu->arch.comparecount_timer); + + kvm_vcpu_uninit(vcpu); + + kvm_mips_dump_stats(vcpu); + + if (vcpu->arch.guest_ebase) + kfree(vcpu->arch.guest_ebase); + + if (vcpu->arch.kseg0_commpage) + kfree(vcpu->arch.kseg0_commpage); + +} + +void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) +{ + kvm_arch_vcpu_free(vcpu); +} + +int +kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, + struct kvm_guest_debug *dbg) +{ + return -EINVAL; +} + +int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + int r = 0; + sigset_t sigsaved; + + if (vcpu->sigset_active) + sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); + + if (vcpu->mmio_needed) { + if (!vcpu->mmio_is_write) + kvm_mips_complete_mmio_load(vcpu, run); + vcpu->mmio_needed = 0; + } + + /* Check if we have any exceptions/interrupts pending */ + kvm_mips_deliver_interrupts(vcpu, + kvm_read_c0_guest_cause(vcpu->arch.cop0)); + + local_irq_disable(); + kvm_guest_enter(); + + r = __kvm_mips_vcpu_run(run, vcpu); + + kvm_guest_exit(); + local_irq_enable(); + + if (vcpu->sigset_active) + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + + return r; +} + +int +kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq) +{ + int intr = (int)irq->irq; + struct kvm_vcpu *dvcpu = NULL; + + if (intr == 3 || intr == -3 || intr == 4 || intr == -4) + kvm_debug("%s: CPU: %d, INTR: %d\n", __func__, irq->cpu, + (int)intr); + + if (irq->cpu == -1) + dvcpu = vcpu; + else + dvcpu = vcpu->kvm->vcpus[irq->cpu]; + + if (intr == 2 || intr == 3 || intr == 4) { + kvm_mips_callbacks->queue_io_int(dvcpu, irq); + + } else if (intr == -2 || intr == -3 || intr == -4) { + kvm_mips_callbacks->dequeue_io_int(dvcpu, irq); + } else { + kvm_err("%s: invalid interrupt ioctl (%d:%d)\n", __func__, + irq->cpu, irq->irq); + return -EINVAL; + } + + dvcpu->arch.wait = 0; + + if (waitqueue_active(&dvcpu->wq)) { + wake_up_interruptible(&dvcpu->wq); + } + + return 0; +} + +int +kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state) +{ + return -EINVAL; +} + +int +kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state) +{ + return -EINVAL; +} + +long +kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) +{ + struct kvm_vcpu *vcpu = filp->private_data; + void __user *argp = (void __user *)arg; + long r; + int intr; + + switch (ioctl) { + case KVM_NMI: + /* Treat the NMI as a CPU reset */ + r = kvm_mips_reset_vcpu(vcpu); + break; + case KVM_INTERRUPT: + { + struct kvm_mips_interrupt irq; + r = -EFAULT; + if (copy_from_user(&irq, argp, sizeof(irq))) + goto out; + + intr = (int)irq.irq; + + kvm_debug("[%d] %s: irq: %d\n", vcpu->vcpu_id, __func__, + irq.irq); + + r = kvm_vcpu_ioctl_interrupt(vcpu, &irq); + break; + } + default: + r = -EINVAL; + } + +out: + return r; +} + +/* + * Get (and clear) the dirty memory log for a memory slot. + */ +int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) +{ + struct kvm_memory_slot *memslot; + unsigned long ga, ga_end; + int is_dirty = 0; + int r; + unsigned long n; + + mutex_lock(&kvm->slots_lock); + + r = kvm_get_dirty_log(kvm, log, &is_dirty); + if (r) + goto out; + + /* If nothing is dirty, don't bother messing with page tables. */ + if (is_dirty) { + memslot = &kvm->memslots->memslots[log->slot]; + + ga = memslot->base_gfn << PAGE_SHIFT; + ga_end = ga + (memslot->npages << PAGE_SHIFT); + + printk("%s: dirty, ga: %#lx, ga_end %#lx\n", __func__, ga, + ga_end); + + n = kvm_dirty_bitmap_bytes(memslot); + memset(memslot->dirty_bitmap, 0, n); + } + + r = 0; +out: + mutex_unlock(&kvm->slots_lock); + return r; + +} + +long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) +{ + long r; + + switch (ioctl) { + default: + r = -EINVAL; + } + + return r; +} + +int kvm_arch_init(void *opaque) +{ + int ret; + + if (kvm_mips_callbacks) { + kvm_err("kvm: module already exists\n"); + return -EEXIST; + } + + ret = kvm_mips_emulation_init(&kvm_mips_callbacks); + + return ret; +} + +void kvm_arch_exit(void) +{ + kvm_mips_callbacks = NULL; +} + +int +kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) +{ + return -ENOTSUPP; +} + +int +kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) +{ + return 0; +} + +int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) +{ + return VM_FAULT_SIGBUS; +} + +int kvm_dev_ioctl_check_extension(long ext) +{ + int r; + + switch (ext) { + case KVM_CAP_COALESCED_MMIO: + r = KVM_COALESCED_MMIO_PAGE_OFFSET; + break; + default: + r = 0; + break; + } + return r; + +} + +int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) +{ + return kvm_mips_pending_timer(vcpu); +} + +int kvm_arch_vcpu_dump_regs(struct kvm_vcpu *vcpu) +{ + int i; + struct mips_coproc *cop0; + + if (!vcpu) + return -1; + + printk("VCPU Register Dump:\n"); + printk("\tpc = 0x%08lx\n", vcpu->arch.pc);; + printk("\texceptions: %08lx\n", vcpu->arch.pending_exceptions); + + for (i = 0; i < 32; i += 4) { + printk("\tgpr%02d: %08lx %08lx %08lx %08lx\n", i, + vcpu->arch.gprs[i], + vcpu->arch.gprs[i + 1], + vcpu->arch.gprs[i + 2], vcpu->arch.gprs[i + 3]); + } + printk("\thi: 0x%08lx\n", vcpu->arch.hi); + printk("\tlo: 0x%08lx\n", vcpu->arch.lo); + + cop0 = vcpu->arch.cop0; + printk("\tStatus: 0x%08lx, Cause: 0x%08lx\n", + kvm_read_c0_guest_status(cop0), kvm_read_c0_guest_cause(cop0)); + + printk("\tEPC: 0x%08lx\n", kvm_read_c0_guest_epc(cop0)); + + return 0; +} + +int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + int i; + + for (i = 0; i < 32; i++) + vcpu->arch.gprs[i] = regs->gprs[i]; + + vcpu->arch.hi = regs->hi; + vcpu->arch.lo = regs->lo; + vcpu->arch.pc = regs->pc; + + return kvm_mips_callbacks->vcpu_ioctl_set_regs(vcpu, regs); +} + +int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + int i; + + for (i = 0; i < 32; i++) + regs->gprs[i] = vcpu->arch.gprs[i]; + + regs->hi = vcpu->arch.hi; + regs->lo = vcpu->arch.lo; + regs->pc = vcpu->arch.pc; + + return kvm_mips_callbacks->vcpu_ioctl_get_regs(vcpu, regs); +} + +void kvm_mips_comparecount_func(unsigned long data) +{ + struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; + + kvm_mips_callbacks->queue_timer_int(vcpu); + + vcpu->arch.wait = 0; + if (waitqueue_active(&vcpu->wq)) { + wake_up_interruptible(&vcpu->wq); + } +} + +/* + * low level hrtimer wake routine. + */ +enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer) +{ + struct kvm_vcpu *vcpu; + + vcpu = container_of(timer, struct kvm_vcpu, arch.comparecount_timer); + kvm_mips_comparecount_func((unsigned long) vcpu); + hrtimer_forward_now(&vcpu->arch.comparecount_timer, + ktime_set(0, MS_TO_NS(10))); + return HRTIMER_RESTART; +} + +int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) +{ + kvm_mips_callbacks->vcpu_init(vcpu); + hrtimer_init(&vcpu->arch.comparecount_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + vcpu->arch.comparecount_timer.function = kvm_mips_comparecount_wakeup; + kvm_mips_init_shadow_tlb(vcpu); + return 0; +} + +void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) +{ + return; +} + +int +kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, struct kvm_translation *tr) +{ + return 0; +} + +/* Initial guest state */ +int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) +{ + return kvm_mips_callbacks->vcpu_setup(vcpu); +} + +static +void kvm_mips_set_c0_status(void) +{ + uint32_t status = read_c0_status(); + + if (cpu_has_fpu) + status |= (ST0_CU1); + + if (cpu_has_dsp) + status |= (ST0_MX); + + write_c0_status(status); + ehb(); +} + +/* + * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV) + */ +int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + uint32_t cause = vcpu->arch.host_cp0_cause; + uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + /* Set a default exit reason */ + run->exit_reason = KVM_EXIT_UNKNOWN; + run->ready_for_interrupt_injection = 1; + + /* Set the appropriate status bits based on host CPU features, before we hit the scheduler */ + kvm_mips_set_c0_status(); + + local_irq_enable(); + + kvm_debug("kvm_mips_handle_exit: cause: %#x, PC: %p, kvm_run: %p, kvm_vcpu: %p\n", + cause, opc, run, vcpu); + + /* Do a privilege check, if in UM most of these exit conditions end up + * causing an exception to be delivered to the Guest Kernel + */ + er = kvm_mips_check_privilege(cause, opc, run, vcpu); + if (er == EMULATE_PRIV_FAIL) { + goto skip_emul; + } else if (er == EMULATE_FAIL) { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + goto skip_emul; + } + + switch (exccode) { + case T_INT: + kvm_debug("[%d]T_INT @ %p\n", vcpu->vcpu_id, opc); + + ++vcpu->stat.int_exits; + trace_kvm_exit(vcpu, INT_EXITS); + + if (need_resched()) { + cond_resched(); + } + + ret = RESUME_GUEST; + break; + + case T_COP_UNUSABLE: + kvm_debug("T_COP_UNUSABLE: @ PC: %p\n", opc); + + ++vcpu->stat.cop_unusable_exits; + trace_kvm_exit(vcpu, COP_UNUSABLE_EXITS); + ret = kvm_mips_callbacks->handle_cop_unusable(vcpu); + /* XXXKYMA: Might need to return to user space */ + if (run->exit_reason == KVM_EXIT_IRQ_WINDOW_OPEN) { + ret = RESUME_HOST; + } + break; + + case T_TLB_MOD: + ++vcpu->stat.tlbmod_exits; + trace_kvm_exit(vcpu, TLBMOD_EXITS); + ret = kvm_mips_callbacks->handle_tlb_mod(vcpu); + break; + + case T_TLB_ST_MISS: + kvm_debug + ("TLB ST fault: cause %#x, status %#lx, PC: %p, BadVaddr: %#lx\n", + cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc, + badvaddr); + + ++vcpu->stat.tlbmiss_st_exits; + trace_kvm_exit(vcpu, TLBMISS_ST_EXITS); + ret = kvm_mips_callbacks->handle_tlb_st_miss(vcpu); + break; + + case T_TLB_LD_MISS: + kvm_debug("TLB LD fault: cause %#x, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); + + ++vcpu->stat.tlbmiss_ld_exits; + trace_kvm_exit(vcpu, TLBMISS_LD_EXITS); + ret = kvm_mips_callbacks->handle_tlb_ld_miss(vcpu); + break; + + case T_ADDR_ERR_ST: + ++vcpu->stat.addrerr_st_exits; + trace_kvm_exit(vcpu, ADDRERR_ST_EXITS); + ret = kvm_mips_callbacks->handle_addr_err_st(vcpu); + break; + + case T_ADDR_ERR_LD: + ++vcpu->stat.addrerr_ld_exits; + trace_kvm_exit(vcpu, ADDRERR_LD_EXITS); + ret = kvm_mips_callbacks->handle_addr_err_ld(vcpu); + break; + + case T_SYSCALL: + ++vcpu->stat.syscall_exits; + trace_kvm_exit(vcpu, SYSCALL_EXITS); + ret = kvm_mips_callbacks->handle_syscall(vcpu); + break; + + case T_RES_INST: + ++vcpu->stat.resvd_inst_exits; + trace_kvm_exit(vcpu, RESVD_INST_EXITS); + ret = kvm_mips_callbacks->handle_res_inst(vcpu); + break; + + case T_BREAK: + ++vcpu->stat.break_inst_exits; + trace_kvm_exit(vcpu, BREAK_INST_EXITS); + ret = kvm_mips_callbacks->handle_break(vcpu); + break; + + default: + kvm_err + ("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#lx\n", + exccode, opc, kvm_get_inst(opc, vcpu), badvaddr, + kvm_read_c0_guest_status(vcpu->arch.cop0)); + kvm_arch_vcpu_dump_regs(vcpu); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + break; + + } + +skip_emul: + local_irq_disable(); + + if (er == EMULATE_DONE && !(ret & RESUME_HOST)) + kvm_mips_deliver_interrupts(vcpu, cause); + + if (!(ret & RESUME_HOST)) { + /* Only check for signals if not already exiting to userspace */ + if (signal_pending(current)) { + run->exit_reason = KVM_EXIT_INTR; + ret = (-EINTR << 2) | RESUME_HOST; + ++vcpu->stat.signal_exits; + trace_kvm_exit(vcpu, SIGNAL_EXITS); + } + } + + return ret; +} + +int __init kvm_mips_init(void) +{ + int ret; + + ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); + + if (ret) + return ret; + + /* On MIPS, kernel modules are executed from "mapped space", which requires TLBs. + * The TLB handling code is statically linked with the rest of the kernel (kvm_tlb.c) + * to avoid the possibility of double faulting. The issue is that the TLB code + * references routines that are part of the the KVM module, + * which are only available once the module is loaded. + */ + kvm_mips_gfn_to_pfn = gfn_to_pfn; + kvm_mips_release_pfn_clean = kvm_release_pfn_clean; + kvm_mips_is_error_pfn = is_error_pfn; + + pr_info("KVM/MIPS Initialized\n"); + return 0; +} + +void __exit kvm_mips_exit(void) +{ + kvm_exit(); + + kvm_mips_gfn_to_pfn = NULL; + kvm_mips_release_pfn_clean = NULL; + kvm_mips_is_error_pfn = NULL; + + pr_info("KVM/MIPS unloaded\n"); +} + +module_init(kvm_mips_init); +module_exit(kvm_mips_exit); + +EXPORT_TRACEPOINT_SYMBOL(kvm_exit); diff --git a/arch/mips/kvm/kvm_mips_comm.h b/arch/mips/kvm/kvm_mips_comm.h new file mode 100644 index 000000000000..a4a8c85cc8f7 --- /dev/null +++ b/arch/mips/kvm/kvm_mips_comm.h @@ -0,0 +1,23 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS: commpage: mapped into get kernel space +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#ifndef __KVM_MIPS_COMMPAGE_H__ +#define __KVM_MIPS_COMMPAGE_H__ + +struct kvm_mips_commpage { + struct mips_coproc cop0; /* COP0 state is mapped into Guest kernel via commpage */ +}; + +#define KVM_MIPS_COMM_EIDI_OFFSET 0x0 + +extern void kvm_mips_commpage_init(struct kvm_vcpu *vcpu); + +#endif /* __KVM_MIPS_COMMPAGE_H__ */ diff --git a/arch/mips/kvm/kvm_mips_commpage.c b/arch/mips/kvm/kvm_mips_commpage.c new file mode 100644 index 000000000000..3873b1ecc40f --- /dev/null +++ b/arch/mips/kvm/kvm_mips_commpage.c @@ -0,0 +1,37 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* commpage, currently used for Virtual COP0 registers. +* Mapped into the guest kernel @ 0x0. +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/bootmem.h> +#include <asm/page.h> +#include <asm/cacheflush.h> +#include <asm/mmu_context.h> + +#include <linux/kvm_host.h> + +#include "kvm_mips_comm.h" + +void kvm_mips_commpage_init(struct kvm_vcpu *vcpu) +{ + struct kvm_mips_commpage *page = vcpu->arch.kseg0_commpage; + memset(page, 0, sizeof(struct kvm_mips_commpage)); + + /* Specific init values for fields */ + vcpu->arch.cop0 = &page->cop0; + memset(vcpu->arch.cop0, 0, sizeof(struct mips_coproc)); + + return; +} diff --git a/arch/mips/kvm/kvm_mips_dyntrans.c b/arch/mips/kvm/kvm_mips_dyntrans.c new file mode 100644 index 000000000000..96528e2d1ea6 --- /dev/null +++ b/arch/mips/kvm/kvm_mips_dyntrans.c @@ -0,0 +1,149 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS: Binary Patching for privileged instructions, reduces traps. +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/kvm_host.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/bootmem.h> + +#include "kvm_mips_comm.h" + +#define SYNCI_TEMPLATE 0x041f0000 +#define SYNCI_BASE(x) (((x) >> 21) & 0x1f) +#define SYNCI_OFFSET ((x) & 0xffff) + +#define LW_TEMPLATE 0x8c000000 +#define CLEAR_TEMPLATE 0x00000020 +#define SW_TEMPLATE 0xac000000 + +int +kvm_mips_trans_cache_index(uint32_t inst, uint32_t *opc, + struct kvm_vcpu *vcpu) +{ + int result = 0; + unsigned long kseg0_opc; + uint32_t synci_inst = 0x0; + + /* Replace the CACHE instruction, with a NOP */ + kseg0_opc = + CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa + (vcpu, (unsigned long) opc)); + memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t)); + mips32_SyncICache(kseg0_opc, 32); + + return result; +} + +/* + * Address based CACHE instructions are transformed into synci(s). A little heavy + * for just D-cache invalidates, but avoids an expensive trap + */ +int +kvm_mips_trans_cache_va(uint32_t inst, uint32_t *opc, + struct kvm_vcpu *vcpu) +{ + int result = 0; + unsigned long kseg0_opc; + uint32_t synci_inst = SYNCI_TEMPLATE, base, offset; + + base = (inst >> 21) & 0x1f; + offset = inst & 0xffff; + synci_inst |= (base << 21); + synci_inst |= offset; + + kseg0_opc = + CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa + (vcpu, (unsigned long) opc)); + memcpy((void *)kseg0_opc, (void *)&synci_inst, sizeof(uint32_t)); + mips32_SyncICache(kseg0_opc, 32); + + return result; +} + +int +kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu) +{ + int32_t rt, rd, sel; + uint32_t mfc0_inst; + unsigned long kseg0_opc, flags; + + rt = (inst >> 16) & 0x1f; + rd = (inst >> 11) & 0x1f; + sel = inst & 0x7; + + if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) { + mfc0_inst = CLEAR_TEMPLATE; + mfc0_inst |= ((rt & 0x1f) << 16); + } else { + mfc0_inst = LW_TEMPLATE; + mfc0_inst |= ((rt & 0x1f) << 16); + mfc0_inst |= + offsetof(struct mips_coproc, + reg[rd][sel]) + offsetof(struct kvm_mips_commpage, + cop0); + } + + if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) { + kseg0_opc = + CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa + (vcpu, (unsigned long) opc)); + memcpy((void *)kseg0_opc, (void *)&mfc0_inst, sizeof(uint32_t)); + mips32_SyncICache(kseg0_opc, 32); + } else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) { + local_irq_save(flags); + memcpy((void *)opc, (void *)&mfc0_inst, sizeof(uint32_t)); + mips32_SyncICache((unsigned long) opc, 32); + local_irq_restore(flags); + } else { + kvm_err("%s: Invalid address: %p\n", __func__, opc); + return -EFAULT; + } + + return 0; +} + +int +kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu) +{ + int32_t rt, rd, sel; + uint32_t mtc0_inst = SW_TEMPLATE; + unsigned long kseg0_opc, flags; + + rt = (inst >> 16) & 0x1f; + rd = (inst >> 11) & 0x1f; + sel = inst & 0x7; + + mtc0_inst |= ((rt & 0x1f) << 16); + mtc0_inst |= + offsetof(struct mips_coproc, + reg[rd][sel]) + offsetof(struct kvm_mips_commpage, cop0); + + if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) { + kseg0_opc = + CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa + (vcpu, (unsigned long) opc)); + memcpy((void *)kseg0_opc, (void *)&mtc0_inst, sizeof(uint32_t)); + mips32_SyncICache(kseg0_opc, 32); + } else if (KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) { + local_irq_save(flags); + memcpy((void *)opc, (void *)&mtc0_inst, sizeof(uint32_t)); + mips32_SyncICache((unsigned long) opc, 32); + local_irq_restore(flags); + } else { + kvm_err("%s: Invalid address: %p\n", __func__, opc); + return -EFAULT; + } + + return 0; +} diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c new file mode 100644 index 000000000000..4b6274b47f33 --- /dev/null +++ b/arch/mips/kvm/kvm_mips_emul.c @@ -0,0 +1,1829 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS: Instruction/Exception emulation +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/kvm_host.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/bootmem.h> +#include <linux/random.h> +#include <asm/page.h> +#include <asm/cacheflush.h> +#include <asm/cpu-info.h> +#include <asm/mmu_context.h> +#include <asm/tlbflush.h> +#include <asm/inst.h> + +#undef CONFIG_MIPS_MT +#include <asm/r4kcache.h> +#define CONFIG_MIPS_MT + +#include "kvm_mips_opcode.h" +#include "kvm_mips_int.h" +#include "kvm_mips_comm.h" + +#include "trace.h" + +/* + * Compute the return address and do emulate branch simulation, if required. + * This function should be called only in branch delay slot active. + */ +unsigned long kvm_compute_return_epc(struct kvm_vcpu *vcpu, + unsigned long instpc) +{ + unsigned int dspcontrol; + union mips_instruction insn; + struct kvm_vcpu_arch *arch = &vcpu->arch; + long epc = instpc; + long nextpc = KVM_INVALID_INST; + + if (epc & 3) + goto unaligned; + + /* + * Read the instruction + */ + insn.word = kvm_get_inst((uint32_t *) epc, vcpu); + + if (insn.word == KVM_INVALID_INST) + return KVM_INVALID_INST; + + switch (insn.i_format.opcode) { + /* + * jr and jalr are in r_format format. + */ + case spec_op: + switch (insn.r_format.func) { + case jalr_op: + arch->gprs[insn.r_format.rd] = epc + 8; + /* Fall through */ + case jr_op: + nextpc = arch->gprs[insn.r_format.rs]; + break; + } + break; + + /* + * This group contains: + * bltz_op, bgez_op, bltzl_op, bgezl_op, + * bltzal_op, bgezal_op, bltzall_op, bgezall_op. + */ + case bcond_op: + switch (insn.i_format.rt) { + case bltz_op: + case bltzl_op: + if ((long)arch->gprs[insn.i_format.rs] < 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + + case bgez_op: + case bgezl_op: + if ((long)arch->gprs[insn.i_format.rs] >= 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + + case bltzal_op: + case bltzall_op: + arch->gprs[31] = epc + 8; + if ((long)arch->gprs[insn.i_format.rs] < 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + + case bgezal_op: + case bgezall_op: + arch->gprs[31] = epc + 8; + if ((long)arch->gprs[insn.i_format.rs] >= 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + case bposge32_op: + if (!cpu_has_dsp) + goto sigill; + + dspcontrol = rddsp(0x01); + + if (dspcontrol >= 32) { + epc = epc + 4 + (insn.i_format.simmediate << 2); + } else + epc += 8; + nextpc = epc; + break; + } + break; + + /* + * These are unconditional and in j_format. + */ + case jal_op: + arch->gprs[31] = instpc + 8; + case j_op: + epc += 4; + epc >>= 28; + epc <<= 28; + epc |= (insn.j_format.target << 2); + nextpc = epc; + break; + + /* + * These are conditional and in i_format. + */ + case beq_op: + case beql_op: + if (arch->gprs[insn.i_format.rs] == + arch->gprs[insn.i_format.rt]) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + + case bne_op: + case bnel_op: + if (arch->gprs[insn.i_format.rs] != + arch->gprs[insn.i_format.rt]) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + + case blez_op: /* not really i_format */ + case blezl_op: + /* rt field assumed to be zero */ + if ((long)arch->gprs[insn.i_format.rs] <= 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + + case bgtz_op: + case bgtzl_op: + /* rt field assumed to be zero */ + if ((long)arch->gprs[insn.i_format.rs] > 0) + epc = epc + 4 + (insn.i_format.simmediate << 2); + else + epc += 8; + nextpc = epc; + break; + + /* + * And now the FPA/cp1 branch instructions. + */ + case cop1_op: + printk("%s: unsupported cop1_op\n", __func__); + break; + } + + return nextpc; + +unaligned: + printk("%s: unaligned epc\n", __func__); + return nextpc; + +sigill: + printk("%s: DSP branch but not DSP ASE\n", __func__); + return nextpc; +} + +enum emulation_result update_pc(struct kvm_vcpu *vcpu, uint32_t cause) +{ + unsigned long branch_pc; + enum emulation_result er = EMULATE_DONE; + + if (cause & CAUSEF_BD) { + branch_pc = kvm_compute_return_epc(vcpu, vcpu->arch.pc); + if (branch_pc == KVM_INVALID_INST) { + er = EMULATE_FAIL; + } else { + vcpu->arch.pc = branch_pc; + kvm_debug("BD update_pc(): New PC: %#lx\n", vcpu->arch.pc); + } + } else + vcpu->arch.pc += 4; + + kvm_debug("update_pc(): New PC: %#lx\n", vcpu->arch.pc); + + return er; +} + +/* Everytime the compare register is written to, we need to decide when to fire + * the timer that represents timer ticks to the GUEST. + * + */ +enum emulation_result kvm_mips_emulate_count(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + enum emulation_result er = EMULATE_DONE; + + /* If COUNT is enabled */ + if (!(kvm_read_c0_guest_cause(cop0) & CAUSEF_DC)) { + hrtimer_try_to_cancel(&vcpu->arch.comparecount_timer); + hrtimer_start(&vcpu->arch.comparecount_timer, + ktime_set(0, MS_TO_NS(10)), HRTIMER_MODE_REL); + } else { + hrtimer_try_to_cancel(&vcpu->arch.comparecount_timer); + } + + return er; +} + +enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + enum emulation_result er = EMULATE_DONE; + + if (kvm_read_c0_guest_status(cop0) & ST0_EXL) { + kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc, + kvm_read_c0_guest_epc(cop0)); + kvm_clear_c0_guest_status(cop0, ST0_EXL); + vcpu->arch.pc = kvm_read_c0_guest_epc(cop0); + + } else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) { + kvm_clear_c0_guest_status(cop0, ST0_ERL); + vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0); + } else { + printk("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n", + vcpu->arch.pc); + er = EMULATE_FAIL; + } + + return er; +} + +enum emulation_result kvm_mips_emul_wait(struct kvm_vcpu *vcpu) +{ + enum emulation_result er = EMULATE_DONE; + + kvm_debug("[%#lx] !!!WAIT!!! (%#lx)\n", vcpu->arch.pc, + vcpu->arch.pending_exceptions); + + ++vcpu->stat.wait_exits; + trace_kvm_exit(vcpu, WAIT_EXITS); + if (!vcpu->arch.pending_exceptions) { + vcpu->arch.wait = 1; + kvm_vcpu_block(vcpu); + + /* We we are runnable, then definitely go off to user space to check if any + * I/O interrupts are pending. + */ + if (kvm_check_request(KVM_REQ_UNHALT, vcpu)) { + clear_bit(KVM_REQ_UNHALT, &vcpu->requests); + vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN; + } + } + + return er; +} + +/* XXXKYMA: Linux doesn't seem to use TLBR, return EMULATE_FAIL for now so that we can catch + * this, if things ever change + */ +enum emulation_result kvm_mips_emul_tlbr(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + enum emulation_result er = EMULATE_FAIL; + uint32_t pc = vcpu->arch.pc; + + printk("[%#x] COP0_TLBR [%ld]\n", pc, kvm_read_c0_guest_index(cop0)); + return er; +} + +/* Write Guest TLB Entry @ Index */ +enum emulation_result kvm_mips_emul_tlbwi(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + int index = kvm_read_c0_guest_index(cop0); + enum emulation_result er = EMULATE_DONE; + struct kvm_mips_tlb *tlb = NULL; + uint32_t pc = vcpu->arch.pc; + + if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) { + printk("%s: illegal index: %d\n", __func__, index); + printk + ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n", + pc, index, kvm_read_c0_guest_entryhi(cop0), + kvm_read_c0_guest_entrylo0(cop0), + kvm_read_c0_guest_entrylo1(cop0), + kvm_read_c0_guest_pagemask(cop0)); + index = (index & ~0x80000000) % KVM_MIPS_GUEST_TLB_SIZE; + } + + tlb = &vcpu->arch.guest_tlb[index]; +#if 1 + /* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */ + kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi); +#endif + + tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0); + tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0); + tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0); + tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0); + + kvm_debug + ("[%#x] COP0_TLBWI [%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx, mask: %#lx)\n", + pc, index, kvm_read_c0_guest_entryhi(cop0), + kvm_read_c0_guest_entrylo0(cop0), kvm_read_c0_guest_entrylo1(cop0), + kvm_read_c0_guest_pagemask(cop0)); + + return er; +} + +/* Write Guest TLB Entry @ Random Index */ +enum emulation_result kvm_mips_emul_tlbwr(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + enum emulation_result er = EMULATE_DONE; + struct kvm_mips_tlb *tlb = NULL; + uint32_t pc = vcpu->arch.pc; + int index; + +#if 1 + get_random_bytes(&index, sizeof(index)); + index &= (KVM_MIPS_GUEST_TLB_SIZE - 1); +#else + index = jiffies % KVM_MIPS_GUEST_TLB_SIZE; +#endif + + if (index < 0 || index >= KVM_MIPS_GUEST_TLB_SIZE) { + printk("%s: illegal index: %d\n", __func__, index); + return EMULATE_FAIL; + } + + tlb = &vcpu->arch.guest_tlb[index]; + +#if 1 + /* Probe the shadow host TLB for the entry being overwritten, if one matches, invalidate it */ + kvm_mips_host_tlb_inv(vcpu, tlb->tlb_hi); +#endif + + tlb->tlb_mask = kvm_read_c0_guest_pagemask(cop0); + tlb->tlb_hi = kvm_read_c0_guest_entryhi(cop0); + tlb->tlb_lo0 = kvm_read_c0_guest_entrylo0(cop0); + tlb->tlb_lo1 = kvm_read_c0_guest_entrylo1(cop0); + + kvm_debug + ("[%#x] COP0_TLBWR[%d] (entryhi: %#lx, entrylo0: %#lx entrylo1: %#lx)\n", + pc, index, kvm_read_c0_guest_entryhi(cop0), + kvm_read_c0_guest_entrylo0(cop0), + kvm_read_c0_guest_entrylo1(cop0)); + + return er; +} + +enum emulation_result kvm_mips_emul_tlbp(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + long entryhi = kvm_read_c0_guest_entryhi(cop0); + enum emulation_result er = EMULATE_DONE; + uint32_t pc = vcpu->arch.pc; + int index = -1; + + index = kvm_mips_guest_tlb_lookup(vcpu, entryhi); + + kvm_write_c0_guest_index(cop0, index); + + kvm_debug("[%#x] COP0_TLBP (entryhi: %#lx), index: %d\n", pc, entryhi, + index); + + return er; +} + +enum emulation_result +kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + enum emulation_result er = EMULATE_DONE; + int32_t rt, rd, copz, sel, co_bit, op; + uint32_t pc = vcpu->arch.pc; + unsigned long curr_pc; + + /* + * Update PC and hold onto current PC in case there is + * an error and we want to rollback the PC + */ + curr_pc = vcpu->arch.pc; + er = update_pc(vcpu, cause); + if (er == EMULATE_FAIL) { + return er; + } + + copz = (inst >> 21) & 0x1f; + rt = (inst >> 16) & 0x1f; + rd = (inst >> 11) & 0x1f; + sel = inst & 0x7; + co_bit = (inst >> 25) & 1; + + /* Verify that the register is valid */ + if (rd > MIPS_CP0_DESAVE) { + printk("Invalid rd: %d\n", rd); + er = EMULATE_FAIL; + goto done; + } + + if (co_bit) { + op = (inst) & 0xff; + + switch (op) { + case tlbr_op: /* Read indexed TLB entry */ + er = kvm_mips_emul_tlbr(vcpu); + break; + case tlbwi_op: /* Write indexed */ + er = kvm_mips_emul_tlbwi(vcpu); + break; + case tlbwr_op: /* Write random */ + er = kvm_mips_emul_tlbwr(vcpu); + break; + case tlbp_op: /* TLB Probe */ + er = kvm_mips_emul_tlbp(vcpu); + break; + case rfe_op: + printk("!!!COP0_RFE!!!\n"); + break; + case eret_op: + er = kvm_mips_emul_eret(vcpu); + goto dont_update_pc; + break; + case wait_op: + er = kvm_mips_emul_wait(vcpu); + break; + } + } else { + switch (copz) { + case mfc_op: +#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS + cop0->stat[rd][sel]++; +#endif + /* Get reg */ + if ((rd == MIPS_CP0_COUNT) && (sel == 0)) { + /* XXXKYMA: Run the Guest count register @ 1/4 the rate of the host */ + vcpu->arch.gprs[rt] = (read_c0_count() >> 2); + } else if ((rd == MIPS_CP0_ERRCTL) && (sel == 0)) { + vcpu->arch.gprs[rt] = 0x0; +#ifdef CONFIG_KVM_MIPS_DYN_TRANS + kvm_mips_trans_mfc0(inst, opc, vcpu); +#endif + } + else { + vcpu->arch.gprs[rt] = cop0->reg[rd][sel]; + +#ifdef CONFIG_KVM_MIPS_DYN_TRANS + kvm_mips_trans_mfc0(inst, opc, vcpu); +#endif + } + + kvm_debug + ("[%#x] MFCz[%d][%d], vcpu->arch.gprs[%d]: %#lx\n", + pc, rd, sel, rt, vcpu->arch.gprs[rt]); + + break; + + case dmfc_op: + vcpu->arch.gprs[rt] = cop0->reg[rd][sel]; + break; + + case mtc_op: +#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS + cop0->stat[rd][sel]++; +#endif + if ((rd == MIPS_CP0_TLB_INDEX) + && (vcpu->arch.gprs[rt] >= + KVM_MIPS_GUEST_TLB_SIZE)) { + printk("Invalid TLB Index: %ld", + vcpu->arch.gprs[rt]); + er = EMULATE_FAIL; + break; + } +#define C0_EBASE_CORE_MASK 0xff + if ((rd == MIPS_CP0_PRID) && (sel == 1)) { + /* Preserve CORE number */ + kvm_change_c0_guest_ebase(cop0, + ~(C0_EBASE_CORE_MASK), + vcpu->arch.gprs[rt]); + printk("MTCz, cop0->reg[EBASE]: %#lx\n", + kvm_read_c0_guest_ebase(cop0)); + } else if (rd == MIPS_CP0_TLB_HI && sel == 0) { + uint32_t nasid = + vcpu->arch.gprs[rt] & ASID_MASK; + if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) + && + ((kvm_read_c0_guest_entryhi(cop0) & + ASID_MASK) != nasid)) { + + kvm_debug + ("MTCz, change ASID from %#lx to %#lx\n", + kvm_read_c0_guest_entryhi(cop0) & + ASID_MASK, + vcpu->arch.gprs[rt] & ASID_MASK); + + /* Blow away the shadow host TLBs */ + kvm_mips_flush_host_tlb(1); + } + kvm_write_c0_guest_entryhi(cop0, + vcpu->arch.gprs[rt]); + } + /* Are we writing to COUNT */ + else if ((rd == MIPS_CP0_COUNT) && (sel == 0)) { + /* Linux doesn't seem to write into COUNT, we throw an error + * if we notice a write to COUNT + */ + /*er = EMULATE_FAIL; */ + goto done; + } else if ((rd == MIPS_CP0_COMPARE) && (sel == 0)) { + kvm_debug("[%#x] MTCz, COMPARE %#lx <- %#lx\n", + pc, kvm_read_c0_guest_compare(cop0), + vcpu->arch.gprs[rt]); + + /* If we are writing to COMPARE */ + /* Clear pending timer interrupt, if any */ + kvm_mips_callbacks->dequeue_timer_int(vcpu); + kvm_write_c0_guest_compare(cop0, + vcpu->arch.gprs[rt]); + } else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) { + kvm_write_c0_guest_status(cop0, + vcpu->arch.gprs[rt]); + /* Make sure that CU1 and NMI bits are never set */ + kvm_clear_c0_guest_status(cop0, + (ST0_CU1 | ST0_NMI)); + +#ifdef CONFIG_KVM_MIPS_DYN_TRANS + kvm_mips_trans_mtc0(inst, opc, vcpu); +#endif + } else { + cop0->reg[rd][sel] = vcpu->arch.gprs[rt]; +#ifdef CONFIG_KVM_MIPS_DYN_TRANS + kvm_mips_trans_mtc0(inst, opc, vcpu); +#endif + } + + kvm_debug("[%#x] MTCz, cop0->reg[%d][%d]: %#lx\n", pc, + rd, sel, cop0->reg[rd][sel]); + break; + + case dmtc_op: + printk + ("!!!!!!![%#lx]dmtc_op: rt: %d, rd: %d, sel: %d!!!!!!\n", + vcpu->arch.pc, rt, rd, sel); + er = EMULATE_FAIL; + break; + + case mfmcz_op: +#ifdef KVM_MIPS_DEBUG_COP0_COUNTERS + cop0->stat[MIPS_CP0_STATUS][0]++; +#endif + if (rt != 0) { + vcpu->arch.gprs[rt] = + kvm_read_c0_guest_status(cop0); + } + /* EI */ + if (inst & 0x20) { + kvm_debug("[%#lx] mfmcz_op: EI\n", + vcpu->arch.pc); + kvm_set_c0_guest_status(cop0, ST0_IE); + } else { + kvm_debug("[%#lx] mfmcz_op: DI\n", + vcpu->arch.pc); + kvm_clear_c0_guest_status(cop0, ST0_IE); + } + + break; + + case wrpgpr_op: + { + uint32_t css = + cop0->reg[MIPS_CP0_STATUS][2] & 0xf; + uint32_t pss = + (cop0->reg[MIPS_CP0_STATUS][2] >> 6) & 0xf; + /* We don't support any shadow register sets, so SRSCtl[PSS] == SRSCtl[CSS] = 0 */ + if (css || pss) { + er = EMULATE_FAIL; + break; + } + kvm_debug("WRPGPR[%d][%d] = %#lx\n", pss, rd, + vcpu->arch.gprs[rt]); + vcpu->arch.gprs[rd] = vcpu->arch.gprs[rt]; + } + break; + default: + printk + ("[%#lx]MachEmulateCP0: unsupported COP0, copz: 0x%x\n", + vcpu->arch.pc, copz); + er = EMULATE_FAIL; + break; + } + } + +done: + /* + * Rollback PC only if emulation was unsuccessful + */ + if (er == EMULATE_FAIL) { + vcpu->arch.pc = curr_pc; + } + +dont_update_pc: + /* + * This is for special instructions whose emulation + * updates the PC, so do not overwrite the PC under + * any circumstances + */ + + return er; +} + +enum emulation_result +kvm_mips_emulate_store(uint32_t inst, uint32_t cause, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er = EMULATE_DO_MMIO; + int32_t op, base, rt, offset; + uint32_t bytes; + void *data = run->mmio.data; + unsigned long curr_pc; + + /* + * Update PC and hold onto current PC in case there is + * an error and we want to rollback the PC + */ + curr_pc = vcpu->arch.pc; + er = update_pc(vcpu, cause); + if (er == EMULATE_FAIL) + return er; + + rt = (inst >> 16) & 0x1f; + base = (inst >> 21) & 0x1f; + offset = inst & 0xffff; + op = (inst >> 26) & 0x3f; + + switch (op) { + case sb_op: + bytes = 1; + if (bytes > sizeof(run->mmio.data)) { + kvm_err("%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + } + run->mmio.phys_addr = + kvm_mips_callbacks->gva_to_gpa(vcpu->arch. + host_cp0_badvaddr); + if (run->mmio.phys_addr == KVM_INVALID_ADDR) { + er = EMULATE_FAIL; + break; + } + run->mmio.len = bytes; + run->mmio.is_write = 1; + vcpu->mmio_needed = 1; + vcpu->mmio_is_write = 1; + *(u8 *) data = vcpu->arch.gprs[rt]; + kvm_debug("OP_SB: eaddr: %#lx, gpr: %#lx, data: %#x\n", + vcpu->arch.host_cp0_badvaddr, vcpu->arch.gprs[rt], + *(uint8_t *) data); + + break; + + case sw_op: + bytes = 4; + if (bytes > sizeof(run->mmio.data)) { + kvm_err("%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + } + run->mmio.phys_addr = + kvm_mips_callbacks->gva_to_gpa(vcpu->arch. + host_cp0_badvaddr); + if (run->mmio.phys_addr == KVM_INVALID_ADDR) { + er = EMULATE_FAIL; + break; + } + + run->mmio.len = bytes; + run->mmio.is_write = 1; + vcpu->mmio_needed = 1; + vcpu->mmio_is_write = 1; + *(uint32_t *) data = vcpu->arch.gprs[rt]; + + kvm_debug("[%#lx] OP_SW: eaddr: %#lx, gpr: %#lx, data: %#x\n", + vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr, + vcpu->arch.gprs[rt], *(uint32_t *) data); + break; + + case sh_op: + bytes = 2; + if (bytes > sizeof(run->mmio.data)) { + kvm_err("%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + } + run->mmio.phys_addr = + kvm_mips_callbacks->gva_to_gpa(vcpu->arch. + host_cp0_badvaddr); + if (run->mmio.phys_addr == KVM_INVALID_ADDR) { + er = EMULATE_FAIL; + break; + } + + run->mmio.len = bytes; + run->mmio.is_write = 1; + vcpu->mmio_needed = 1; + vcpu->mmio_is_write = 1; + *(uint16_t *) data = vcpu->arch.gprs[rt]; + + kvm_debug("[%#lx] OP_SH: eaddr: %#lx, gpr: %#lx, data: %#x\n", + vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr, + vcpu->arch.gprs[rt], *(uint32_t *) data); + break; + + default: + printk("Store not yet supported"); + er = EMULATE_FAIL; + break; + } + + /* + * Rollback PC if emulation was unsuccessful + */ + if (er == EMULATE_FAIL) { + vcpu->arch.pc = curr_pc; + } + + return er; +} + +enum emulation_result +kvm_mips_emulate_load(uint32_t inst, uint32_t cause, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er = EMULATE_DO_MMIO; + int32_t op, base, rt, offset; + uint32_t bytes; + + rt = (inst >> 16) & 0x1f; + base = (inst >> 21) & 0x1f; + offset = inst & 0xffff; + op = (inst >> 26) & 0x3f; + + vcpu->arch.pending_load_cause = cause; + vcpu->arch.io_gpr = rt; + + switch (op) { + case lw_op: + bytes = 4; + if (bytes > sizeof(run->mmio.data)) { + kvm_err("%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + er = EMULATE_FAIL; + break; + } + run->mmio.phys_addr = + kvm_mips_callbacks->gva_to_gpa(vcpu->arch. + host_cp0_badvaddr); + if (run->mmio.phys_addr == KVM_INVALID_ADDR) { + er = EMULATE_FAIL; + break; + } + + run->mmio.len = bytes; + run->mmio.is_write = 0; + vcpu->mmio_needed = 1; + vcpu->mmio_is_write = 0; + break; + + case lh_op: + case lhu_op: + bytes = 2; + if (bytes > sizeof(run->mmio.data)) { + kvm_err("%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + er = EMULATE_FAIL; + break; + } + run->mmio.phys_addr = + kvm_mips_callbacks->gva_to_gpa(vcpu->arch. + host_cp0_badvaddr); + if (run->mmio.phys_addr == KVM_INVALID_ADDR) { + er = EMULATE_FAIL; + break; + } + + run->mmio.len = bytes; + run->mmio.is_write = 0; + vcpu->mmio_needed = 1; + vcpu->mmio_is_write = 0; + + if (op == lh_op) + vcpu->mmio_needed = 2; + else + vcpu->mmio_needed = 1; + + break; + + case lbu_op: + case lb_op: + bytes = 1; + if (bytes > sizeof(run->mmio.data)) { + kvm_err("%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + er = EMULATE_FAIL; + break; + } + run->mmio.phys_addr = + kvm_mips_callbacks->gva_to_gpa(vcpu->arch. + host_cp0_badvaddr); + if (run->mmio.phys_addr == KVM_INVALID_ADDR) { + er = EMULATE_FAIL; + break; + } + + run->mmio.len = bytes; + run->mmio.is_write = 0; + vcpu->mmio_is_write = 0; + + if (op == lb_op) + vcpu->mmio_needed = 2; + else + vcpu->mmio_needed = 1; + + break; + + default: + printk("Load not yet supported"); + er = EMULATE_FAIL; + break; + } + + return er; +} + +int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu) +{ + unsigned long offset = (va & ~PAGE_MASK); + struct kvm *kvm = vcpu->kvm; + unsigned long pa; + gfn_t gfn; + pfn_t pfn; + + gfn = va >> PAGE_SHIFT; + + if (gfn >= kvm->arch.guest_pmap_npages) { + printk("%s: Invalid gfn: %#llx\n", __func__, gfn); + kvm_mips_dump_host_tlbs(); + kvm_arch_vcpu_dump_regs(vcpu); + return -1; + } + pfn = kvm->arch.guest_pmap[gfn]; + pa = (pfn << PAGE_SHIFT) | offset; + + printk("%s: va: %#lx, unmapped: %#x\n", __func__, va, CKSEG0ADDR(pa)); + + mips32_SyncICache(CKSEG0ADDR(pa), 32); + return 0; +} + +#define MIPS_CACHE_OP_INDEX_INV 0x0 +#define MIPS_CACHE_OP_INDEX_LD_TAG 0x1 +#define MIPS_CACHE_OP_INDEX_ST_TAG 0x2 +#define MIPS_CACHE_OP_IMP 0x3 +#define MIPS_CACHE_OP_HIT_INV 0x4 +#define MIPS_CACHE_OP_FILL_WB_INV 0x5 +#define MIPS_CACHE_OP_HIT_HB 0x6 +#define MIPS_CACHE_OP_FETCH_LOCK 0x7 + +#define MIPS_CACHE_ICACHE 0x0 +#define MIPS_CACHE_DCACHE 0x1 +#define MIPS_CACHE_SEC 0x3 + +enum emulation_result +kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + extern void (*r4k_blast_dcache) (void); + extern void (*r4k_blast_icache) (void); + enum emulation_result er = EMULATE_DONE; + int32_t offset, cache, op_inst, op, base; + struct kvm_vcpu_arch *arch = &vcpu->arch; + unsigned long va; + unsigned long curr_pc; + + /* + * Update PC and hold onto current PC in case there is + * an error and we want to rollback the PC + */ + curr_pc = vcpu->arch.pc; + er = update_pc(vcpu, cause); + if (er == EMULATE_FAIL) + return er; + + base = (inst >> 21) & 0x1f; + op_inst = (inst >> 16) & 0x1f; + offset = inst & 0xffff; + cache = (inst >> 16) & 0x3; + op = (inst >> 18) & 0x7; + + va = arch->gprs[base] + offset; + + kvm_debug("CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n", + cache, op, base, arch->gprs[base], offset); + + /* Treat INDEX_INV as a nop, basically issued by Linux on startup to invalidate + * the caches entirely by stepping through all the ways/indexes + */ + if (op == MIPS_CACHE_OP_INDEX_INV) { + kvm_debug + ("@ %#lx/%#lx CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n", + vcpu->arch.pc, vcpu->arch.gprs[31], cache, op, base, + arch->gprs[base], offset); + + if (cache == MIPS_CACHE_DCACHE) + r4k_blast_dcache(); + else if (cache == MIPS_CACHE_ICACHE) + r4k_blast_icache(); + else { + printk("%s: unsupported CACHE INDEX operation\n", + __func__); + return EMULATE_FAIL; + } + +#ifdef CONFIG_KVM_MIPS_DYN_TRANS + kvm_mips_trans_cache_index(inst, opc, vcpu); +#endif + goto done; + } + + preempt_disable(); + if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) { + + if (kvm_mips_host_tlb_lookup(vcpu, va) < 0) { + kvm_mips_handle_kseg0_tlb_fault(va, vcpu); + } + } else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) || + KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) { + int index; + + /* If an entry already exists then skip */ + if (kvm_mips_host_tlb_lookup(vcpu, va) >= 0) { + goto skip_fault; + } + + /* If address not in the guest TLB, then give the guest a fault, the + * resulting handler will do the right thing + */ + index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) | + (kvm_read_c0_guest_entryhi + (cop0) & ASID_MASK)); + + if (index < 0) { + vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK); + vcpu->arch.host_cp0_badvaddr = va; + er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run, + vcpu); + preempt_enable(); + goto dont_update_pc; + } else { + struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index]; + /* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */ + if (!TLB_IS_VALID(*tlb, va)) { + er = kvm_mips_emulate_tlbinv_ld(cause, NULL, + run, vcpu); + preempt_enable(); + goto dont_update_pc; + } else { + /* We fault an entry from the guest tlb to the shadow host TLB */ + kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, + NULL, + NULL); + } + } + } else { + printk + ("INVALID CACHE INDEX/ADDRESS (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n", + cache, op, base, arch->gprs[base], offset); + er = EMULATE_FAIL; + preempt_enable(); + goto dont_update_pc; + + } + +skip_fault: + /* XXXKYMA: Only a subset of cache ops are supported, used by Linux */ + if (cache == MIPS_CACHE_DCACHE + && (op == MIPS_CACHE_OP_FILL_WB_INV + || op == MIPS_CACHE_OP_HIT_INV)) { + flush_dcache_line(va); + +#ifdef CONFIG_KVM_MIPS_DYN_TRANS + /* Replace the CACHE instruction, with a SYNCI, not the same, but avoids a trap */ + kvm_mips_trans_cache_va(inst, opc, vcpu); +#endif + } else if (op == MIPS_CACHE_OP_HIT_INV && cache == MIPS_CACHE_ICACHE) { + flush_dcache_line(va); + flush_icache_line(va); + +#ifdef CONFIG_KVM_MIPS_DYN_TRANS + /* Replace the CACHE instruction, with a SYNCI */ + kvm_mips_trans_cache_va(inst, opc, vcpu); +#endif + } else { + printk + ("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n", + cache, op, base, arch->gprs[base], offset); + er = EMULATE_FAIL; + preempt_enable(); + goto dont_update_pc; + } + + preempt_enable(); + + dont_update_pc: + /* + * Rollback PC + */ + vcpu->arch.pc = curr_pc; + done: + return er; +} + +enum emulation_result +kvm_mips_emulate_inst(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er = EMULATE_DONE; + uint32_t inst; + + /* + * Fetch the instruction. + */ + if (cause & CAUSEF_BD) { + opc += 1; + } + + inst = kvm_get_inst(opc, vcpu); + + switch (((union mips_instruction)inst).r_format.opcode) { + case cop0_op: + er = kvm_mips_emulate_CP0(inst, opc, cause, run, vcpu); + break; + case sb_op: + case sh_op: + case sw_op: + er = kvm_mips_emulate_store(inst, cause, run, vcpu); + break; + case lb_op: + case lbu_op: + case lhu_op: + case lh_op: + case lw_op: + er = kvm_mips_emulate_load(inst, cause, run, vcpu); + break; + + case cache_op: + ++vcpu->stat.cache_exits; + trace_kvm_exit(vcpu, CACHE_EXITS); + er = kvm_mips_emulate_cache(inst, opc, cause, run, vcpu); + break; + + default: + printk("Instruction emulation not supported (%p/%#x)\n", opc, + inst); + kvm_arch_vcpu_dump_regs(vcpu); + er = EMULATE_FAIL; + break; + } + + return er; +} + +enum emulation_result +kvm_mips_emulate_syscall(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering SYSCALL @ pc %#lx\n", arch->pc); + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_SYSCALL << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + printk("Trying to deliver SYSCALL when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + +enum emulation_result +kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + unsigned long entryhi = (vcpu->arch. host_cp0_badvaddr & VPN2_MASK) | + (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("[EXL == 0] delivering TLB MISS @ pc %#lx\n", + arch->pc); + + /* set pc to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x0; + + } else { + kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n", + arch->pc); + + arch->pc = KVM_GUEST_KSEG0 + 0x180; + } + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_TLB_LD_MISS << CAUSEB_EXCCODE)); + + /* setup badvaddr, context and entryhi registers for the guest */ + kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); + /* XXXKYMA: is the context register used by linux??? */ + kvm_write_c0_guest_entryhi(cop0, entryhi); + /* Blow away the shadow host TLBs */ + kvm_mips_flush_host_tlb(1); + + return er; +} + +enum emulation_result +kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + unsigned long entryhi = + (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | + (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("[EXL == 0] delivering TLB INV @ pc %#lx\n", + arch->pc); + + /* set pc to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n", + arch->pc); + arch->pc = KVM_GUEST_KSEG0 + 0x180; + } + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_TLB_LD_MISS << CAUSEB_EXCCODE)); + + /* setup badvaddr, context and entryhi registers for the guest */ + kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); + /* XXXKYMA: is the context register used by linux??? */ + kvm_write_c0_guest_entryhi(cop0, entryhi); + /* Blow away the shadow host TLBs */ + kvm_mips_flush_host_tlb(1); + + return er; +} + +enum emulation_result +kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | + (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n", + arch->pc); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x0; + } else { + kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n", + arch->pc); + arch->pc = KVM_GUEST_KSEG0 + 0x180; + } + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_TLB_ST_MISS << CAUSEB_EXCCODE)); + + /* setup badvaddr, context and entryhi registers for the guest */ + kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); + /* XXXKYMA: is the context register used by linux??? */ + kvm_write_c0_guest_entryhi(cop0, entryhi); + /* Blow away the shadow host TLBs */ + kvm_mips_flush_host_tlb(1); + + return er; +} + +enum emulation_result +kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | + (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("[EXL == 0] Delivering TLB MISS @ pc %#lx\n", + arch->pc); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + } else { + kvm_debug("[EXL == 1] Delivering TLB MISS @ pc %#lx\n", + arch->pc); + arch->pc = KVM_GUEST_KSEG0 + 0x180; + } + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_TLB_ST_MISS << CAUSEB_EXCCODE)); + + /* setup badvaddr, context and entryhi registers for the guest */ + kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); + /* XXXKYMA: is the context register used by linux??? */ + kvm_write_c0_guest_entryhi(cop0, entryhi); + /* Blow away the shadow host TLBs */ + kvm_mips_flush_host_tlb(1); + + return er; +} + +/* TLBMOD: store into address matching TLB with Dirty bit off */ +enum emulation_result +kvm_mips_handle_tlbmod(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er = EMULATE_DONE; + +#ifdef DEBUG + /* + * If address not in the guest TLB, then we are in trouble + */ + index = kvm_mips_guest_tlb_lookup(vcpu, entryhi); + if (index < 0) { + /* XXXKYMA Invalidate and retry */ + kvm_mips_host_tlb_inv(vcpu, vcpu->arch.host_cp0_badvaddr); + kvm_err("%s: host got TLBMOD for %#lx but entry not present in Guest TLB\n", + __func__, entryhi); + kvm_mips_dump_guest_tlbs(vcpu); + kvm_mips_dump_host_tlbs(); + return EMULATE_FAIL; + } +#endif + + er = kvm_mips_emulate_tlbmod(cause, opc, run, vcpu); + return er; +} + +enum emulation_result +kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) | + (kvm_read_c0_guest_entryhi(cop0) & ASID_MASK); + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("[EXL == 0] Delivering TLB MOD @ pc %#lx\n", + arch->pc); + + arch->pc = KVM_GUEST_KSEG0 + 0x180; + } else { + kvm_debug("[EXL == 1] Delivering TLB MOD @ pc %#lx\n", + arch->pc); + arch->pc = KVM_GUEST_KSEG0 + 0x180; + } + + kvm_change_c0_guest_cause(cop0, (0xff), (T_TLB_MOD << CAUSEB_EXCCODE)); + + /* setup badvaddr, context and entryhi registers for the guest */ + kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); + /* XXXKYMA: is the context register used by linux??? */ + kvm_write_c0_guest_entryhi(cop0, entryhi); + /* Blow away the shadow host TLBs */ + kvm_mips_flush_host_tlb(1); + + return er; +} + +enum emulation_result +kvm_mips_emulate_fpu_exc(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + } + + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_COP_UNUSABLE << CAUSEB_EXCCODE)); + kvm_change_c0_guest_cause(cop0, (CAUSEF_CE), (0x1 << CAUSEB_CE)); + + return er; +} + +enum emulation_result +kvm_mips_emulate_ri_exc(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering RI @ pc %#lx\n", arch->pc); + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_RES_INST << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + kvm_err("Trying to deliver RI when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + +enum emulation_result +kvm_mips_emulate_bp_exc(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering BP @ pc %#lx\n", arch->pc); + + kvm_change_c0_guest_cause(cop0, (0xff), + (T_BREAK << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + } else { + printk("Trying to deliver BP when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + +/* + * ll/sc, rdhwr, sync emulation + */ + +#define OPCODE 0xfc000000 +#define BASE 0x03e00000 +#define RT 0x001f0000 +#define OFFSET 0x0000ffff +#define LL 0xc0000000 +#define SC 0xe0000000 +#define SPEC0 0x00000000 +#define SPEC3 0x7c000000 +#define RD 0x0000f800 +#define FUNC 0x0000003f +#define SYNC 0x0000000f +#define RDHWR 0x0000003b + +enum emulation_result +kvm_mips_handle_ri(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + unsigned long curr_pc; + uint32_t inst; + + /* + * Update PC and hold onto current PC in case there is + * an error and we want to rollback the PC + */ + curr_pc = vcpu->arch.pc; + er = update_pc(vcpu, cause); + if (er == EMULATE_FAIL) + return er; + + /* + * Fetch the instruction. + */ + if (cause & CAUSEF_BD) + opc += 1; + + inst = kvm_get_inst(opc, vcpu); + + if (inst == KVM_INVALID_INST) { + printk("%s: Cannot get inst @ %p\n", __func__, opc); + return EMULATE_FAIL; + } + + if ((inst & OPCODE) == SPEC3 && (inst & FUNC) == RDHWR) { + int rd = (inst & RD) >> 11; + int rt = (inst & RT) >> 16; + switch (rd) { + case 0: /* CPU number */ + arch->gprs[rt] = 0; + break; + case 1: /* SYNCI length */ + arch->gprs[rt] = min(current_cpu_data.dcache.linesz, + current_cpu_data.icache.linesz); + break; + case 2: /* Read count register */ + printk("RDHWR: Cont register\n"); + arch->gprs[rt] = kvm_read_c0_guest_count(cop0); + break; + case 3: /* Count register resolution */ + switch (current_cpu_data.cputype) { + case CPU_20KC: + case CPU_25KF: + arch->gprs[rt] = 1; + break; + default: + arch->gprs[rt] = 2; + } + break; + case 29: +#if 1 + arch->gprs[rt] = kvm_read_c0_guest_userlocal(cop0); +#else + /* UserLocal not implemented */ + er = kvm_mips_emulate_ri_exc(cause, opc, run, vcpu); +#endif + break; + + default: + printk("RDHWR not supported\n"); + er = EMULATE_FAIL; + break; + } + } else { + printk("Emulate RI not supported @ %p: %#x\n", opc, inst); + er = EMULATE_FAIL; + } + + /* + * Rollback PC only if emulation was unsuccessful + */ + if (er == EMULATE_FAIL) { + vcpu->arch.pc = curr_pc; + } + return er; +} + +enum emulation_result +kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr]; + enum emulation_result er = EMULATE_DONE; + unsigned long curr_pc; + + if (run->mmio.len > sizeof(*gpr)) { + printk("Bad MMIO length: %d", run->mmio.len); + er = EMULATE_FAIL; + goto done; + } + + /* + * Update PC and hold onto current PC in case there is + * an error and we want to rollback the PC + */ + curr_pc = vcpu->arch.pc; + er = update_pc(vcpu, vcpu->arch.pending_load_cause); + if (er == EMULATE_FAIL) + return er; + + switch (run->mmio.len) { + case 4: + *gpr = *(int32_t *) run->mmio.data; + break; + + case 2: + if (vcpu->mmio_needed == 2) + *gpr = *(int16_t *) run->mmio.data; + else + *gpr = *(int16_t *) run->mmio.data; + + break; + case 1: + if (vcpu->mmio_needed == 2) + *gpr = *(int8_t *) run->mmio.data; + else + *gpr = *(u8 *) run->mmio.data; + break; + } + + if (vcpu->arch.pending_load_cause & CAUSEF_BD) + kvm_debug + ("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n", + vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr, + vcpu->mmio_needed); + +done: + return er; +} + +static enum emulation_result +kvm_mips_emulate_exc(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f; + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_vcpu_arch *arch = &vcpu->arch; + enum emulation_result er = EMULATE_DONE; + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_change_c0_guest_cause(cop0, (0xff), + (exccode << CAUSEB_EXCCODE)); + + /* Set PC to the exception entry point */ + arch->pc = KVM_GUEST_KSEG0 + 0x180; + kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr); + + kvm_debug("Delivering EXC %d @ pc %#lx, badVaddr: %#lx\n", + exccode, kvm_read_c0_guest_epc(cop0), + kvm_read_c0_guest_badvaddr(cop0)); + } else { + printk("Trying to deliver EXC when EXL is already set\n"); + er = EMULATE_FAIL; + } + + return er; +} + +enum emulation_result +kvm_mips_check_privilege(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er = EMULATE_DONE; + uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f; + unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + + int usermode = !KVM_GUEST_KERNEL_MODE(vcpu); + + if (usermode) { + switch (exccode) { + case T_INT: + case T_SYSCALL: + case T_BREAK: + case T_RES_INST: + break; + + case T_COP_UNUSABLE: + if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 0) + er = EMULATE_PRIV_FAIL; + break; + + case T_TLB_MOD: + break; + + case T_TLB_LD_MISS: + /* We we are accessing Guest kernel space, then send an address error exception to the guest */ + if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) { + printk("%s: LD MISS @ %#lx\n", __func__, + badvaddr); + cause &= ~0xff; + cause |= (T_ADDR_ERR_LD << CAUSEB_EXCCODE); + er = EMULATE_PRIV_FAIL; + } + break; + + case T_TLB_ST_MISS: + /* We we are accessing Guest kernel space, then send an address error exception to the guest */ + if (badvaddr >= (unsigned long) KVM_GUEST_KSEG0) { + printk("%s: ST MISS @ %#lx\n", __func__, + badvaddr); + cause &= ~0xff; + cause |= (T_ADDR_ERR_ST << CAUSEB_EXCCODE); + er = EMULATE_PRIV_FAIL; + } + break; + + case T_ADDR_ERR_ST: + printk("%s: address error ST @ %#lx\n", __func__, + badvaddr); + if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) { + cause &= ~0xff; + cause |= (T_TLB_ST_MISS << CAUSEB_EXCCODE); + } + er = EMULATE_PRIV_FAIL; + break; + case T_ADDR_ERR_LD: + printk("%s: address error LD @ %#lx\n", __func__, + badvaddr); + if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) { + cause &= ~0xff; + cause |= (T_TLB_LD_MISS << CAUSEB_EXCCODE); + } + er = EMULATE_PRIV_FAIL; + break; + default: + er = EMULATE_PRIV_FAIL; + break; + } + } + + if (er == EMULATE_PRIV_FAIL) { + kvm_mips_emulate_exc(cause, opc, run, vcpu); + } + return er; +} + +/* User Address (UA) fault, this could happen if + * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this + * case we pass on the fault to the guest kernel and let it handle it. + * (2) TLB entry is present in the Guest TLB but not in the shadow, in this + * case we inject the TLB from the Guest TLB into the shadow host TLB + */ +enum emulation_result +kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc, + struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er = EMULATE_DONE; + uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f; + unsigned long va = vcpu->arch.host_cp0_badvaddr; + int index; + + kvm_debug("kvm_mips_handle_tlbmiss: badvaddr: %#lx, entryhi: %#lx\n", + vcpu->arch.host_cp0_badvaddr, vcpu->arch.host_cp0_entryhi); + + /* KVM would not have got the exception if this entry was valid in the shadow host TLB + * Check the Guest TLB, if the entry is not there then send the guest an + * exception. The guest exc handler should then inject an entry into the + * guest TLB + */ + index = kvm_mips_guest_tlb_lookup(vcpu, + (va & VPN2_MASK) | + (kvm_read_c0_guest_entryhi + (vcpu->arch.cop0) & ASID_MASK)); + if (index < 0) { + if (exccode == T_TLB_LD_MISS) { + er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu); + } else if (exccode == T_TLB_ST_MISS) { + er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu); + } else { + printk("%s: invalid exc code: %d\n", __func__, exccode); + er = EMULATE_FAIL; + } + } else { + struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index]; + + /* Check if the entry is valid, if not then setup a TLB invalid exception to the guest */ + if (!TLB_IS_VALID(*tlb, va)) { + if (exccode == T_TLB_LD_MISS) { + er = kvm_mips_emulate_tlbinv_ld(cause, opc, run, + vcpu); + } else if (exccode == T_TLB_ST_MISS) { + er = kvm_mips_emulate_tlbinv_st(cause, opc, run, + vcpu); + } else { + printk("%s: invalid exc code: %d\n", __func__, + exccode); + er = EMULATE_FAIL; + } + } else { +#ifdef DEBUG + kvm_debug + ("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n", + tlb->tlb_hi, tlb->tlb_lo0, tlb->tlb_lo1); +#endif + /* OK we have a Guest TLB entry, now inject it into the shadow host TLB */ + kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL, + NULL); + } + } + + return er; +} diff --git a/arch/mips/kvm/kvm_mips_int.c b/arch/mips/kvm/kvm_mips_int.c new file mode 100644 index 000000000000..1e5de16afe29 --- /dev/null +++ b/arch/mips/kvm/kvm_mips_int.c @@ -0,0 +1,243 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS: Interrupt delivery +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/bootmem.h> +#include <asm/page.h> +#include <asm/cacheflush.h> + +#include <linux/kvm_host.h> + +#include "kvm_mips_int.h" + +void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority) +{ + set_bit(priority, &vcpu->arch.pending_exceptions); +} + +void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority) +{ + clear_bit(priority, &vcpu->arch.pending_exceptions); +} + +void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu) +{ + /* Cause bits to reflect the pending timer interrupt, + * the EXC code will be set when we are actually + * delivering the interrupt: + */ + kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI)); + + /* Queue up an INT exception for the core */ + kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_TIMER); + +} + +void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu) +{ + kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ5 | C_TI)); + kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_TIMER); +} + +void +kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu, struct kvm_mips_interrupt *irq) +{ + int intr = (int)irq->irq; + + /* Cause bits to reflect the pending IO interrupt, + * the EXC code will be set when we are actually + * delivering the interrupt: + */ + switch (intr) { + case 2: + kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0)); + /* Queue up an INT exception for the core */ + kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IO); + break; + + case 3: + kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1)); + kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_1); + break; + + case 4: + kvm_set_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2)); + kvm_mips_queue_irq(vcpu, MIPS_EXC_INT_IPI_2); + break; + + default: + break; + } + +} + +void +kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu, + struct kvm_mips_interrupt *irq) +{ + int intr = (int)irq->irq; + switch (intr) { + case -2: + kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ0)); + kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IO); + break; + + case -3: + kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ1)); + kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_1); + break; + + case -4: + kvm_clear_c0_guest_cause(vcpu->arch.cop0, (C_IRQ2)); + kvm_mips_dequeue_irq(vcpu, MIPS_EXC_INT_IPI_2); + break; + + default: + break; + } + +} + +/* Deliver the interrupt of the corresponding priority, if possible. */ +int +kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority, + uint32_t cause) +{ + int allowed = 0; + uint32_t exccode; + + struct kvm_vcpu_arch *arch = &vcpu->arch; + struct mips_coproc *cop0 = vcpu->arch.cop0; + + switch (priority) { + case MIPS_EXC_INT_TIMER: + if ((kvm_read_c0_guest_status(cop0) & ST0_IE) + && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL))) + && (kvm_read_c0_guest_status(cop0) & IE_IRQ5)) { + allowed = 1; + exccode = T_INT; + } + break; + + case MIPS_EXC_INT_IO: + if ((kvm_read_c0_guest_status(cop0) & ST0_IE) + && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL))) + && (kvm_read_c0_guest_status(cop0) & IE_IRQ0)) { + allowed = 1; + exccode = T_INT; + } + break; + + case MIPS_EXC_INT_IPI_1: + if ((kvm_read_c0_guest_status(cop0) & ST0_IE) + && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL))) + && (kvm_read_c0_guest_status(cop0) & IE_IRQ1)) { + allowed = 1; + exccode = T_INT; + } + break; + + case MIPS_EXC_INT_IPI_2: + if ((kvm_read_c0_guest_status(cop0) & ST0_IE) + && (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL))) + && (kvm_read_c0_guest_status(cop0) & IE_IRQ2)) { + allowed = 1; + exccode = T_INT; + } + break; + + default: + break; + } + + /* Are we allowed to deliver the interrupt ??? */ + if (allowed) { + + if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) { + /* save old pc */ + kvm_write_c0_guest_epc(cop0, arch->pc); + kvm_set_c0_guest_status(cop0, ST0_EXL); + + if (cause & CAUSEF_BD) + kvm_set_c0_guest_cause(cop0, CAUSEF_BD); + else + kvm_clear_c0_guest_cause(cop0, CAUSEF_BD); + + kvm_debug("Delivering INT @ pc %#lx\n", arch->pc); + + } else + kvm_err("Trying to deliver interrupt when EXL is already set\n"); + + kvm_change_c0_guest_cause(cop0, CAUSEF_EXCCODE, + (exccode << CAUSEB_EXCCODE)); + + /* XXXSL Set PC to the interrupt exception entry point */ + if (kvm_read_c0_guest_cause(cop0) & CAUSEF_IV) + arch->pc = KVM_GUEST_KSEG0 + 0x200; + else + arch->pc = KVM_GUEST_KSEG0 + 0x180; + + clear_bit(priority, &vcpu->arch.pending_exceptions); + } + + return allowed; +} + +int +kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority, + uint32_t cause) +{ + return 1; +} + +void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause) +{ + unsigned long *pending = &vcpu->arch.pending_exceptions; + unsigned long *pending_clr = &vcpu->arch.pending_exceptions_clr; + unsigned int priority; + + if (!(*pending) && !(*pending_clr)) + return; + + priority = __ffs(*pending_clr); + while (priority <= MIPS_EXC_MAX) { + if (kvm_mips_callbacks->irq_clear(vcpu, priority, cause)) { + if (!KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE) + break; + } + + priority = find_next_bit(pending_clr, + BITS_PER_BYTE * sizeof(*pending_clr), + priority + 1); + } + + priority = __ffs(*pending); + while (priority <= MIPS_EXC_MAX) { + if (kvm_mips_callbacks->irq_deliver(vcpu, priority, cause)) { + if (!KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE) + break; + } + + priority = find_next_bit(pending, + BITS_PER_BYTE * sizeof(*pending), + priority + 1); + } + +} + +int kvm_mips_pending_timer(struct kvm_vcpu *vcpu) +{ + return test_bit(MIPS_EXC_INT_TIMER, &vcpu->arch.pending_exceptions); +} diff --git a/arch/mips/kvm/kvm_mips_int.h b/arch/mips/kvm/kvm_mips_int.h new file mode 100644 index 000000000000..20da7d29eede --- /dev/null +++ b/arch/mips/kvm/kvm_mips_int.h @@ -0,0 +1,49 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS: Interrupts +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +/* MIPS Exception Priorities, exceptions (including interrupts) are queued up + * for the guest in the order specified by their priorities + */ + +#define MIPS_EXC_RESET 0 +#define MIPS_EXC_SRESET 1 +#define MIPS_EXC_DEBUG_ST 2 +#define MIPS_EXC_DEBUG 3 +#define MIPS_EXC_DDB 4 +#define MIPS_EXC_NMI 5 +#define MIPS_EXC_MCHK 6 +#define MIPS_EXC_INT_TIMER 7 +#define MIPS_EXC_INT_IO 8 +#define MIPS_EXC_EXECUTE 9 +#define MIPS_EXC_INT_IPI_1 10 +#define MIPS_EXC_INT_IPI_2 11 +#define MIPS_EXC_MAX 12 +/* XXXSL More to follow */ + +#define C_TI (_ULCAST_(1) << 30) + +#define KVM_MIPS_IRQ_DELIVER_ALL_AT_ONCE (0) +#define KVM_MIPS_IRQ_CLEAR_ALL_AT_ONCE (0) + +void kvm_mips_queue_irq(struct kvm_vcpu *vcpu, uint32_t priority); +void kvm_mips_dequeue_irq(struct kvm_vcpu *vcpu, uint32_t priority); +int kvm_mips_pending_timer(struct kvm_vcpu *vcpu); + +void kvm_mips_queue_timer_int_cb(struct kvm_vcpu *vcpu); +void kvm_mips_dequeue_timer_int_cb(struct kvm_vcpu *vcpu); +void kvm_mips_queue_io_int_cb(struct kvm_vcpu *vcpu, + struct kvm_mips_interrupt *irq); +void kvm_mips_dequeue_io_int_cb(struct kvm_vcpu *vcpu, + struct kvm_mips_interrupt *irq); +int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority, + uint32_t cause); +int kvm_mips_irq_clear_cb(struct kvm_vcpu *vcpu, unsigned int priority, + uint32_t cause); +void kvm_mips_deliver_interrupts(struct kvm_vcpu *vcpu, uint32_t cause); diff --git a/arch/mips/kvm/kvm_mips_opcode.h b/arch/mips/kvm/kvm_mips_opcode.h new file mode 100644 index 000000000000..86d3b4cc348b --- /dev/null +++ b/arch/mips/kvm/kvm_mips_opcode.h @@ -0,0 +1,24 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +/* + * Define opcode values not defined in <asm/isnt.h> + */ + +#ifndef __KVM_MIPS_OPCODE_H__ +#define __KVM_MIPS_OPCODE_H__ + +/* COP0 Ops */ +#define mfmcz_op 0x0b /* 01011 */ +#define wrpgpr_op 0x0e /* 01110 */ + +/* COP0 opcodes (only if COP0 and CO=1): */ +#define wait_op 0x20 /* 100000 */ + +#endif /* __KVM_MIPS_OPCODE_H__ */ diff --git a/arch/mips/kvm/kvm_mips_stats.c b/arch/mips/kvm/kvm_mips_stats.c new file mode 100644 index 000000000000..075904bcac1b --- /dev/null +++ b/arch/mips/kvm/kvm_mips_stats.c @@ -0,0 +1,82 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS: COP0 access histogram +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/kvm_host.h> + +char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES] = { + "WAIT", + "CACHE", + "Signal", + "Interrupt", + "COP0/1 Unusable", + "TLB Mod", + "TLB Miss (LD)", + "TLB Miss (ST)", + "Address Err (ST)", + "Address Error (LD)", + "System Call", + "Reserved Inst", + "Break Inst", + "D-Cache Flushes", +}; + +char *kvm_cop0_str[N_MIPS_COPROC_REGS] = { + "Index", + "Random", + "EntryLo0", + "EntryLo1", + "Context", + "PG Mask", + "Wired", + "HWREna", + "BadVAddr", + "Count", + "EntryHI", + "Compare", + "Status", + "Cause", + "EXC PC", + "PRID", + "Config", + "LLAddr", + "Watch Lo", + "Watch Hi", + "X Context", + "Reserved", + "Impl Dep", + "Debug", + "DEPC", + "PerfCnt", + "ErrCtl", + "CacheErr", + "TagLo", + "TagHi", + "ErrorEPC", + "DESAVE" +}; + +int kvm_mips_dump_stats(struct kvm_vcpu *vcpu) +{ +#ifdef CONFIG_KVM_MIPS_DEBUG_COP0_COUNTERS + int i, j; + + printk("\nKVM VCPU[%d] COP0 Access Profile:\n", vcpu->vcpu_id); + for (i = 0; i < N_MIPS_COPROC_REGS; i++) { + for (j = 0; j < N_MIPS_COPROC_SEL; j++) { + if (vcpu->arch.cop0->stat[i][j]) + printk("%s[%d]: %lu\n", kvm_cop0_str[i], j, + vcpu->arch.cop0->stat[i][j]); + } + } +#endif + + return 0; +} diff --git a/arch/mips/kvm/kvm_tlb.c b/arch/mips/kvm/kvm_tlb.c new file mode 100644 index 000000000000..e3f0d9b8b6c5 --- /dev/null +++ b/arch/mips/kvm/kvm_tlb.c @@ -0,0 +1,932 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS TLB handling, this file is part of the Linux host kernel so that +* TLB handlers run from KSEG0 +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/smp.h> +#include <linux/mm.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/kvm_host.h> + +#include <asm/cpu.h> +#include <asm/bootinfo.h> +#include <asm/mmu_context.h> +#include <asm/pgtable.h> +#include <asm/cacheflush.h> + +#undef CONFIG_MIPS_MT +#include <asm/r4kcache.h> +#define CONFIG_MIPS_MT + +#define KVM_GUEST_PC_TLB 0 +#define KVM_GUEST_SP_TLB 1 + +#define PRIx64 "llx" + +/* Use VZ EntryHi.EHINV to invalidate TLB entries */ +#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) + +atomic_t kvm_mips_instance; +EXPORT_SYMBOL(kvm_mips_instance); + +/* These function pointers are initialized once the KVM module is loaded */ +pfn_t(*kvm_mips_gfn_to_pfn) (struct kvm *kvm, gfn_t gfn); +EXPORT_SYMBOL(kvm_mips_gfn_to_pfn); + +void (*kvm_mips_release_pfn_clean) (pfn_t pfn); +EXPORT_SYMBOL(kvm_mips_release_pfn_clean); + +bool(*kvm_mips_is_error_pfn) (pfn_t pfn); +EXPORT_SYMBOL(kvm_mips_is_error_pfn); + +uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK; +} + + +uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK; +} + +inline uint32_t kvm_mips_get_commpage_asid (struct kvm_vcpu *vcpu) +{ + return vcpu->kvm->arch.commpage_tlb; +} + + +/* + * Structure defining an tlb entry data set. + */ + +void kvm_mips_dump_host_tlbs(void) +{ + unsigned long old_entryhi; + unsigned long old_pagemask; + struct kvm_mips_tlb tlb; + unsigned long flags; + int i; + + local_irq_save(flags); + + old_entryhi = read_c0_entryhi(); + old_pagemask = read_c0_pagemask(); + + printk("HOST TLBs:\n"); + printk("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK); + + for (i = 0; i < current_cpu_data.tlbsize; i++) { + write_c0_index(i); + mtc0_tlbw_hazard(); + + tlb_read(); + tlbw_use_hazard(); + + tlb.tlb_hi = read_c0_entryhi(); + tlb.tlb_lo0 = read_c0_entrylo0(); + tlb.tlb_lo1 = read_c0_entrylo1(); + tlb.tlb_mask = read_c0_pagemask(); + + printk("TLB%c%3d Hi 0x%08lx ", + (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*', + i, tlb.tlb_hi); + printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ", + (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0), + (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ', + (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ', + (tlb.tlb_lo0 >> 3) & 7); + printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n", + (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1), + (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ', + (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ', + (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask); + } + write_c0_entryhi(old_entryhi); + write_c0_pagemask(old_pagemask); + mtc0_tlbw_hazard(); + local_irq_restore(flags); +} + +void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + struct kvm_mips_tlb tlb; + int i; + + printk("Guest TLBs:\n"); + printk("Guest EntryHi: %#lx\n", kvm_read_c0_guest_entryhi(cop0)); + + for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) { + tlb = vcpu->arch.guest_tlb[i]; + printk("TLB%c%3d Hi 0x%08lx ", + (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*', + i, tlb.tlb_hi); + printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ", + (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0), + (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ', + (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ', + (tlb.tlb_lo0 >> 3) & 7); + printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n", + (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1), + (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ', + (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ', + (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask); + } +} + +void kvm_mips_dump_shadow_tlbs(struct kvm_vcpu *vcpu) +{ + int i; + volatile struct kvm_mips_tlb tlb; + + printk("Shadow TLBs:\n"); + for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) { + tlb = vcpu->arch.shadow_tlb[smp_processor_id()][i]; + printk("TLB%c%3d Hi 0x%08lx ", + (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*', + i, tlb.tlb_hi); + printk("Lo0=0x%09" PRIx64 " %c%c attr %lx ", + (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo0), + (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ', + (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ', + (tlb.tlb_lo0 >> 3) & 7); + printk("Lo1=0x%09" PRIx64 " %c%c attr %lx sz=%lx\n", + (uint64_t) mips3_tlbpfn_to_paddr(tlb.tlb_lo1), + (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ', + (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ', + (tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask); + } +} + +static void kvm_mips_map_page(struct kvm *kvm, gfn_t gfn) +{ + pfn_t pfn; + + if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE) + return; + + pfn = kvm_mips_gfn_to_pfn(kvm, gfn); + + if (kvm_mips_is_error_pfn(pfn)) { + panic("Couldn't get pfn for gfn %#" PRIx64 "!\n", gfn); + } + + kvm->arch.guest_pmap[gfn] = pfn; + return; +} + +/* Translate guest KSEG0 addresses to Host PA */ +unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu, + unsigned long gva) +{ + gfn_t gfn; + uint32_t offset = gva & ~PAGE_MASK; + struct kvm *kvm = vcpu->kvm; + + if (KVM_GUEST_KSEGX(gva) != KVM_GUEST_KSEG0) { + kvm_err("%s/%p: Invalid gva: %#lx\n", __func__, + __builtin_return_address(0), gva); + return KVM_INVALID_PAGE; + } + + gfn = (KVM_GUEST_CPHYSADDR(gva) >> PAGE_SHIFT); + + if (gfn >= kvm->arch.guest_pmap_npages) { + kvm_err("%s: Invalid gfn: %#llx, GVA: %#lx\n", __func__, gfn, + gva); + return KVM_INVALID_PAGE; + } + kvm_mips_map_page(vcpu->kvm, gfn); + return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset; +} + +/* XXXKYMA: Must be called with interrupts disabled */ +/* set flush_dcache_mask == 0 if no dcache flush required */ +int +kvm_mips_host_tlb_write(struct kvm_vcpu *vcpu, unsigned long entryhi, + unsigned long entrylo0, unsigned long entrylo1, int flush_dcache_mask) +{ + unsigned long flags; + unsigned long old_entryhi; + volatile int idx; + + local_irq_save(flags); + + + old_entryhi = read_c0_entryhi(); + write_c0_entryhi(entryhi); + mtc0_tlbw_hazard(); + + tlb_probe(); + tlb_probe_hazard(); + idx = read_c0_index(); + + if (idx > current_cpu_data.tlbsize) { + kvm_err("%s: Invalid Index: %d\n", __func__, idx); + kvm_mips_dump_host_tlbs(); + return -1; + } + + if (idx < 0) { + idx = read_c0_random() % current_cpu_data.tlbsize; + write_c0_index(idx); + mtc0_tlbw_hazard(); + } + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + mtc0_tlbw_hazard(); + + tlb_write_indexed(); + tlbw_use_hazard(); + +#ifdef DEBUG + if (debug) { + kvm_debug("@ %#lx idx: %2d [entryhi(R): %#lx] " + "entrylo0(R): 0x%08lx, entrylo1(R): 0x%08lx\n", + vcpu->arch.pc, idx, read_c0_entryhi(), + read_c0_entrylo0(), read_c0_entrylo1()); + } +#endif + + /* Flush D-cache */ + if (flush_dcache_mask) { + if (entrylo0 & MIPS3_PG_V) { + ++vcpu->stat.flush_dcache_exits; + flush_data_cache_page((entryhi & VPN2_MASK) & ~flush_dcache_mask); + } + if (entrylo1 & MIPS3_PG_V) { + ++vcpu->stat.flush_dcache_exits; + flush_data_cache_page(((entryhi & VPN2_MASK) & ~flush_dcache_mask) | + (0x1 << PAGE_SHIFT)); + } + } + + /* Restore old ASID */ + write_c0_entryhi(old_entryhi); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + local_irq_restore(flags); + return 0; +} + + +/* XXXKYMA: Must be called with interrupts disabled */ +int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr, + struct kvm_vcpu *vcpu) +{ + gfn_t gfn; + pfn_t pfn0, pfn1; + unsigned long vaddr = 0; + unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0; + int even; + struct kvm *kvm = vcpu->kvm; + const int flush_dcache_mask = 0; + + + if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) { + kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr); + kvm_mips_dump_host_tlbs(); + return -1; + } + + gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT); + if (gfn >= kvm->arch.guest_pmap_npages) { + kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__, + gfn, badvaddr); + kvm_mips_dump_host_tlbs(); + return -1; + } + even = !(gfn & 0x1); + vaddr = badvaddr & (PAGE_MASK << 1); + + kvm_mips_map_page(vcpu->kvm, gfn); + kvm_mips_map_page(vcpu->kvm, gfn ^ 0x1); + + if (even) { + pfn0 = kvm->arch.guest_pmap[gfn]; + pfn1 = kvm->arch.guest_pmap[gfn ^ 0x1]; + } else { + pfn0 = kvm->arch.guest_pmap[gfn ^ 0x1]; + pfn1 = kvm->arch.guest_pmap[gfn]; + } + + entryhi = (vaddr | kvm_mips_get_kernel_asid(vcpu)); + entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) | + (0x1 << 1); + entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) | + (0x1 << 1); + + return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1, + flush_dcache_mask); +} + +int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr, + struct kvm_vcpu *vcpu) +{ + pfn_t pfn0, pfn1; + unsigned long flags, old_entryhi = 0, vaddr = 0; + unsigned long entrylo0 = 0, entrylo1 = 0; + + + pfn0 = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT; + pfn1 = 0; + entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | (1 << 2) | + (0x1 << 1); + entrylo1 = 0; + + local_irq_save(flags); + + old_entryhi = read_c0_entryhi(); + vaddr = badvaddr & (PAGE_MASK << 1); + write_c0_entryhi(vaddr | kvm_mips_get_kernel_asid(vcpu)); + mtc0_tlbw_hazard(); + write_c0_entrylo0(entrylo0); + mtc0_tlbw_hazard(); + write_c0_entrylo1(entrylo1); + mtc0_tlbw_hazard(); + write_c0_index(kvm_mips_get_commpage_asid(vcpu)); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + +#ifdef DEBUG + kvm_debug ("@ %#lx idx: %2d [entryhi(R): %#lx] entrylo0 (R): 0x%08lx, entrylo1(R): 0x%08lx\n", + vcpu->arch.pc, read_c0_index(), read_c0_entryhi(), + read_c0_entrylo0(), read_c0_entrylo1()); +#endif + + /* Restore old ASID */ + write_c0_entryhi(old_entryhi); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + local_irq_restore(flags); + + return 0; +} + +int +kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu, + struct kvm_mips_tlb *tlb, unsigned long *hpa0, unsigned long *hpa1) +{ + unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0; + struct kvm *kvm = vcpu->kvm; + pfn_t pfn0, pfn1; + + + if ((tlb->tlb_hi & VPN2_MASK) == 0) { + pfn0 = 0; + pfn1 = 0; + } else { + kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT); + kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT); + + pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0) >> PAGE_SHIFT]; + pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1) >> PAGE_SHIFT]; + } + + if (hpa0) + *hpa0 = pfn0 << PAGE_SHIFT; + + if (hpa1) + *hpa1 = pfn1 << PAGE_SHIFT; + + /* Get attributes from the Guest TLB */ + entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ? + kvm_mips_get_kernel_asid(vcpu) : kvm_mips_get_user_asid(vcpu)); + entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) | + (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V); + entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) | + (tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V); + +#ifdef DEBUG + kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc, + tlb->tlb_lo0, tlb->tlb_lo1); +#endif + + return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1, + tlb->tlb_mask); +} + +int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi) +{ + int i; + int index = -1; + struct kvm_mips_tlb *tlb = vcpu->arch.guest_tlb; + + + for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) { + if (((TLB_VPN2(tlb[i]) & ~tlb[i].tlb_mask) == ((entryhi & VPN2_MASK) & ~tlb[i].tlb_mask)) && + (TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == (entryhi & ASID_MASK)))) { + index = i; + break; + } + } + +#ifdef DEBUG + kvm_debug("%s: entryhi: %#lx, index: %d lo0: %#lx, lo1: %#lx\n", + __func__, entryhi, index, tlb[i].tlb_lo0, tlb[i].tlb_lo1); +#endif + + return index; +} + +int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr) +{ + unsigned long old_entryhi, flags; + volatile int idx; + + + local_irq_save(flags); + + old_entryhi = read_c0_entryhi(); + + if (KVM_GUEST_KERNEL_MODE(vcpu)) + write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_kernel_asid(vcpu)); + else { + write_c0_entryhi((vaddr & VPN2_MASK) | kvm_mips_get_user_asid(vcpu)); + } + + mtc0_tlbw_hazard(); + + tlb_probe(); + tlb_probe_hazard(); + idx = read_c0_index(); + + /* Restore old ASID */ + write_c0_entryhi(old_entryhi); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + + local_irq_restore(flags); + +#ifdef DEBUG + kvm_debug("Host TLB lookup, %#lx, idx: %2d\n", vaddr, idx); +#endif + + return idx; +} + +int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va) +{ + int idx; + unsigned long flags, old_entryhi; + + local_irq_save(flags); + + + old_entryhi = read_c0_entryhi(); + + write_c0_entryhi((va & VPN2_MASK) | kvm_mips_get_user_asid(vcpu)); + mtc0_tlbw_hazard(); + + tlb_probe(); + tlb_probe_hazard(); + idx = read_c0_index(); + + if (idx >= current_cpu_data.tlbsize) + BUG(); + + if (idx > 0) { + write_c0_entryhi(UNIQUE_ENTRYHI(idx)); + mtc0_tlbw_hazard(); + + write_c0_entrylo0(0); + mtc0_tlbw_hazard(); + + write_c0_entrylo1(0); + mtc0_tlbw_hazard(); + + tlb_write_indexed(); + mtc0_tlbw_hazard(); + } + + write_c0_entryhi(old_entryhi); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + + local_irq_restore(flags); + +#ifdef DEBUG + if (idx > 0) { + kvm_debug("%s: Invalidated entryhi %#lx @ idx %d\n", __func__, + (va & VPN2_MASK) | (vcpu->arch.asid_map[va & ASID_MASK] & ASID_MASK), idx); + } +#endif + + return 0; +} + +/* XXXKYMA: Fix Guest USER/KERNEL no longer share the same ASID*/ +int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index) +{ + unsigned long flags, old_entryhi; + + if (index >= current_cpu_data.tlbsize) + BUG(); + + local_irq_save(flags); + + + old_entryhi = read_c0_entryhi(); + + write_c0_entryhi(UNIQUE_ENTRYHI(index)); + mtc0_tlbw_hazard(); + + write_c0_index(index); + mtc0_tlbw_hazard(); + + write_c0_entrylo0(0); + mtc0_tlbw_hazard(); + + write_c0_entrylo1(0); + mtc0_tlbw_hazard(); + + tlb_write_indexed(); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + + write_c0_entryhi(old_entryhi); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + + local_irq_restore(flags); + + return 0; +} + +void kvm_mips_flush_host_tlb(int skip_kseg0) +{ + unsigned long flags; + unsigned long old_entryhi, entryhi; + unsigned long old_pagemask; + int entry = 0; + int maxentry = current_cpu_data.tlbsize; + + + local_irq_save(flags); + + old_entryhi = read_c0_entryhi(); + old_pagemask = read_c0_pagemask(); + + /* Blast 'em all away. */ + for (entry = 0; entry < maxentry; entry++) { + + write_c0_index(entry); + mtc0_tlbw_hazard(); + + if (skip_kseg0) { + tlb_read(); + tlbw_use_hazard(); + + entryhi = read_c0_entryhi(); + + /* Don't blow away guest kernel entries */ + if (KVM_GUEST_KSEGX(entryhi) == KVM_GUEST_KSEG0) { + continue; + } + } + + /* Make sure all entries differ. */ + write_c0_entryhi(UNIQUE_ENTRYHI(entry)); + mtc0_tlbw_hazard(); + write_c0_entrylo0(0); + mtc0_tlbw_hazard(); + write_c0_entrylo1(0); + mtc0_tlbw_hazard(); + + tlb_write_indexed(); + mtc0_tlbw_hazard(); + } + + tlbw_use_hazard(); + + write_c0_entryhi(old_entryhi); + write_c0_pagemask(old_pagemask); + mtc0_tlbw_hazard(); + tlbw_use_hazard(); + + local_irq_restore(flags); +} + +void +kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu, + struct kvm_vcpu *vcpu) +{ + unsigned long asid = asid_cache(cpu); + + if (!((asid += ASID_INC) & ASID_MASK)) { + if (cpu_has_vtag_icache) { + flush_icache_all(); + } + + kvm_local_flush_tlb_all(); /* start new asid cycle */ + + if (!asid) /* fix version if needed */ + asid = ASID_FIRST_VERSION; + } + + cpu_context(cpu, mm) = asid_cache(cpu) = asid; +} + +void kvm_shadow_tlb_put(struct kvm_vcpu *vcpu) +{ + unsigned long flags; + unsigned long old_entryhi; + unsigned long old_pagemask; + int entry = 0; + int cpu = smp_processor_id(); + + local_irq_save(flags); + + old_entryhi = read_c0_entryhi(); + old_pagemask = read_c0_pagemask(); + + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + write_c0_index(entry); + mtc0_tlbw_hazard(); + tlb_read(); + tlbw_use_hazard(); + + vcpu->arch.shadow_tlb[cpu][entry].tlb_hi = read_c0_entryhi(); + vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = read_c0_entrylo0(); + vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = read_c0_entrylo1(); + vcpu->arch.shadow_tlb[cpu][entry].tlb_mask = read_c0_pagemask(); + } + + write_c0_entryhi(old_entryhi); + write_c0_pagemask(old_pagemask); + mtc0_tlbw_hazard(); + + local_irq_restore(flags); + +} + +void kvm_shadow_tlb_load(struct kvm_vcpu *vcpu) +{ + unsigned long flags; + unsigned long old_ctx; + int entry; + int cpu = smp_processor_id(); + + local_irq_save(flags); + + old_ctx = read_c0_entryhi(); + + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + write_c0_entryhi(vcpu->arch.shadow_tlb[cpu][entry].tlb_hi); + mtc0_tlbw_hazard(); + write_c0_entrylo0(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0); + write_c0_entrylo1(vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1); + + write_c0_index(entry); + mtc0_tlbw_hazard(); + + tlb_write_indexed(); + tlbw_use_hazard(); + } + + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + mtc0_tlbw_hazard(); + local_irq_restore(flags); +} + + +void kvm_local_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + int entry = 0; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + + /* Blast 'em all away. */ + while (entry < current_cpu_data.tlbsize) { + /* Make sure all entries differ. */ + write_c0_entryhi(UNIQUE_ENTRYHI(entry)); + write_c0_index(entry); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + entry++; + } + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + mtc0_tlbw_hazard(); + + local_irq_restore(flags); +} + +void kvm_mips_init_shadow_tlb(struct kvm_vcpu *vcpu) +{ + int cpu, entry; + + for_each_possible_cpu(cpu) { + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + vcpu->arch.shadow_tlb[cpu][entry].tlb_hi = + UNIQUE_ENTRYHI(entry); + vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0 = 0x0; + vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1 = 0x0; + vcpu->arch.shadow_tlb[cpu][entry].tlb_mask = + read_c0_pagemask(); +#ifdef DEBUG + kvm_debug + ("shadow_tlb[%d][%d]: tlb_hi: %#lx, lo0: %#lx, lo1: %#lx\n", + cpu, entry, + vcpu->arch.shadow_tlb[cpu][entry].tlb_hi, + vcpu->arch.shadow_tlb[cpu][entry].tlb_lo0, + vcpu->arch.shadow_tlb[cpu][entry].tlb_lo1); +#endif + } + } +} + +/* Restore ASID once we are scheduled back after preemption */ +void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) +{ + unsigned long flags; + int newasid = 0; + +#ifdef DEBUG + kvm_debug("%s: vcpu %p, cpu: %d\n", __func__, vcpu, cpu); +#endif + + /* Alocate new kernel and user ASIDs if needed */ + + local_irq_save(flags); + + if (((vcpu->arch. + guest_kernel_asid[cpu] ^ asid_cache(cpu)) & ASID_VERSION_MASK)) { + kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu); + vcpu->arch.guest_kernel_asid[cpu] = + vcpu->arch.guest_kernel_mm.context.asid[cpu]; + kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu); + vcpu->arch.guest_user_asid[cpu] = + vcpu->arch.guest_user_mm.context.asid[cpu]; + newasid++; + + kvm_info("[%d]: cpu_context: %#lx\n", cpu, + cpu_context(cpu, current->mm)); + kvm_info("[%d]: Allocated new ASID for Guest Kernel: %#x\n", + cpu, vcpu->arch.guest_kernel_asid[cpu]); + kvm_info("[%d]: Allocated new ASID for Guest User: %#x\n", cpu, + vcpu->arch.guest_user_asid[cpu]); + } + + if (vcpu->arch.last_sched_cpu != cpu) { + kvm_info("[%d->%d]KVM VCPU[%d] switch\n", + vcpu->arch.last_sched_cpu, cpu, vcpu->vcpu_id); + } + + /* Only reload shadow host TLB if new ASIDs haven't been allocated */ +#if 0 + if ((atomic_read(&kvm_mips_instance) > 1) && !newasid) { + kvm_mips_flush_host_tlb(0); + kvm_shadow_tlb_load(vcpu); + } +#endif + + if (!newasid) { + /* If we preempted while the guest was executing, then reload the pre-empted ASID */ + if (current->flags & PF_VCPU) { + write_c0_entryhi(vcpu->arch. + preempt_entryhi & ASID_MASK); + ehb(); + } + } else { + /* New ASIDs were allocated for the VM */ + + /* Were we in guest context? If so then the pre-empted ASID is no longer + * valid, we need to set it to what it should be based on the mode of + * the Guest (Kernel/User) + */ + if (current->flags & PF_VCPU) { + if (KVM_GUEST_KERNEL_MODE(vcpu)) + write_c0_entryhi(vcpu->arch. + guest_kernel_asid[cpu] & + ASID_MASK); + else + write_c0_entryhi(vcpu->arch. + guest_user_asid[cpu] & + ASID_MASK); + ehb(); + } + } + + local_irq_restore(flags); + +} + +/* ASID can change if another task is scheduled during preemption */ +void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) +{ + unsigned long flags; + uint32_t cpu; + + local_irq_save(flags); + + cpu = smp_processor_id(); + + + vcpu->arch.preempt_entryhi = read_c0_entryhi(); + vcpu->arch.last_sched_cpu = cpu; + +#if 0 + if ((atomic_read(&kvm_mips_instance) > 1)) { + kvm_shadow_tlb_put(vcpu); + } +#endif + + if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) & + ASID_VERSION_MASK)) { + kvm_debug("%s: Dropping MMU Context: %#lx\n", __func__, + cpu_context(cpu, current->mm)); + drop_mmu_context(current->mm, cpu); + } + write_c0_entryhi(cpu_asid(cpu, current->mm)); + ehb(); + + local_irq_restore(flags); +} + +uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + unsigned long paddr, flags; + uint32_t inst; + int index; + + if (KVM_GUEST_KSEGX((unsigned long) opc) < KVM_GUEST_KSEG0 || + KVM_GUEST_KSEGX((unsigned long) opc) == KVM_GUEST_KSEG23) { + local_irq_save(flags); + index = kvm_mips_host_tlb_lookup(vcpu, (unsigned long) opc); + if (index >= 0) { + inst = *(opc); + } else { + index = + kvm_mips_guest_tlb_lookup(vcpu, + ((unsigned long) opc & VPN2_MASK) + | + (kvm_read_c0_guest_entryhi + (cop0) & ASID_MASK)); + if (index < 0) { + kvm_err + ("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n", + __func__, opc, vcpu, read_c0_entryhi()); + kvm_mips_dump_host_tlbs(); + local_irq_restore(flags); + return KVM_INVALID_INST; + } + kvm_mips_handle_mapped_seg_tlb_fault(vcpu, + &vcpu->arch. + guest_tlb[index], + NULL, NULL); + inst = *(opc); + } + local_irq_restore(flags); + } else if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) { + paddr = + kvm_mips_translate_guest_kseg0_to_hpa(vcpu, + (unsigned long) opc); + inst = *(uint32_t *) CKSEG0ADDR(paddr); + } else { + kvm_err("%s: illegal address: %p\n", __func__, opc); + return KVM_INVALID_INST; + } + + return inst; +} + +EXPORT_SYMBOL(kvm_local_flush_tlb_all); +EXPORT_SYMBOL(kvm_shadow_tlb_put); +EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault); +EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault); +EXPORT_SYMBOL(kvm_mips_init_shadow_tlb); +EXPORT_SYMBOL(kvm_mips_dump_host_tlbs); +EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault); +EXPORT_SYMBOL(kvm_mips_host_tlb_lookup); +EXPORT_SYMBOL(kvm_mips_flush_host_tlb); +EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup); +EXPORT_SYMBOL(kvm_mips_host_tlb_inv); +EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa); +EXPORT_SYMBOL(kvm_shadow_tlb_load); +EXPORT_SYMBOL(kvm_mips_dump_shadow_tlbs); +EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs); +EXPORT_SYMBOL(kvm_get_inst); +EXPORT_SYMBOL(kvm_arch_vcpu_load); +EXPORT_SYMBOL(kvm_arch_vcpu_put); diff --git a/arch/mips/kvm/kvm_trap_emul.c b/arch/mips/kvm/kvm_trap_emul.c new file mode 100644 index 000000000000..466aeef044bd --- /dev/null +++ b/arch/mips/kvm/kvm_trap_emul.c @@ -0,0 +1,482 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* KVM/MIPS: Deliver/Emulate exceptions to the guest kernel +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/vmalloc.h> + +#include <linux/kvm_host.h> + +#include "kvm_mips_opcode.h" +#include "kvm_mips_int.h" + +static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva) +{ + gpa_t gpa; + uint32_t kseg = KSEGX(gva); + + if ((kseg == CKSEG0) || (kseg == CKSEG1)) + gpa = CPHYSADDR(gva); + else { + printk("%s: cannot find GPA for GVA: %#lx\n", __func__, gva); + kvm_mips_dump_host_tlbs(); + gpa = KVM_INVALID_ADDR; + } + +#ifdef DEBUG + kvm_debug("%s: gva %#lx, gpa: %#llx\n", __func__, gva, gpa); +#endif + + return gpa; +} + + +static int kvm_trap_emul_handle_cop_unusable(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 1) { + er = kvm_mips_emulate_fpu_exc(cause, opc, run, vcpu); + } else + er = kvm_mips_emulate_inst(cause, opc, run, vcpu); + + switch (er) { + case EMULATE_DONE: + ret = RESUME_GUEST; + break; + + case EMULATE_FAIL: + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + break; + + case EMULATE_WAIT: + run->exit_reason = KVM_EXIT_INTR; + ret = RESUME_HOST; + break; + + default: + BUG(); + } + return ret; +} + +static int kvm_trap_emul_handle_tlb_mod(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0 + || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) { +#ifdef DEBUG + kvm_debug + ("USER/KSEG23 ADDR TLB MOD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); +#endif + er = kvm_mips_handle_tlbmod(cause, opc, run, vcpu); + + if (er == EMULATE_DONE) + ret = RESUME_GUEST; + else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + } else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) { + /* XXXKYMA: The guest kernel does not expect to get this fault when we are not + * using HIGHMEM. Need to address this in a HIGHMEM kernel + */ + printk + ("TLB MOD fault not handled, cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); + kvm_mips_dump_host_tlbs(); + kvm_arch_vcpu_dump_regs(vcpu); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } else { + printk + ("Illegal TLB Mod fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); + kvm_mips_dump_host_tlbs(); + kvm_arch_vcpu_dump_regs(vcpu); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_tlb_st_miss(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) + && KVM_GUEST_KERNEL_MODE(vcpu)) { + if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + } else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0 + || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) { +#ifdef DEBUG + kvm_debug + ("USER ADDR TLB LD fault: cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); +#endif + er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu); + if (er == EMULATE_DONE) + ret = RESUME_GUEST; + else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + } else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) { + /* All KSEG0 faults are handled by KVM, as the guest kernel does not + * expect to ever get them + */ + if (kvm_mips_handle_kseg0_tlb_fault + (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + } else { + kvm_err + ("Illegal TLB LD fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); + kvm_mips_dump_host_tlbs(); + kvm_arch_vcpu_dump_regs(vcpu); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_tlb_ld_miss(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + if (((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) + && KVM_GUEST_KERNEL_MODE(vcpu)) { + if (kvm_mips_handle_commpage_tlb_fault(badvaddr, vcpu) < 0) { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + } else if (KVM_GUEST_KSEGX(badvaddr) < KVM_GUEST_KSEG0 + || KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG23) { +#ifdef DEBUG + kvm_debug("USER ADDR TLB ST fault: PC: %#lx, BadVaddr: %#lx\n", + vcpu->arch.pc, badvaddr); +#endif + + /* User Address (UA) fault, this could happen if + * (1) TLB entry not present/valid in both Guest and shadow host TLBs, in this + * case we pass on the fault to the guest kernel and let it handle it. + * (2) TLB entry is present in the Guest TLB but not in the shadow, in this + * case we inject the TLB from the Guest TLB into the shadow host TLB + */ + + er = kvm_mips_handle_tlbmiss(cause, opc, run, vcpu); + if (er == EMULATE_DONE) + ret = RESUME_GUEST; + else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + } else if (KVM_GUEST_KSEGX(badvaddr) == KVM_GUEST_KSEG0) { + if (kvm_mips_handle_kseg0_tlb_fault + (vcpu->arch.host_cp0_badvaddr, vcpu) < 0) { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + } else { + printk + ("Illegal TLB ST fault address , cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); + kvm_mips_dump_host_tlbs(); + kvm_arch_vcpu_dump_regs(vcpu); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_addr_err_st(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + if (KVM_GUEST_KERNEL_MODE(vcpu) + && (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1)) { +#ifdef DEBUG + kvm_debug("Emulate Store to MMIO space\n"); +#endif + er = kvm_mips_emulate_inst(cause, opc, run, vcpu); + if (er == EMULATE_FAIL) { + printk("Emulate Store to MMIO space failed\n"); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } else { + run->exit_reason = KVM_EXIT_MMIO; + ret = RESUME_HOST; + } + } else { + printk + ("Address Error (STORE): cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_addr_err_ld(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + if (KSEGX(badvaddr) == CKSEG0 || KSEGX(badvaddr) == CKSEG1) { +#ifdef DEBUG + kvm_debug("Emulate Load from MMIO space @ %#lx\n", badvaddr); +#endif + er = kvm_mips_emulate_inst(cause, opc, run, vcpu); + if (er == EMULATE_FAIL) { + printk("Emulate Load from MMIO space failed\n"); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } else { + run->exit_reason = KVM_EXIT_MMIO; + ret = RESUME_HOST; + } + } else { + printk + ("Address Error (LOAD): cause %#lx, PC: %p, BadVaddr: %#lx\n", + cause, opc, badvaddr); + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + er = EMULATE_FAIL; + } + return ret; +} + +static int kvm_trap_emul_handle_syscall(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + er = kvm_mips_emulate_syscall(cause, opc, run, vcpu); + if (er == EMULATE_DONE) + ret = RESUME_GUEST; + else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_res_inst(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + er = kvm_mips_handle_ri(cause, opc, run, vcpu); + if (er == EMULATE_DONE) + ret = RESUME_GUEST; + else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; + unsigned long cause = vcpu->arch.host_cp0_cause; + enum emulation_result er = EMULATE_DONE; + int ret = RESUME_GUEST; + + er = kvm_mips_emulate_bp_exc(cause, opc, run, vcpu); + if (er == EMULATE_DONE) + ret = RESUME_GUEST; + else { + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + ret = RESUME_HOST; + } + return ret; +} + +static int +kvm_trap_emul_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + + kvm_write_c0_guest_index(cop0, regs->cp0reg[MIPS_CP0_TLB_INDEX][0]); + kvm_write_c0_guest_context(cop0, regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0]); + kvm_write_c0_guest_badvaddr(cop0, regs->cp0reg[MIPS_CP0_BAD_VADDR][0]); + kvm_write_c0_guest_entryhi(cop0, regs->cp0reg[MIPS_CP0_TLB_HI][0]); + kvm_write_c0_guest_epc(cop0, regs->cp0reg[MIPS_CP0_EXC_PC][0]); + + kvm_write_c0_guest_status(cop0, regs->cp0reg[MIPS_CP0_STATUS][0]); + kvm_write_c0_guest_cause(cop0, regs->cp0reg[MIPS_CP0_CAUSE][0]); + kvm_write_c0_guest_pagemask(cop0, + regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0]); + kvm_write_c0_guest_wired(cop0, regs->cp0reg[MIPS_CP0_TLB_WIRED][0]); + kvm_write_c0_guest_errorepc(cop0, regs->cp0reg[MIPS_CP0_ERROR_PC][0]); + + return 0; +} + +static int +kvm_trap_emul_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + + regs->cp0reg[MIPS_CP0_TLB_INDEX][0] = kvm_read_c0_guest_index(cop0); + regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0] = kvm_read_c0_guest_context(cop0); + regs->cp0reg[MIPS_CP0_BAD_VADDR][0] = kvm_read_c0_guest_badvaddr(cop0); + regs->cp0reg[MIPS_CP0_TLB_HI][0] = kvm_read_c0_guest_entryhi(cop0); + regs->cp0reg[MIPS_CP0_EXC_PC][0] = kvm_read_c0_guest_epc(cop0); + + regs->cp0reg[MIPS_CP0_STATUS][0] = kvm_read_c0_guest_status(cop0); + regs->cp0reg[MIPS_CP0_CAUSE][0] = kvm_read_c0_guest_cause(cop0); + regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0] = + kvm_read_c0_guest_pagemask(cop0); + regs->cp0reg[MIPS_CP0_TLB_WIRED][0] = kvm_read_c0_guest_wired(cop0); + regs->cp0reg[MIPS_CP0_ERROR_PC][0] = kvm_read_c0_guest_errorepc(cop0); + + regs->cp0reg[MIPS_CP0_CONFIG][0] = kvm_read_c0_guest_config(cop0); + regs->cp0reg[MIPS_CP0_CONFIG][1] = kvm_read_c0_guest_config1(cop0); + regs->cp0reg[MIPS_CP0_CONFIG][2] = kvm_read_c0_guest_config2(cop0); + regs->cp0reg[MIPS_CP0_CONFIG][3] = kvm_read_c0_guest_config3(cop0); + regs->cp0reg[MIPS_CP0_CONFIG][7] = kvm_read_c0_guest_config7(cop0); + + return 0; +} + +static int kvm_trap_emul_vm_init(struct kvm *kvm) +{ + return 0; +} + +static int kvm_trap_emul_vcpu_init(struct kvm_vcpu *vcpu) +{ + return 0; +} + +static int kvm_trap_emul_vcpu_setup(struct kvm_vcpu *vcpu) +{ + struct mips_coproc *cop0 = vcpu->arch.cop0; + uint32_t config1; + int vcpu_id = vcpu->vcpu_id; + + /* Arch specific stuff, set up config registers properly so that the + * guest will come up as expected, for now we simulate a + * MIPS 24kc + */ + kvm_write_c0_guest_prid(cop0, 0x00019300); + kvm_write_c0_guest_config(cop0, + MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT)); + + /* Read the cache characteristics from the host Config1 Register */ + config1 = (read_c0_config1() & ~0x7f); + + /* Set up MMU size */ + config1 &= ~(0x3f << 25); + config1 |= ((KVM_MIPS_GUEST_TLB_SIZE - 1) << 25); + + /* We unset some bits that we aren't emulating */ + config1 &= + ~((1 << CP0C1_C2) | (1 << CP0C1_MD) | (1 << CP0C1_PC) | + (1 << CP0C1_WR) | (1 << CP0C1_CA)); + kvm_write_c0_guest_config1(cop0, config1); + + kvm_write_c0_guest_config2(cop0, MIPS_CONFIG2); + /* MIPS_CONFIG2 | (read_c0_config2() & 0xfff) */ + kvm_write_c0_guest_config3(cop0, + MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << + CP0C3_ULRI)); + + /* Set Wait IE/IXMT Ignore in Config7, IAR, AR */ + kvm_write_c0_guest_config7(cop0, (MIPS_CONF7_WII) | (1 << 10)); + + /* Setup IntCtl defaults, compatibilty mode for timer interrupts (HW5) */ + kvm_write_c0_guest_intctl(cop0, 0xFC000000); + + /* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */ + kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF)); + + return 0; +} + +static struct kvm_mips_callbacks kvm_trap_emul_callbacks = { + /* exit handlers */ + .handle_cop_unusable = kvm_trap_emul_handle_cop_unusable, + .handle_tlb_mod = kvm_trap_emul_handle_tlb_mod, + .handle_tlb_st_miss = kvm_trap_emul_handle_tlb_st_miss, + .handle_tlb_ld_miss = kvm_trap_emul_handle_tlb_ld_miss, + .handle_addr_err_st = kvm_trap_emul_handle_addr_err_st, + .handle_addr_err_ld = kvm_trap_emul_handle_addr_err_ld, + .handle_syscall = kvm_trap_emul_handle_syscall, + .handle_res_inst = kvm_trap_emul_handle_res_inst, + .handle_break = kvm_trap_emul_handle_break, + + .vm_init = kvm_trap_emul_vm_init, + .vcpu_init = kvm_trap_emul_vcpu_init, + .vcpu_setup = kvm_trap_emul_vcpu_setup, + .gva_to_gpa = kvm_trap_emul_gva_to_gpa_cb, + .queue_timer_int = kvm_mips_queue_timer_int_cb, + .dequeue_timer_int = kvm_mips_dequeue_timer_int_cb, + .queue_io_int = kvm_mips_queue_io_int_cb, + .dequeue_io_int = kvm_mips_dequeue_io_int_cb, + .irq_deliver = kvm_mips_irq_deliver_cb, + .irq_clear = kvm_mips_irq_clear_cb, + .vcpu_ioctl_get_regs = kvm_trap_emul_ioctl_get_regs, + .vcpu_ioctl_set_regs = kvm_trap_emul_ioctl_set_regs, +}; + +int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks) +{ + *install_callbacks = &kvm_trap_emul_callbacks; + return 0; +} diff --git a/arch/mips/kvm/trace.h b/arch/mips/kvm/trace.h new file mode 100644 index 000000000000..bc9e0f406c08 --- /dev/null +++ b/arch/mips/kvm/trace.h @@ -0,0 +1,46 @@ +/* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +* +* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. +* Authors: Sanjay Lal <sanjayl@kymasys.com> +*/ + +#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_KVM_H + +#include <linux/tracepoint.h> + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM kvm +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE trace + +/* + * Tracepoints for VM eists + */ +extern char *kvm_mips_exit_types_str[MAX_KVM_MIPS_EXIT_TYPES]; + +TRACE_EVENT(kvm_exit, + TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason), + TP_ARGS(vcpu, reason), + TP_STRUCT__entry( + __field(struct kvm_vcpu *, vcpu) + __field(unsigned int, reason) + ), + + TP_fast_assign( + __entry->vcpu = vcpu; + __entry->reason = reason; + ), + + TP_printk("[%s]PC: 0x%08lx", + kvm_mips_exit_types_str[__entry->reason], + __entry->vcpu->arch.pc) +); + +#endif /* _TRACE_KVM_H */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/arch/mips/lantiq/xway/gptu.c b/arch/mips/lantiq/xway/gptu.c index 9861c8669fab..850821df924c 100644 --- a/arch/mips/lantiq/xway/gptu.c +++ b/arch/mips/lantiq/xway/gptu.c @@ -144,10 +144,6 @@ static int gptu_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Failed to get resource\n"); - return -ENOMEM; - } /* remap gptu register range */ gptu_membase = devm_ioremap_resource(&pdev->dev, res); @@ -169,6 +165,8 @@ static int gptu_probe(struct platform_device *pdev) if (((gptu_r32(GPTU_ID) >> 8) & 0xff) != GPTU_MAGIC) { dev_err(&pdev->dev, "Failed to find magic\n"); gptu_hwexit(); + clk_disable(clk); + clk_put(clk); return -ENAVAIL; } diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c index a64daee740ee..3b2a1e78a543 100644 --- a/arch/mips/lib/bitops.c +++ b/arch/mips/lib/bitops.c @@ -19,7 +19,7 @@ */ void __mips_set_bit(unsigned long nr, volatile unsigned long *addr) { - volatile unsigned long *a = addr; + unsigned long *a = (unsigned long *)addr; unsigned bit = nr & SZLONG_MASK; unsigned long mask; unsigned long flags; @@ -41,7 +41,7 @@ EXPORT_SYMBOL(__mips_set_bit); */ void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr) { - volatile unsigned long *a = addr; + unsigned long *a = (unsigned long *)addr; unsigned bit = nr & SZLONG_MASK; unsigned long mask; unsigned long flags; @@ -63,7 +63,7 @@ EXPORT_SYMBOL(__mips_clear_bit); */ void __mips_change_bit(unsigned long nr, volatile unsigned long *addr) { - volatile unsigned long *a = addr; + unsigned long *a = (unsigned long *)addr; unsigned bit = nr & SZLONG_MASK; unsigned long mask; unsigned long flags; @@ -86,7 +86,7 @@ EXPORT_SYMBOL(__mips_change_bit); int __mips_test_and_set_bit(unsigned long nr, volatile unsigned long *addr) { - volatile unsigned long *a = addr; + unsigned long *a = (unsigned long *)addr; unsigned bit = nr & SZLONG_MASK; unsigned long mask; unsigned long flags; @@ -112,7 +112,7 @@ EXPORT_SYMBOL(__mips_test_and_set_bit); int __mips_test_and_set_bit_lock(unsigned long nr, volatile unsigned long *addr) { - volatile unsigned long *a = addr; + unsigned long *a = (unsigned long *)addr; unsigned bit = nr & SZLONG_MASK; unsigned long mask; unsigned long flags; @@ -137,7 +137,7 @@ EXPORT_SYMBOL(__mips_test_and_set_bit_lock); */ int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) { - volatile unsigned long *a = addr; + unsigned long *a = (unsigned long *)addr; unsigned bit = nr & SZLONG_MASK; unsigned long mask; unsigned long flags; @@ -162,7 +162,7 @@ EXPORT_SYMBOL(__mips_test_and_clear_bit); */ int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr) { - volatile unsigned long *a = addr; + unsigned long *a = (unsigned long *)addr; unsigned bit = nr & SZLONG_MASK; unsigned long mask; unsigned long flags; diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 053d3b0b0317..0580194e7402 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S @@ -5,7 +5,8 @@ * * Copyright (C) 1998, 1999, 2000 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Copyright (C) 2007 Maciej W. Rozycki + * Copyright (C) 2007 by Maciej W. Rozycki + * Copyright (C) 2011, 2012 MIPS Technologies, Inc. */ #include <asm/asm.h> #include <asm/asm-offsets.h> @@ -19,6 +20,20 @@ #define LONG_S_R sdr #endif +#ifdef CONFIG_CPU_MICROMIPS +#define STORSIZE (LONGSIZE * 2) +#define STORMASK (STORSIZE - 1) +#define FILL64RG t8 +#define FILLPTRG t7 +#undef LONG_S +#define LONG_S LONG_SP +#else +#define STORSIZE LONGSIZE +#define STORMASK LONGMASK +#define FILL64RG a1 +#define FILLPTRG t0 +#endif + #define EX(insn,reg,addr,handler) \ 9: insn reg, addr; \ .section __ex_table,"a"; \ @@ -26,23 +41,25 @@ .previous .macro f_fill64 dst, offset, val, fixup - EX(LONG_S, \val, (\offset + 0 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 1 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 2 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 3 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 4 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 5 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 6 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 7 * LONGSIZE)(\dst), \fixup) -#if LONGSIZE == 4 - EX(LONG_S, \val, (\offset + 8 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 9 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup) - EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 3 * STORSIZE)(\dst), \fixup) +#if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS)) + EX(LONG_S, \val, (\offset + 4 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 5 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 6 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 7 * STORSIZE)(\dst), \fixup) +#endif +#if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) + EX(LONG_S, \val, (\offset + 8 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 9 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup) + EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup) #endif .endm @@ -71,16 +88,20 @@ LEAF(memset) 1: FEXPORT(__bzero) - sltiu t0, a2, LONGSIZE /* very small region? */ + sltiu t0, a2, STORSIZE /* very small region? */ bnez t0, .Lsmall_memset - andi t0, a0, LONGMASK /* aligned? */ + andi t0, a0, STORMASK /* aligned? */ +#ifdef CONFIG_CPU_MICROMIPS + move t8, a1 /* used by 'swp' instruction */ + move t9, a1 +#endif #ifndef CONFIG_CPU_DADDI_WORKAROUNDS beqz t0, 1f - PTR_SUBU t0, LONGSIZE /* alignment in bytes */ + PTR_SUBU t0, STORSIZE /* alignment in bytes */ #else .set noat - li AT, LONGSIZE + li AT, STORSIZE beqz t0, 1f PTR_SUBU t0, AT /* alignment in bytes */ .set at @@ -99,24 +120,27 @@ FEXPORT(__bzero) 1: ori t1, a2, 0x3f /* # of full blocks */ xori t1, 0x3f beqz t1, .Lmemset_partial /* no block to fill */ - andi t0, a2, 0x40-LONGSIZE + andi t0, a2, 0x40-STORSIZE PTR_ADDU t1, a0 /* end address */ .set reorder 1: PTR_ADDIU a0, 64 R10KCBARRIER(0(ra)) - f_fill64 a0, -64, a1, .Lfwd_fixup + f_fill64 a0, -64, FILL64RG, .Lfwd_fixup bne t1, a0, 1b .set noreorder .Lmemset_partial: R10KCBARRIER(0(ra)) PTR_LA t1, 2f /* where to start */ +#ifdef CONFIG_CPU_MICROMIPS + LONG_SRL t7, t0, 1 +#endif #if LONGSIZE == 4 - PTR_SUBU t1, t0 + PTR_SUBU t1, FILLPTRG #else .set noat - LONG_SRL AT, t0, 1 + LONG_SRL AT, FILLPTRG, 1 PTR_SUBU t1, AT .set at #endif @@ -126,9 +150,9 @@ FEXPORT(__bzero) .set push .set noreorder .set nomacro - f_fill64 a0, -64, a1, .Lpartial_fixup /* ... but first do longs ... */ + f_fill64 a0, -64, FILL64RG, .Lpartial_fixup /* ... but first do longs ... */ 2: .set pop - andi a2, LONGMASK /* At most one long to go */ + andi a2, STORMASK /* At most one long to go */ beqz a2, 1f PTR_ADDU a0, a2 /* What's left */ @@ -169,7 +193,7 @@ FEXPORT(__bzero) .Lpartial_fixup: PTR_L t0, TI_TASK($28) - andi a2, LONGMASK + andi a2, STORMASK LONG_L t0, THREAD_BUADDR(t0) LONG_ADDU a2, t1 jr ra @@ -177,4 +201,4 @@ FEXPORT(__bzero) .Llast_fixup: jr ra - andi v1, a2, LONGMASK + andi v1, a2, STORMASK diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c index cd160be3ce4d..6807f7172eaf 100644 --- a/arch/mips/lib/mips-atomic.c +++ b/arch/mips/lib/mips-atomic.c @@ -13,6 +13,7 @@ #include <linux/compiler.h> #include <linux/preempt.h> #include <linux/export.h> +#include <linux/stringify.h> #if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) @@ -34,8 +35,11 @@ * * Workaround: mask EXL bit of the result or place a nop before mfc0. */ -__asm__( - " .macro arch_local_irq_disable\n" +notrace void arch_local_irq_disable(void) +{ + preempt_disable(); + + __asm__ __volatile__( " .set push \n" " .set noat \n" #ifdef CONFIG_MIPS_MT_SMTC @@ -52,108 +56,98 @@ __asm__( " .set noreorder \n" " mtc0 $1,$12 \n" #endif - " irq_disable_hazard \n" + " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" - " .endm \n"); + : /* no outputs */ + : /* no inputs */ + : "memory"); -notrace void arch_local_irq_disable(void) -{ - preempt_disable(); - __asm__ __volatile__( - "arch_local_irq_disable" - : /* no outputs */ - : /* no inputs */ - : "memory"); preempt_enable(); } EXPORT_SYMBOL(arch_local_irq_disable); -__asm__( - " .macro arch_local_irq_save result \n" +notrace unsigned long arch_local_irq_save(void) +{ + unsigned long flags; + + preempt_disable(); + + __asm__ __volatile__( " .set push \n" " .set reorder \n" " .set noat \n" #ifdef CONFIG_MIPS_MT_SMTC - " mfc0 \\result, $2, 1 \n" - " ori $1, \\result, 0x400 \n" + " mfc0 %[flags], $2, 1 \n" + " ori $1, %[flags], 0x400 \n" " .set noreorder \n" " mtc0 $1, $2, 1 \n" - " andi \\result, \\result, 0x400 \n" + " andi %[flags], %[flags], 0x400 \n" #elif defined(CONFIG_CPU_MIPSR2) /* see irqflags.h for inline function */ #else - " mfc0 \\result, $12 \n" - " ori $1, \\result, 0x1f \n" + " mfc0 %[flags], $12 \n" + " ori $1, %[flags], 0x1f \n" " xori $1, 0x1f \n" " .set noreorder \n" " mtc0 $1, $12 \n" #endif - " irq_disable_hazard \n" + " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" - " .endm \n"); + : [flags] "=r" (flags) + : /* no inputs */ + : "memory"); -notrace unsigned long arch_local_irq_save(void) -{ - unsigned long flags; - preempt_disable(); - asm volatile("arch_local_irq_save\t%0" - : "=r" (flags) - : /* no inputs */ - : "memory"); preempt_enable(); + return flags; } EXPORT_SYMBOL(arch_local_irq_save); +notrace void arch_local_irq_restore(unsigned long flags) +{ + unsigned long __tmp1; + +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC kernel needs to do a software replay of queued + * IPIs, at the cost of branch and call overhead on each + * local_irq_restore() + */ + if (unlikely(!(flags & 0x0400))) + smtc_ipi_replay(); +#endif + preempt_disable(); -__asm__( - " .macro arch_local_irq_restore flags \n" + __asm__ __volatile__( " .set push \n" " .set noreorder \n" " .set noat \n" #ifdef CONFIG_MIPS_MT_SMTC - "mfc0 $1, $2, 1 \n" - "andi \\flags, 0x400 \n" - "ori $1, 0x400 \n" - "xori $1, 0x400 \n" - "or \\flags, $1 \n" - "mtc0 \\flags, $2, 1 \n" + " mfc0 $1, $2, 1 \n" + " andi %[flags], 0x400 \n" + " ori $1, 0x400 \n" + " xori $1, 0x400 \n" + " or %[flags], $1 \n" + " mtc0 %[flags], $2, 1 \n" #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) /* see irqflags.h for inline function */ #elif defined(CONFIG_CPU_MIPSR2) /* see irqflags.h for inline function */ #else " mfc0 $1, $12 \n" - " andi \\flags, 1 \n" + " andi %[flags], 1 \n" " ori $1, 0x1f \n" " xori $1, 0x1f \n" - " or \\flags, $1 \n" - " mtc0 \\flags, $12 \n" + " or %[flags], $1 \n" + " mtc0 %[flags], $12 \n" #endif - " irq_disable_hazard \n" + " " __stringify(__irq_disable_hazard) " \n" " .set pop \n" - " .endm \n"); + : [flags] "=r" (__tmp1) + : "0" (flags) + : "memory"); -notrace void arch_local_irq_restore(unsigned long flags) -{ - unsigned long __tmp1; - -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC kernel needs to do a software replay of queued - * IPIs, at the cost of branch and call overhead on each - * local_irq_restore() - */ - if (unlikely(!(flags & 0x0400))) - smtc_ipi_replay(); -#endif - preempt_disable(); - __asm__ __volatile__( - "arch_local_irq_restore\t%0" - : "=r" (__tmp1) - : "0" (flags) - : "memory"); preempt_enable(); } EXPORT_SYMBOL(arch_local_irq_restore); @@ -164,11 +158,36 @@ notrace void __arch_local_irq_restore(unsigned long flags) unsigned long __tmp1; preempt_disable(); + __asm__ __volatile__( - "arch_local_irq_restore\t%0" - : "=r" (__tmp1) - : "0" (flags) - : "memory"); + " .set push \n" + " .set noreorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 $1, $2, 1 \n" + " andi %[flags], 0x400 \n" + " ori $1, 0x400 \n" + " xori $1, 0x400 \n" + " or %[flags], $1 \n" + " mtc0 %[flags], $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) + /* see irqflags.h for inline function */ +#elif defined(CONFIG_CPU_MIPSR2) + /* see irqflags.h for inline function */ +#else + " mfc0 $1, $12 \n" + " andi %[flags], 1 \n" + " ori $1, 0x1f \n" + " xori $1, 0x1f \n" + " or %[flags], $1 \n" + " mtc0 %[flags], $12 \n" +#endif + " " __stringify(__irq_disable_hazard) " \n" + " .set pop \n" + : [flags] "=r" (__tmp1) + : "0" (flags) + : "memory"); + preempt_enable(); } EXPORT_SYMBOL(__arch_local_irq_restore); diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S index fdbb970f670d..e362dcdc69d1 100644 --- a/arch/mips/lib/strlen_user.S +++ b/arch/mips/lib/strlen_user.S @@ -3,8 +3,9 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1996, 1998, 1999, 2004 by Ralf Baechle - * Copyright (c) 1999 Silicon Graphics, Inc. + * Copyright (C) 1996, 1998, 1999, 2004 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2011 MIPS Technologies, Inc. */ #include <asm/asm.h> #include <asm/asm-offsets.h> @@ -28,9 +29,9 @@ LEAF(__strlen_user_asm) FEXPORT(__strlen_user_nocheck_asm) move v0, a0 -1: EX(lb, t0, (v0), .Lfault) +1: EX(lbu, v1, (v0), .Lfault) PTR_ADDIU v0, 1 - bnez t0, 1b + bnez v1, 1b PTR_SUBU v0, a0 jr ra END(__strlen_user_asm) diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S index bad539487503..92870b6b53ea 100644 --- a/arch/mips/lib/strncpy_user.S +++ b/arch/mips/lib/strncpy_user.S @@ -3,7 +3,8 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1996, 1999 by Ralf Baechle + * Copyright (C) 1996, 1999 by Ralf Baechle + * Copyright (C) 2011 MIPS Technologies, Inc. */ #include <linux/errno.h> #include <asm/asm.h> @@ -33,26 +34,27 @@ LEAF(__strncpy_from_user_asm) bnez v0, .Lfault FEXPORT(__strncpy_from_user_nocheck_asm) - move v0, zero - move v1, a1 .set noreorder -1: EX(lbu, t0, (v1), .Lfault) + move t0, zero + move v1, a1 +1: EX(lbu, v0, (v1), .Lfault) PTR_ADDIU v1, 1 R10KCBARRIER(0(ra)) - beqz t0, 2f - sb t0, (a0) - PTR_ADDIU v0, 1 - .set reorder - PTR_ADDIU a0, 1 - bne v0, a2, 1b -2: PTR_ADDU t0, a1, v0 - xor t0, a1 - bltz t0, .Lfault + beqz v0, 2f + sb v0, (a0) + PTR_ADDIU t0, 1 + bne t0, a2, 1b + PTR_ADDIU a0, 1 +2: PTR_ADDU v0, a1, t0 + xor v0, a1 + bltz v0, .Lfault + nop jr ra # return n + move v0, t0 END(__strncpy_from_user_asm) -.Lfault: li v0, -EFAULT - jr ra +.Lfault: jr ra + li v0, -EFAULT .section __ex_table,"a" PTR 1b, .Lfault diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S index beea03c8c0ce..fcacea5e61f1 100644 --- a/arch/mips/lib/strnlen_user.S +++ b/arch/mips/lib/strnlen_user.S @@ -35,7 +35,7 @@ FEXPORT(__strnlen_user_nocheck_asm) PTR_ADDU a1, a0 # stop pointer 1: beq v0, a1, 1f # limit reached? EX(lb, t0, (v0), .Lfault) - PTR_ADDU v0, 1 + PTR_ADDIU v0, 1 bnez t0, 1b 1: PTR_SUBU v0, a0 jr ra diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile index e526488df655..4c57b3e5743f 100644 --- a/arch/mips/loongson/common/Makefile +++ b/arch/mips/loongson/common/Makefile @@ -4,7 +4,7 @@ obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \ pci.o bonito-irq.o mem.o machtype.o platform.o -obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_GPIOLIB) += gpio.o # # Serial port support diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index afb5a0bcf7a5..f03771900813 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -45,6 +45,7 @@ #include <asm/signal.h> #include <asm/mipsregs.h> #include <asm/fpu_emulator.h> +#include <asm/fpu.h> #include <asm/uaccess.h> #include <asm/branch.h> @@ -81,6 +82,11 @@ DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); /* Determine rounding mode from the RM bits of the FCSR */ #define modeindex(v) ((v) & FPU_CSR_RM) +/* microMIPS bitfields */ +#define MM_POOL32A_MINOR_MASK 0x3f +#define MM_POOL32A_MINOR_SHIFT 0x6 +#define MM_MIPS32_COND_FC 0x30 + /* Convert Mips rounding mode (0..3) to IEEE library modes. */ static const unsigned char ieee_rm[4] = { [FPU_CSR_RN] = IEEE754_RN, @@ -110,6 +116,556 @@ static const unsigned int fpucondbit[8] = { }; #endif +/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */ +static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7}; + +/* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */ +static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0}; +static const int sdps_format[] = {16, 17, 22, 0, 0, 0, 0, 0}; +static const int dwl_format[] = {17, 20, 21, 0, 0, 0, 0, 0}; +static const int swl_format[] = {16, 20, 21, 0, 0, 0, 0, 0}; + +/* + * This functions translates a 32-bit microMIPS instruction + * into a 32-bit MIPS32 instruction. Returns 0 on success + * and SIGILL otherwise. + */ +static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr) +{ + union mips_instruction insn = *insn_ptr; + union mips_instruction mips32_insn = insn; + int func, fmt, op; + + switch (insn.mm_i_format.opcode) { + case mm_ldc132_op: + mips32_insn.mm_i_format.opcode = ldc1_op; + mips32_insn.mm_i_format.rt = insn.mm_i_format.rs; + mips32_insn.mm_i_format.rs = insn.mm_i_format.rt; + break; + case mm_lwc132_op: + mips32_insn.mm_i_format.opcode = lwc1_op; + mips32_insn.mm_i_format.rt = insn.mm_i_format.rs; + mips32_insn.mm_i_format.rs = insn.mm_i_format.rt; + break; + case mm_sdc132_op: + mips32_insn.mm_i_format.opcode = sdc1_op; + mips32_insn.mm_i_format.rt = insn.mm_i_format.rs; + mips32_insn.mm_i_format.rs = insn.mm_i_format.rt; + break; + case mm_swc132_op: + mips32_insn.mm_i_format.opcode = swc1_op; + mips32_insn.mm_i_format.rt = insn.mm_i_format.rs; + mips32_insn.mm_i_format.rs = insn.mm_i_format.rt; + break; + case mm_pool32i_op: + /* NOTE: offset is << by 1 if in microMIPS mode. */ + if ((insn.mm_i_format.rt == mm_bc1f_op) || + (insn.mm_i_format.rt == mm_bc1t_op)) { + mips32_insn.fb_format.opcode = cop1_op; + mips32_insn.fb_format.bc = bc_op; + mips32_insn.fb_format.flag = + (insn.mm_i_format.rt == mm_bc1t_op) ? 1 : 0; + } else + return SIGILL; + break; + case mm_pool32f_op: + switch (insn.mm_fp0_format.func) { + case mm_32f_01_op: + case mm_32f_11_op: + case mm_32f_02_op: + case mm_32f_12_op: + case mm_32f_41_op: + case mm_32f_51_op: + case mm_32f_42_op: + case mm_32f_52_op: + op = insn.mm_fp0_format.func; + if (op == mm_32f_01_op) + func = madd_s_op; + else if (op == mm_32f_11_op) + func = madd_d_op; + else if (op == mm_32f_02_op) + func = nmadd_s_op; + else if (op == mm_32f_12_op) + func = nmadd_d_op; + else if (op == mm_32f_41_op) + func = msub_s_op; + else if (op == mm_32f_51_op) + func = msub_d_op; + else if (op == mm_32f_42_op) + func = nmsub_s_op; + else + func = nmsub_d_op; + mips32_insn.fp6_format.opcode = cop1x_op; + mips32_insn.fp6_format.fr = insn.mm_fp6_format.fr; + mips32_insn.fp6_format.ft = insn.mm_fp6_format.ft; + mips32_insn.fp6_format.fs = insn.mm_fp6_format.fs; + mips32_insn.fp6_format.fd = insn.mm_fp6_format.fd; + mips32_insn.fp6_format.func = func; + break; + case mm_32f_10_op: + func = -1; /* Invalid */ + op = insn.mm_fp5_format.op & 0x7; + if (op == mm_ldxc1_op) + func = ldxc1_op; + else if (op == mm_sdxc1_op) + func = sdxc1_op; + else if (op == mm_lwxc1_op) + func = lwxc1_op; + else if (op == mm_swxc1_op) + func = swxc1_op; + + if (func != -1) { + mips32_insn.r_format.opcode = cop1x_op; + mips32_insn.r_format.rs = + insn.mm_fp5_format.base; + mips32_insn.r_format.rt = + insn.mm_fp5_format.index; + mips32_insn.r_format.rd = 0; + mips32_insn.r_format.re = insn.mm_fp5_format.fd; + mips32_insn.r_format.func = func; + } else + return SIGILL; + break; + case mm_32f_40_op: + op = -1; /* Invalid */ + if (insn.mm_fp2_format.op == mm_fmovt_op) + op = 1; + else if (insn.mm_fp2_format.op == mm_fmovf_op) + op = 0; + if (op != -1) { + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = + sdps_format[insn.mm_fp2_format.fmt]; + mips32_insn.fp0_format.ft = + (insn.mm_fp2_format.cc<<2) + op; + mips32_insn.fp0_format.fs = + insn.mm_fp2_format.fs; + mips32_insn.fp0_format.fd = + insn.mm_fp2_format.fd; + mips32_insn.fp0_format.func = fmovc_op; + } else + return SIGILL; + break; + case mm_32f_60_op: + func = -1; /* Invalid */ + if (insn.mm_fp0_format.op == mm_fadd_op) + func = fadd_op; + else if (insn.mm_fp0_format.op == mm_fsub_op) + func = fsub_op; + else if (insn.mm_fp0_format.op == mm_fmul_op) + func = fmul_op; + else if (insn.mm_fp0_format.op == mm_fdiv_op) + func = fdiv_op; + if (func != -1) { + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = + sdps_format[insn.mm_fp0_format.fmt]; + mips32_insn.fp0_format.ft = + insn.mm_fp0_format.ft; + mips32_insn.fp0_format.fs = + insn.mm_fp0_format.fs; + mips32_insn.fp0_format.fd = + insn.mm_fp0_format.fd; + mips32_insn.fp0_format.func = func; + } else + return SIGILL; + break; + case mm_32f_70_op: + func = -1; /* Invalid */ + if (insn.mm_fp0_format.op == mm_fmovn_op) + func = fmovn_op; + else if (insn.mm_fp0_format.op == mm_fmovz_op) + func = fmovz_op; + if (func != -1) { + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = + sdps_format[insn.mm_fp0_format.fmt]; + mips32_insn.fp0_format.ft = + insn.mm_fp0_format.ft; + mips32_insn.fp0_format.fs = + insn.mm_fp0_format.fs; + mips32_insn.fp0_format.fd = + insn.mm_fp0_format.fd; + mips32_insn.fp0_format.func = func; + } else + return SIGILL; + break; + case mm_32f_73_op: /* POOL32FXF */ + switch (insn.mm_fp1_format.op) { + case mm_movf0_op: + case mm_movf1_op: + case mm_movt0_op: + case mm_movt1_op: + if ((insn.mm_fp1_format.op & 0x7f) == + mm_movf0_op) + op = 0; + else + op = 1; + mips32_insn.r_format.opcode = spec_op; + mips32_insn.r_format.rs = insn.mm_fp4_format.fs; + mips32_insn.r_format.rt = + (insn.mm_fp4_format.cc << 2) + op; + mips32_insn.r_format.rd = insn.mm_fp4_format.rt; + mips32_insn.r_format.re = 0; + mips32_insn.r_format.func = movc_op; + break; + case mm_fcvtd0_op: + case mm_fcvtd1_op: + case mm_fcvts0_op: + case mm_fcvts1_op: + if ((insn.mm_fp1_format.op & 0x7f) == + mm_fcvtd0_op) { + func = fcvtd_op; + fmt = swl_format[insn.mm_fp3_format.fmt]; + } else { + func = fcvts_op; + fmt = dwl_format[insn.mm_fp3_format.fmt]; + } + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = fmt; + mips32_insn.fp0_format.ft = 0; + mips32_insn.fp0_format.fs = + insn.mm_fp3_format.fs; + mips32_insn.fp0_format.fd = + insn.mm_fp3_format.rt; + mips32_insn.fp0_format.func = func; + break; + case mm_fmov0_op: + case mm_fmov1_op: + case mm_fabs0_op: + case mm_fabs1_op: + case mm_fneg0_op: + case mm_fneg1_op: + if ((insn.mm_fp1_format.op & 0x7f) == + mm_fmov0_op) + func = fmov_op; + else if ((insn.mm_fp1_format.op & 0x7f) == + mm_fabs0_op) + func = fabs_op; + else + func = fneg_op; + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = + sdps_format[insn.mm_fp3_format.fmt]; + mips32_insn.fp0_format.ft = 0; + mips32_insn.fp0_format.fs = + insn.mm_fp3_format.fs; + mips32_insn.fp0_format.fd = + insn.mm_fp3_format.rt; + mips32_insn.fp0_format.func = func; + break; + case mm_ffloorl_op: + case mm_ffloorw_op: + case mm_fceill_op: + case mm_fceilw_op: + case mm_ftruncl_op: + case mm_ftruncw_op: + case mm_froundl_op: + case mm_froundw_op: + case mm_fcvtl_op: + case mm_fcvtw_op: + if (insn.mm_fp1_format.op == mm_ffloorl_op) + func = ffloorl_op; + else if (insn.mm_fp1_format.op == mm_ffloorw_op) + func = ffloor_op; + else if (insn.mm_fp1_format.op == mm_fceill_op) + func = fceill_op; + else if (insn.mm_fp1_format.op == mm_fceilw_op) + func = fceil_op; + else if (insn.mm_fp1_format.op == mm_ftruncl_op) + func = ftruncl_op; + else if (insn.mm_fp1_format.op == mm_ftruncw_op) + func = ftrunc_op; + else if (insn.mm_fp1_format.op == mm_froundl_op) + func = froundl_op; + else if (insn.mm_fp1_format.op == mm_froundw_op) + func = fround_op; + else if (insn.mm_fp1_format.op == mm_fcvtl_op) + func = fcvtl_op; + else + func = fcvtw_op; + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = + sd_format[insn.mm_fp1_format.fmt]; + mips32_insn.fp0_format.ft = 0; + mips32_insn.fp0_format.fs = + insn.mm_fp1_format.fs; + mips32_insn.fp0_format.fd = + insn.mm_fp1_format.rt; + mips32_insn.fp0_format.func = func; + break; + case mm_frsqrt_op: + case mm_fsqrt_op: + case mm_frecip_op: + if (insn.mm_fp1_format.op == mm_frsqrt_op) + func = frsqrt_op; + else if (insn.mm_fp1_format.op == mm_fsqrt_op) + func = fsqrt_op; + else + func = frecip_op; + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = + sdps_format[insn.mm_fp1_format.fmt]; + mips32_insn.fp0_format.ft = 0; + mips32_insn.fp0_format.fs = + insn.mm_fp1_format.fs; + mips32_insn.fp0_format.fd = + insn.mm_fp1_format.rt; + mips32_insn.fp0_format.func = func; + break; + case mm_mfc1_op: + case mm_mtc1_op: + case mm_cfc1_op: + case mm_ctc1_op: + if (insn.mm_fp1_format.op == mm_mfc1_op) + op = mfc_op; + else if (insn.mm_fp1_format.op == mm_mtc1_op) + op = mtc_op; + else if (insn.mm_fp1_format.op == mm_cfc1_op) + op = cfc_op; + else + op = ctc_op; + mips32_insn.fp1_format.opcode = cop1_op; + mips32_insn.fp1_format.op = op; + mips32_insn.fp1_format.rt = + insn.mm_fp1_format.rt; + mips32_insn.fp1_format.fs = + insn.mm_fp1_format.fs; + mips32_insn.fp1_format.fd = 0; + mips32_insn.fp1_format.func = 0; + break; + default: + return SIGILL; + break; + } + break; + case mm_32f_74_op: /* c.cond.fmt */ + mips32_insn.fp0_format.opcode = cop1_op; + mips32_insn.fp0_format.fmt = + sdps_format[insn.mm_fp4_format.fmt]; + mips32_insn.fp0_format.ft = insn.mm_fp4_format.rt; + mips32_insn.fp0_format.fs = insn.mm_fp4_format.fs; + mips32_insn.fp0_format.fd = insn.mm_fp4_format.cc << 2; + mips32_insn.fp0_format.func = + insn.mm_fp4_format.cond | MM_MIPS32_COND_FC; + break; + default: + return SIGILL; + break; + } + break; + default: + return SIGILL; + break; + } + + *insn_ptr = mips32_insn; + return 0; +} + +int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, + unsigned long *contpc) +{ + union mips_instruction insn = (union mips_instruction)dec_insn.insn; + int bc_false = 0; + unsigned int fcr31; + unsigned int bit; + + switch (insn.mm_i_format.opcode) { + case mm_pool32a_op: + if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) == + mm_pool32axf_op) { + switch (insn.mm_i_format.simmediate >> + MM_POOL32A_MINOR_SHIFT) { + case mm_jalr_op: + case mm_jalrhb_op: + case mm_jalrs_op: + case mm_jalrshb_op: + if (insn.mm_i_format.rt != 0) /* Not mm_jr */ + regs->regs[insn.mm_i_format.rt] = + regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + *contpc = regs->regs[insn.mm_i_format.rs]; + return 1; + break; + } + } + break; + case mm_pool32i_op: + switch (insn.mm_i_format.rt) { + case mm_bltzals_op: + case mm_bltzal_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ + case mm_bltz_op: + if ((long)regs->regs[insn.mm_i_format.rs] < 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case mm_bgezals_op: + case mm_bgezal_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ + case mm_bgez_op: + if ((long)regs->regs[insn.mm_i_format.rs] >= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case mm_blez_op: + if ((long)regs->regs[insn.mm_i_format.rs] <= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case mm_bgtz_op: + if ((long)regs->regs[insn.mm_i_format.rs] <= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case mm_bc2f_op: + case mm_bc1f_op: + bc_false = 1; + /* Fall through */ + case mm_bc2t_op: + case mm_bc1t_op: + preempt_disable(); + if (is_fpu_owner()) + asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); + else + fcr31 = current->thread.fpu.fcr31; + preempt_enable(); + + if (bc_false) + fcr31 = ~fcr31; + + bit = (insn.mm_i_format.rs >> 2); + bit += (bit != 0); + bit += 23; + if (fcr31 & (1 << bit)) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + break; + } + break; + case mm_pool16c_op: + switch (insn.mm_i_format.rt) { + case mm_jalr16_op: + case mm_jalrs16_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + /* Fall through */ + case mm_jr16_op: + *contpc = regs->regs[insn.mm_i_format.rs]; + return 1; + break; + } + break; + case mm_beqz16_op: + if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_b1_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + break; + case mm_bnez16_op: + if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_b1_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + break; + case mm_b16_op: + *contpc = regs->cp0_epc + dec_insn.pc_inc + + (insn.mm_b0_format.simmediate << 1); + return 1; + break; + case mm_beq32_op: + if (regs->regs[insn.mm_i_format.rs] == + regs->regs[insn.mm_i_format.rt]) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case mm_bne32_op: + if (regs->regs[insn.mm_i_format.rs] != + regs->regs[insn.mm_i_format.rt]) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + break; + case mm_jalx32_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + *contpc = regs->cp0_epc + dec_insn.pc_inc; + *contpc >>= 28; + *contpc <<= 28; + *contpc |= (insn.j_format.target << 2); + return 1; + break; + case mm_jals32_op: + case mm_jal32_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + /* Fall through */ + case mm_j32_op: + *contpc = regs->cp0_epc + dec_insn.pc_inc; + *contpc >>= 27; + *contpc <<= 27; + *contpc |= (insn.j_format.target << 1); + set_isa16_mode(*contpc); + return 1; + break; + } + return 0; +} /* * Redundant with logic already in kernel/branch.c, @@ -117,53 +673,177 @@ static const unsigned int fpucondbit[8] = { * a single subroutine should be used across both * modules. */ -static int isBranchInstr(mips_instruction * i) +static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, + unsigned long *contpc) { - switch (MIPSInst_OPCODE(*i)) { + union mips_instruction insn = (union mips_instruction)dec_insn.insn; + unsigned int fcr31; + unsigned int bit = 0; + + switch (insn.i_format.opcode) { case spec_op: - switch (MIPSInst_FUNC(*i)) { + switch (insn.r_format.func) { case jalr_op: + regs->regs[insn.r_format.rd] = + regs->cp0_epc + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ case jr_op: + *contpc = regs->regs[insn.r_format.rs]; return 1; + break; } break; - case bcond_op: - switch (MIPSInst_RT(*i)) { + switch (insn.i_format.rt) { + case bltzal_op: + case bltzall_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ case bltz_op: - case bgez_op: case bltzl_op: - case bgezl_op: - case bltzal_op: + if ((long)regs->regs[insn.i_format.rs] < 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; case bgezal_op: - case bltzall_op: case bgezall_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ + case bgez_op: + case bgezl_op: + if ((long)regs->regs[insn.i_format.rs] >= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; return 1; + break; } break; - - case j_op: - case jal_op: case jalx_op: + set_isa16_mode(bit); + case jal_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ + case j_op: + *contpc = regs->cp0_epc + dec_insn.pc_inc; + *contpc >>= 28; + *contpc <<= 28; + *contpc |= (insn.j_format.target << 2); + /* Set microMIPS mode bit: XOR for jalx. */ + *contpc ^= bit; + return 1; + break; case beq_op: - case bne_op: - case blez_op: - case bgtz_op: case beql_op: + if (regs->regs[insn.i_format.rs] == + regs->regs[insn.i_format.rt]) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case bne_op: case bnel_op: + if (regs->regs[insn.i_format.rs] != + regs->regs[insn.i_format.rt]) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case blez_op: case blezl_op: + if ((long)regs->regs[insn.i_format.rs] <= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case bgtz_op: case bgtzl_op: + if ((long)regs->regs[insn.i_format.rs] > 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; return 1; - + break; case cop0_op: case cop1_op: case cop2_op: case cop1x_op: - if (MIPSInst_RS(*i) == bc_op) - return 1; + if (insn.i_format.rs == bc_op) { + preempt_disable(); + if (is_fpu_owner()) + asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); + else + fcr31 = current->thread.fpu.fcr31; + preempt_enable(); + + bit = (insn.i_format.rt >> 2); + bit += (bit != 0); + bit += 23; + switch (insn.i_format.rt & 3) { + case 0: /* bc1f */ + case 2: /* bc1fl */ + if (~fcr31 & (1 << bit)) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + case 1: /* bc1t */ + case 3: /* bc1tl */ + if (fcr31 & (1 << bit)) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.i_format.simmediate << 2); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + break; + } + } break; } - return 0; } @@ -210,26 +890,23 @@ static inline int cop1_64bit(struct pt_regs *xcp) */ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, - void *__user *fault_addr) + struct mm_decoded_insn dec_insn, void *__user *fault_addr) { mips_instruction ir; - unsigned long emulpc, contpc; + unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc; unsigned int cond; - - if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)xcp->cp0_epc; - return SIGBUS; - } - if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)xcp->cp0_epc; - return SIGSEGV; - } + int pc_inc; /* XXX NEC Vr54xx bug workaround */ - if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) - xcp->cp0_cause &= ~CAUSEF_BD; + if (xcp->cp0_cause & CAUSEF_BD) { + if (dec_insn.micro_mips_mode) { + if (!mm_isBranchInstr(xcp, dec_insn, &contpc)) + xcp->cp0_cause &= ~CAUSEF_BD; + } else { + if (!isBranchInstr(xcp, dec_insn, &contpc)) + xcp->cp0_cause &= ~CAUSEF_BD; + } + } if (xcp->cp0_cause & CAUSEF_BD) { /* @@ -244,32 +921,33 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * Linux MIPS branch emulator operates on context, updating the * cp0_epc. */ - emulpc = xcp->cp0_epc + 4; /* Snapshot emulation target */ + ir = dec_insn.next_insn; /* process delay slot instr */ + pc_inc = dec_insn.next_pc_inc; + } else { + ir = dec_insn.insn; /* process current instr */ + pc_inc = dec_insn.pc_inc; + } - if (__compute_return_epc(xcp) < 0) { -#ifdef CP1DBG - printk("failed to emulate branch at %p\n", - (void *) (xcp->cp0_epc)); -#endif + /* + * Since microMIPS FPU instructios are a subset of MIPS32 FPU + * instructions, we want to convert microMIPS FPU instructions + * into MIPS32 instructions so that we could reuse all of the + * FPU emulation code. + * + * NOTE: We cannot do this for branch instructions since they + * are not a subset. Example: Cannot emulate a 16-bit + * aligned target address with a MIPS32 instruction. + */ + if (dec_insn.micro_mips_mode) { + /* + * If next instruction is a 16-bit instruction, then it + * it cannot be a FPU instruction. This could happen + * since we can be called for non-FPU instructions. + */ + if ((pc_inc == 2) || + (microMIPS32_to_MIPS32((union mips_instruction *)&ir) + == SIGILL)) return SIGILL; - } - if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)emulpc; - return SIGBUS; - } - if (__get_user(ir, (mips_instruction __user *) emulpc)) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)emulpc; - return SIGSEGV; - } - /* __compute_return_epc() will have updated cp0_epc */ - contpc = xcp->cp0_epc; - /* In order not to confuse ptrace() et al, tweak context */ - xcp->cp0_epc = emulpc - 4; - } else { - emulpc = xcp->cp0_epc; - contpc = xcp->cp0_epc + 4; } emul: @@ -474,22 +1152,35 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* branch taken: emulate dslot * instruction */ - xcp->cp0_epc += 4; - contpc = (xcp->cp0_epc + - (MIPSInst_SIMM(ir) << 2)); - - if (!access_ok(VERIFY_READ, xcp->cp0_epc, - sizeof(mips_instruction))) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)xcp->cp0_epc; - return SIGBUS; - } - if (__get_user(ir, - (mips_instruction __user *) xcp->cp0_epc)) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)xcp->cp0_epc; - return SIGSEGV; - } + xcp->cp0_epc += dec_insn.pc_inc; + + contpc = MIPSInst_SIMM(ir); + ir = dec_insn.next_insn; + if (dec_insn.micro_mips_mode) { + contpc = (xcp->cp0_epc + (contpc << 1)); + + /* If 16-bit instruction, not FPU. */ + if ((dec_insn.next_pc_inc == 2) || + (microMIPS32_to_MIPS32((union mips_instruction *)&ir) == SIGILL)) { + + /* + * Since this instruction will + * be put on the stack with + * 32-bit words, get around + * this problem by putting a + * NOP16 as the second one. + */ + if (dec_insn.next_pc_inc == 2) + ir = (ir & (~0xffff)) | MM_NOP16; + + /* + * Single step the non-CP1 + * instruction in the dslot. + */ + return mips_dsemul(xcp, ir, contpc); + } + } else + contpc = (xcp->cp0_epc + (contpc << 2)); switch (MIPSInst_OPCODE(ir)) { case lwc1_op: @@ -525,8 +1216,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * branch likely nullifies * dslot if not taken */ - xcp->cp0_epc += 4; - contpc += 4; + xcp->cp0_epc += dec_insn.pc_inc; + contpc += dec_insn.pc_inc; /* * else continue & execute * dslot as normal insn @@ -1313,25 +2004,75 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int has_fpu, void *__user *fault_addr) { unsigned long oldepc, prevepc; - mips_instruction insn; + struct mm_decoded_insn dec_insn; + u16 instr[4]; + u16 *instr_ptr; int sig = 0; oldepc = xcp->cp0_epc; do { prevepc = xcp->cp0_epc; - if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)xcp->cp0_epc; - return SIGBUS; - } - if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) { - MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = (mips_instruction __user *)xcp->cp0_epc; - return SIGSEGV; + if (get_isa16_mode(prevepc) && cpu_has_mmips) { + /* + * Get next 2 microMIPS instructions and convert them + * into 32-bit instructions. + */ + if ((get_user(instr[0], (u16 __user *)msk_isa16_mode(xcp->cp0_epc))) || + (get_user(instr[1], (u16 __user *)msk_isa16_mode(xcp->cp0_epc + 2))) || + (get_user(instr[2], (u16 __user *)msk_isa16_mode(xcp->cp0_epc + 4))) || + (get_user(instr[3], (u16 __user *)msk_isa16_mode(xcp->cp0_epc + 6)))) { + MIPS_FPU_EMU_INC_STATS(errors); + return SIGBUS; + } + instr_ptr = instr; + + /* Get first instruction. */ + if (mm_insn_16bit(*instr_ptr)) { + /* Duplicate the half-word. */ + dec_insn.insn = (*instr_ptr << 16) | + (*instr_ptr); + /* 16-bit instruction. */ + dec_insn.pc_inc = 2; + instr_ptr += 1; + } else { + dec_insn.insn = (*instr_ptr << 16) | + *(instr_ptr+1); + /* 32-bit instruction. */ + dec_insn.pc_inc = 4; + instr_ptr += 2; + } + /* Get second instruction. */ + if (mm_insn_16bit(*instr_ptr)) { + /* Duplicate the half-word. */ + dec_insn.next_insn = (*instr_ptr << 16) | + (*instr_ptr); + /* 16-bit instruction. */ + dec_insn.next_pc_inc = 2; + } else { + dec_insn.next_insn = (*instr_ptr << 16) | + *(instr_ptr+1); + /* 32-bit instruction. */ + dec_insn.next_pc_inc = 4; + } + dec_insn.micro_mips_mode = 1; + } else { + if ((get_user(dec_insn.insn, + (mips_instruction __user *) xcp->cp0_epc)) || + (get_user(dec_insn.next_insn, + (mips_instruction __user *)(xcp->cp0_epc+4)))) { + MIPS_FPU_EMU_INC_STATS(errors); + return SIGBUS; + } + dec_insn.pc_inc = 4; + dec_insn.next_pc_inc = 4; + dec_insn.micro_mips_mode = 0; } - if (insn == 0) - xcp->cp0_epc += 4; /* skip nops */ + + if ((dec_insn.insn == 0) || + ((dec_insn.pc_inc == 2) && + ((dec_insn.insn & 0xffff) == MM_NOP16))) + xcp->cp0_epc += dec_insn.pc_inc; /* Skip NOPs */ else { /* * The 'ieee754_csr' is an alias of @@ -1341,7 +2082,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, */ /* convert to ieee library modes */ ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; - sig = cop1Emulate(xcp, ctx, fault_addr); + sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr); /* revert to mips rounding mode */ ieee754_csr.rm = mips_rm[ieee754_csr.rm]; } diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 384a3b0091ea..7ea622ab8dad 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -55,7 +55,9 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) struct emuframe __user *fr; int err; - if (ir == 0) { /* a nop is easy */ + if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) || + (ir == 0)) { + /* NOP is easy */ regs->cp0_epc = cpc; regs->cp0_cause &= ~CAUSEF_BD; return 0; @@ -91,8 +93,16 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe)))) return SIGBUS; - err = __put_user(ir, &fr->emul); - err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst); + if (get_isa16_mode(regs->cp0_epc)) { + err = __put_user(ir >> 16, (u16 __user *)(&fr->emul)); + err |= __put_user(ir & 0xffff, (u16 __user *)((long)(&fr->emul) + 2)); + err |= __put_user(BREAK_MATH >> 16, (u16 __user *)(&fr->badinst)); + err |= __put_user(BREAK_MATH & 0xffff, (u16 __user *)((long)(&fr->badinst) + 2)); + } else { + err = __put_user(ir, &fr->emul); + err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst); + } + err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie); err |= __put_user(cpc, &fr->epc); @@ -101,7 +111,8 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) return SIGBUS; } - regs->cp0_epc = (unsigned long) &fr->emul; + regs->cp0_epc = ((unsigned long) &fr->emul) | + get_isa16_mode(regs->cp0_epc); flush_cache_sigtramp((unsigned long)&fr->badinst); @@ -114,9 +125,10 @@ int do_dsemulret(struct pt_regs *xcp) unsigned long epc; u32 insn, cookie; int err = 0; + u16 instr[2]; fr = (struct emuframe __user *) - (xcp->cp0_epc - sizeof(mips_instruction)); + (msk_isa16_mode(xcp->cp0_epc) - sizeof(mips_instruction)); /* * If we can't even access the area, something is very wrong, but we'll @@ -131,7 +143,13 @@ int do_dsemulret(struct pt_regs *xcp) * - Is the instruction pointed to by the EPC an BREAK_MATH? * - Is the following memory word the BD_COOKIE? */ - err = __get_user(insn, &fr->badinst); + if (get_isa16_mode(xcp->cp0_epc)) { + err = __get_user(instr[0], (u16 __user *)(&fr->badinst)); + err |= __get_user(instr[1], (u16 __user *)((long)(&fr->badinst) + 2)); + insn = (instr[0] << 16) | instr[1]; + } else { + err = __get_user(insn, &fr->badinst); + } err |= __get_user(cookie, &fr->cookie); if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) { diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index 1dcec30ad1c4..e87aae1f2e80 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile @@ -4,7 +4,7 @@ obj-y += cache.o dma-default.o extable.o fault.o \ gup.o init.o mmap.o page.o page-funcs.o \ - tlbex.o tlbex-fault.o uasm.o + tlbex.o tlbex-fault.o uasm-mips.o obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o obj-$(CONFIG_64BIT) += pgtable-64.o @@ -22,3 +22,5 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o + +obj-$(CONFIG_SYS_SUPPORTS_MICROMIPS) += uasm-micromips.o diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 2078915eacb9..21813beec7a5 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -33,6 +33,7 @@ #include <asm/war.h> #include <asm/cacheflush.h> /* for run_uncached() */ #include <asm/traps.h> +#include <asm/dma-coherence.h> /* * Special Variant of smp_call_function for use by cache functions: @@ -136,7 +137,8 @@ static void __cpuinit r4k_blast_dcache_page_indexed_setup(void) r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed; } -static void (* r4k_blast_dcache)(void); +void (* r4k_blast_dcache)(void); +EXPORT_SYMBOL(r4k_blast_dcache); static void __cpuinit r4k_blast_dcache_setup(void) { @@ -264,7 +266,8 @@ static void __cpuinit r4k_blast_icache_page_indexed_setup(void) r4k_blast_icache_page_indexed = blast_icache64_page_indexed; } -static void (* r4k_blast_icache)(void); +void (* r4k_blast_icache)(void); +EXPORT_SYMBOL(r4k_blast_icache); static void __cpuinit r4k_blast_icache_setup(void) { @@ -1377,20 +1380,6 @@ static void __cpuinit coherency_setup(void) } } -#if defined(CONFIG_DMA_NONCOHERENT) - -static int __cpuinitdata coherentio; - -static int __init setcoherentio(char *str) -{ - coherentio = 1; - - return 0; -} - -early_param("coherentio", setcoherentio); -#endif - static void __cpuinit r4k_cache_error_setup(void) { extern char __weak except_vec2_generic; @@ -1472,9 +1461,14 @@ void __cpuinit r4k_cache_init(void) build_clear_page(); build_copy_page(); -#if !defined(CONFIG_MIPS_CMP) + + /* + * We want to run CMP kernels on core with and without coherent + * caches. Therefore, do not use CONFIG_MIPS_CMP to decide whether + * or not to flush caches. + */ local_r4k___flush_cache_all(NULL); -#endif + coherency_setup(); board_cache_error_setup = r4k_cache_error_setup; } diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 07cec4407b0c..5aeb3eb0b72f 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -48,6 +48,7 @@ void (*flush_icache_all)(void); EXPORT_SYMBOL_GPL(local_flush_data_cache_page); EXPORT_SYMBOL(flush_data_cache_page); +EXPORT_SYMBOL(flush_icache_all); #ifdef CONFIG_DMA_NONCOHERENT diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index f9ef83829a52..caf92ecb37d6 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -22,6 +22,26 @@ #include <dma-coherence.h> +int coherentio = 0; /* User defined DMA coherency from command line. */ +EXPORT_SYMBOL_GPL(coherentio); +int hw_coherentio = 0; /* Actual hardware supported DMA coherency setting. */ + +static int __init setcoherentio(char *str) +{ + coherentio = 1; + pr_info("Hardware DMA cache coherency (command line)\n"); + return 0; +} +early_param("coherentio", setcoherentio); + +static int __init setnocoherentio(char *str) +{ + coherentio = 0; + pr_info("Software DMA cache coherency (command line)\n"); + return 0; +} +early_param("nocoherentio", setnocoherentio); + static inline struct page *dma_addr_to_page(struct device *dev, dma_addr_t dma_addr) { @@ -115,7 +135,8 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size, if (!plat_device_is_coherent(dev)) { dma_cache_wback_inv((unsigned long) ret, size); - ret = UNCAC_ADDR(ret); + if (!hw_coherentio) + ret = UNCAC_ADDR(ret); } } @@ -142,7 +163,7 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr, plat_unmap_dma_mem(dev, dma_handle, size, DMA_BIDIRECTIONAL); - if (!plat_device_is_coherent(dev)) + if (!plat_device_is_coherent(dev) && !hw_coherentio) addr = CAC_ADDR(addr); free_pages(addr, get_order(size)); diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index a29fba55b53e..4eb8dcfaf1ce 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -247,6 +247,11 @@ void __cpuinit build_clear_page(void) struct uasm_label *l = labels; struct uasm_reloc *r = relocs; int i; + static atomic_t run_once = ATOMIC_INIT(0); + + if (atomic_xchg(&run_once, 1)) { + return; + } memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -389,6 +394,11 @@ void __cpuinit build_copy_page(void) struct uasm_label *l = labels; struct uasm_reloc *r = relocs; int i; + static atomic_t run_once = ATOMIC_INIT(0); + + if (atomic_xchg(&run_once, 1)) { + return; + } memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 493131c81a29..c643de4c473a 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -13,6 +13,7 @@ #include <linux/smp.h> #include <linux/mm.h> #include <linux/hugetlb.h> +#include <linux/module.h> #include <asm/cpu.h> #include <asm/bootinfo.h> @@ -94,6 +95,7 @@ void local_flush_tlb_all(void) FLUSH_ITLB; EXIT_CRITICAL(flags); } +EXPORT_SYMBOL(local_flush_tlb_all); /* All entries common to a mm share an asid. To effectively flush these entries, we just bump the asid. */ diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 820e6612d744..ce9818eef7d3 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1458,17 +1458,17 @@ u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned; u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned; u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; #ifdef CONFIG_MIPS_PGD_C0_CONTEXT -u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned; +u32 tlbmiss_handler_setup_pgd_array[16] __cacheline_aligned; static void __cpuinit build_r4000_setup_pgd(void) { const int a0 = 4; const int a1 = 5; - u32 *p = tlbmiss_handler_setup_pgd; + u32 *p = tlbmiss_handler_setup_pgd_array; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; - memset(tlbmiss_handler_setup_pgd, 0, sizeof(tlbmiss_handler_setup_pgd)); + memset(tlbmiss_handler_setup_pgd_array, 0, sizeof(tlbmiss_handler_setup_pgd_array)); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -1496,15 +1496,15 @@ static void __cpuinit build_r4000_setup_pgd(void) uasm_i_jr(&p, 31); UASM_i_MTC0(&p, a0, 31, pgd_reg); } - if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd)) - panic("tlbmiss_handler_setup_pgd space exceeded"); + if (p - tlbmiss_handler_setup_pgd_array > ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)) + panic("tlbmiss_handler_setup_pgd_array space exceeded"); uasm_resolve_relocs(relocs, labels); - pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", - (unsigned int)(p - tlbmiss_handler_setup_pgd)); + pr_debug("Wrote tlbmiss_handler_setup_pgd_array (%u instructions).\n", + (unsigned int)(p - tlbmiss_handler_setup_pgd_array)); dump_handler("tlbmiss_handler", - tlbmiss_handler_setup_pgd, - ARRAY_SIZE(tlbmiss_handler_setup_pgd)); + tlbmiss_handler_setup_pgd_array, + ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)); } #endif @@ -2030,6 +2030,13 @@ static void __cpuinit build_r4000_tlb_load_handler(void) uasm_l_nopage_tlbl(&l, p); build_restore_work_registers(&p); +#ifdef CONFIG_CPU_MICROMIPS + if ((unsigned long)tlb_do_page_fault_0 & 1) { + uasm_i_lui(&p, K0, uasm_rel_hi((long)tlb_do_page_fault_0)); + uasm_i_addiu(&p, K0, K0, uasm_rel_lo((long)tlb_do_page_fault_0)); + uasm_i_jr(&p, K0); + } else +#endif uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); uasm_i_nop(&p); @@ -2077,6 +2084,13 @@ static void __cpuinit build_r4000_tlb_store_handler(void) uasm_l_nopage_tlbs(&l, p); build_restore_work_registers(&p); +#ifdef CONFIG_CPU_MICROMIPS + if ((unsigned long)tlb_do_page_fault_1 & 1) { + uasm_i_lui(&p, K0, uasm_rel_hi((long)tlb_do_page_fault_1)); + uasm_i_addiu(&p, K0, K0, uasm_rel_lo((long)tlb_do_page_fault_1)); + uasm_i_jr(&p, K0); + } else +#endif uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); @@ -2125,6 +2139,13 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) uasm_l_nopage_tlbm(&l, p); build_restore_work_registers(&p); +#ifdef CONFIG_CPU_MICROMIPS + if ((unsigned long)tlb_do_page_fault_1 & 1) { + uasm_i_lui(&p, K0, uasm_rel_hi((long)tlb_do_page_fault_1)); + uasm_i_addiu(&p, K0, K0, uasm_rel_lo((long)tlb_do_page_fault_1)); + uasm_i_jr(&p, K0); + } else +#endif uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); @@ -2162,8 +2183,11 @@ void __cpuinit build_tlb_refill_handler(void) case CPU_TX3922: case CPU_TX3927: #ifndef CONFIG_MIPS_PGD_C0_CONTEXT - build_r3000_tlb_refill_handler(); + if (cpu_has_local_ebase) + build_r3000_tlb_refill_handler(); if (!run_once) { + if (!cpu_has_local_ebase) + build_r3000_tlb_refill_handler(); build_r3000_tlb_load_handler(); build_r3000_tlb_store_handler(); build_r3000_tlb_modify_handler(); @@ -2192,9 +2216,12 @@ void __cpuinit build_tlb_refill_handler(void) build_r4000_tlb_load_handler(); build_r4000_tlb_store_handler(); build_r4000_tlb_modify_handler(); + if (!cpu_has_local_ebase) + build_r4000_tlb_refill_handler(); run_once++; } - build_r4000_tlb_refill_handler(); + if (cpu_has_local_ebase) + build_r4000_tlb_refill_handler(); } } @@ -2207,7 +2234,7 @@ void __cpuinit flush_tlb_handlers(void) local_flush_icache_range((unsigned long)handle_tlbm, (unsigned long)handle_tlbm + sizeof(handle_tlbm)); #ifdef CONFIG_MIPS_PGD_C0_CONTEXT - local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd, - (unsigned long)tlbmiss_handler_setup_pgd + sizeof(handle_tlbm)); + local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, + (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); #endif } diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c new file mode 100644 index 000000000000..162ee6d62788 --- /dev/null +++ b/arch/mips/mm/uasm-micromips.c @@ -0,0 +1,221 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * A small micro-assembler. It is intentionally kept simple, does only + * support a subset of instructions, and does not try to hide pipeline + * effects like branch delay slots. + * + * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer + * Copyright (C) 2005, 2007 Maciej W. Rozycki + * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> + +#include <asm/inst.h> +#include <asm/elf.h> +#include <asm/bugs.h> +#define UASM_ISA _UASM_ISA_MICROMIPS +#include <asm/uasm.h> + +#define RS_MASK 0x1f +#define RS_SH 16 +#define RT_MASK 0x1f +#define RT_SH 21 +#define SCIMM_MASK 0x3ff +#define SCIMM_SH 16 + +/* This macro sets the non-variable bits of an instruction. */ +#define M(a, b, c, d, e, f) \ + ((a) << OP_SH \ + | (b) << RT_SH \ + | (c) << RS_SH \ + | (d) << RD_SH \ + | (e) << RE_SH \ + | (f) << FUNC_SH) + +/* Define these when we are not the ISA the kernel is being compiled with. */ +#ifndef CONFIG_CPU_MICROMIPS +#define MM_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off) +#define MM_uasm_i_beqz(buf, rs, off) ISAOPC(_beq)(buf, rs, 0, off) +#define MM_uasm_i_beqzl(buf, rs, off) ISAOPC(_beql)(buf, rs, 0, off) +#define MM_uasm_i_bnez(buf, rs, off) ISAOPC(_bne)(buf, rs, 0, off) +#endif + +#include "uasm.c" + +static struct insn insn_table_MM[] __uasminitdata = { + { insn_addu, M(mm_pool32a_op, 0, 0, 0, 0, mm_addu32_op), RT | RS | RD }, + { insn_addiu, M(mm_addiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, + { insn_and, M(mm_pool32a_op, 0, 0, 0, 0, mm_and_op), RT | RS | RD }, + { insn_andi, M(mm_andi32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, + { insn_beq, M(mm_beq32_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_beql, 0, 0 }, + { insn_bgez, M(mm_pool32i_op, mm_bgez_op, 0, 0, 0, 0), RS | BIMM }, + { insn_bgezl, 0, 0 }, + { insn_bltz, M(mm_pool32i_op, mm_bltz_op, 0, 0, 0, 0), RS | BIMM }, + { insn_bltzl, 0, 0 }, + { insn_bne, M(mm_bne32_op, 0, 0, 0, 0, 0), RT | RS | BIMM }, + { insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM }, + { insn_daddu, 0, 0 }, + { insn_daddiu, 0, 0 }, + { insn_dmfc0, 0, 0 }, + { insn_dmtc0, 0, 0 }, + { insn_dsll, 0, 0 }, + { insn_dsll32, 0, 0 }, + { insn_dsra, 0, 0 }, + { insn_dsrl, 0, 0 }, + { insn_dsrl32, 0, 0 }, + { insn_drotr, 0, 0 }, + { insn_drotr32, 0, 0 }, + { insn_dsubu, 0, 0 }, + { insn_eret, M(mm_pool32a_op, 0, 0, 0, mm_eret_op, mm_pool32axf_op), 0 }, + { insn_ins, M(mm_pool32a_op, 0, 0, 0, 0, mm_ins_op), RT | RS | RD | RE }, + { insn_ext, M(mm_pool32a_op, 0, 0, 0, 0, mm_ext_op), RT | RS | RD | RE }, + { insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM }, + { insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM }, + { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS }, + { insn_ld, 0, 0 }, + { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM }, + { insn_lld, 0, 0 }, + { insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM }, + { insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, + { insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD }, + { insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD }, + { insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD }, + { insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, + { insn_pref, M(mm_pool32c_op, 0, 0, (mm_pref_func << 1), 0, 0), RT | RS | SIMM }, + { insn_rfe, 0, 0 }, + { insn_sc, M(mm_pool32c_op, 0, 0, (mm_sc_func << 1), 0, 0), RT | RS | SIMM }, + { insn_scd, 0, 0 }, + { insn_sd, 0, 0 }, + { insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD }, + { insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD }, + { insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD }, + { insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD }, + { insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD }, + { insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, + { insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 }, + { insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 }, + { insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 }, + { insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 }, + { insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD }, + { insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, + { insn_dins, 0, 0 }, + { insn_dinsm, 0, 0 }, + { insn_syscall, M(mm_pool32a_op, 0, 0, 0, mm_syscall_op, mm_pool32axf_op), SCIMM}, + { insn_bbit0, 0, 0 }, + { insn_bbit1, 0, 0 }, + { insn_lwx, 0, 0 }, + { insn_ldx, 0, 0 }, + { insn_invalid, 0, 0 } +}; + +#undef M + +static inline __uasminit u32 build_bimm(s32 arg) +{ + WARN(arg > 0xffff || arg < -0x10000, + KERN_WARNING "Micro-assembler field overflow\n"); + + WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n"); + + return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 1) & 0x7fff); +} + +static inline __uasminit u32 build_jimm(u32 arg) +{ + + WARN(arg & ~((JIMM_MASK << 2) | 1), + KERN_WARNING "Micro-assembler field overflow\n"); + + return (arg >> 1) & JIMM_MASK; +} + +/* + * The order of opcode arguments is implicitly left to right, + * starting with RS and ending with FUNC or IMM. + */ +static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) +{ + struct insn *ip = NULL; + unsigned int i; + va_list ap; + u32 op; + + for (i = 0; insn_table_MM[i].opcode != insn_invalid; i++) + if (insn_table_MM[i].opcode == opc) { + ip = &insn_table_MM[i]; + break; + } + + if (!ip || (opc == insn_daddiu && r4k_daddiu_bug())) + panic("Unsupported Micro-assembler instruction %d", opc); + + op = ip->match; + va_start(ap, opc); + if (ip->fields & RS) { + if (opc == insn_mfc0 || opc == insn_mtc0) + op |= build_rt(va_arg(ap, u32)); + else + op |= build_rs(va_arg(ap, u32)); + } + if (ip->fields & RT) { + if (opc == insn_mfc0 || opc == insn_mtc0) + op |= build_rs(va_arg(ap, u32)); + else + op |= build_rt(va_arg(ap, u32)); + } + if (ip->fields & RD) + op |= build_rd(va_arg(ap, u32)); + if (ip->fields & RE) + op |= build_re(va_arg(ap, u32)); + if (ip->fields & SIMM) + op |= build_simm(va_arg(ap, s32)); + if (ip->fields & UIMM) + op |= build_uimm(va_arg(ap, u32)); + if (ip->fields & BIMM) + op |= build_bimm(va_arg(ap, s32)); + if (ip->fields & JIMM) + op |= build_jimm(va_arg(ap, u32)); + if (ip->fields & FUNC) + op |= build_func(va_arg(ap, u32)); + if (ip->fields & SET) + op |= build_set(va_arg(ap, u32)); + if (ip->fields & SCIMM) + op |= build_scimm(va_arg(ap, u32)); + va_end(ap); + +#ifdef CONFIG_CPU_LITTLE_ENDIAN + **buf = ((op & 0xffff) << 16) | (op >> 16); +#else + **buf = op; +#endif + (*buf)++; +} + +static inline void __uasminit +__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) +{ + long laddr = (long)lab->addr; + long raddr = (long)rel->addr; + + switch (rel->type) { + case R_MIPS_PC16: +#ifdef CONFIG_CPU_LITTLE_ENDIAN + *rel->addr |= (build_bimm(laddr - (raddr + 4)) << 16); +#else + *rel->addr |= build_bimm(laddr - (raddr + 4)); +#endif + break; + + default: + panic("Unsupported Micro-assembler relocation %d", + rel->type); + } +} diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c new file mode 100644 index 000000000000..5fcdd8fe3e83 --- /dev/null +++ b/arch/mips/mm/uasm-mips.c @@ -0,0 +1,205 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * A small micro-assembler. It is intentionally kept simple, does only + * support a subset of instructions, and does not try to hide pipeline + * effects like branch delay slots. + * + * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer + * Copyright (C) 2005, 2007 Maciej W. Rozycki + * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> + +#include <asm/inst.h> +#include <asm/elf.h> +#include <asm/bugs.h> +#define UASM_ISA _UASM_ISA_CLASSIC +#include <asm/uasm.h> + +#define RS_MASK 0x1f +#define RS_SH 21 +#define RT_MASK 0x1f +#define RT_SH 16 +#define SCIMM_MASK 0xfffff +#define SCIMM_SH 6 + +/* This macro sets the non-variable bits of an instruction. */ +#define M(a, b, c, d, e, f) \ + ((a) << OP_SH \ + | (b) << RS_SH \ + | (c) << RT_SH \ + | (d) << RD_SH \ + | (e) << RE_SH \ + | (f) << FUNC_SH) + +/* Define these when we are not the ISA the kernel is being compiled with. */ +#ifdef CONFIG_CPU_MICROMIPS +#define CL_uasm_i_b(buf, off) ISAOPC(_beq)(buf, 0, 0, off) +#define CL_uasm_i_beqz(buf, rs, off) ISAOPC(_beq)(buf, rs, 0, off) +#define CL_uasm_i_beqzl(buf, rs, off) ISAOPC(_beql)(buf, rs, 0, off) +#define CL_uasm_i_bnez(buf, rs, off) ISAOPC(_bne)(buf, rs, 0, off) +#endif + +#include "uasm.c" + +static struct insn insn_table[] __uasminitdata = { + { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, + { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, + { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, + { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM }, + { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM }, + { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM }, + { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM }, + { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD }, + { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE }, + { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, + { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET}, + { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET}, + { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, + { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, + { insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE }, + { insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE }, + { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE }, + { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, + { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, + { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, + { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, + { insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE }, + { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE }, + { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, + { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, + { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, + { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, + { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, + { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM }, + { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, + { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, + { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, + { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, + { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, + { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 }, + { insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE }, + { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, + { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, + { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, + { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, + { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, + { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 }, + { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 }, + { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 }, + { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, + { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, + { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, + { insn_invalid, 0, 0 } +}; + +#undef M + +static inline __uasminit u32 build_bimm(s32 arg) +{ + WARN(arg > 0x1ffff || arg < -0x20000, + KERN_WARNING "Micro-assembler field overflow\n"); + + WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n"); + + return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); +} + +static inline __uasminit u32 build_jimm(u32 arg) +{ + WARN(arg & ~(JIMM_MASK << 2), + KERN_WARNING "Micro-assembler field overflow\n"); + + return (arg >> 2) & JIMM_MASK; +} + +/* + * The order of opcode arguments is implicitly left to right, + * starting with RS and ending with FUNC or IMM. + */ +static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) +{ + struct insn *ip = NULL; + unsigned int i; + va_list ap; + u32 op; + + for (i = 0; insn_table[i].opcode != insn_invalid; i++) + if (insn_table[i].opcode == opc) { + ip = &insn_table[i]; + break; + } + + if (!ip || (opc == insn_daddiu && r4k_daddiu_bug())) + panic("Unsupported Micro-assembler instruction %d", opc); + + op = ip->match; + va_start(ap, opc); + if (ip->fields & RS) + op |= build_rs(va_arg(ap, u32)); + if (ip->fields & RT) + op |= build_rt(va_arg(ap, u32)); + if (ip->fields & RD) + op |= build_rd(va_arg(ap, u32)); + if (ip->fields & RE) + op |= build_re(va_arg(ap, u32)); + if (ip->fields & SIMM) + op |= build_simm(va_arg(ap, s32)); + if (ip->fields & UIMM) + op |= build_uimm(va_arg(ap, u32)); + if (ip->fields & BIMM) + op |= build_bimm(va_arg(ap, s32)); + if (ip->fields & JIMM) + op |= build_jimm(va_arg(ap, u32)); + if (ip->fields & FUNC) + op |= build_func(va_arg(ap, u32)); + if (ip->fields & SET) + op |= build_set(va_arg(ap, u32)); + if (ip->fields & SCIMM) + op |= build_scimm(va_arg(ap, u32)); + va_end(ap); + + **buf = op; + (*buf)++; +} + +static inline void __uasminit +__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) +{ + long laddr = (long)lab->addr; + long raddr = (long)rel->addr; + + switch (rel->type) { + case R_MIPS_PC16: + *rel->addr |= build_bimm(laddr - (raddr + 4)); + break; + + default: + panic("Unsupported Micro-assembler relocation %d", + rel->type); + } +} diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 942ff6c2eba2..7eb5e4355d25 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -10,17 +10,9 @@ * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer * Copyright (C) 2005, 2007 Maciej W. Rozycki * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2012, 2013 MIPS Technologies, Inc. All rights reserved. */ -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/init.h> - -#include <asm/inst.h> -#include <asm/elf.h> -#include <asm/bugs.h> -#include <asm/uasm.h> - enum fields { RS = 0x001, RT = 0x002, @@ -37,10 +29,6 @@ enum fields { #define OP_MASK 0x3f #define OP_SH 26 -#define RS_MASK 0x1f -#define RS_SH 21 -#define RT_MASK 0x1f -#define RT_SH 16 #define RD_MASK 0x1f #define RD_SH 11 #define RE_MASK 0x1f @@ -53,8 +41,6 @@ enum fields { #define FUNC_SH 0 #define SET_MASK 0x7 #define SET_SH 0 -#define SCIMM_MASK 0xfffff -#define SCIMM_SH 6 enum opcode { insn_invalid, @@ -77,85 +63,6 @@ struct insn { enum fields fields; }; -/* This macro sets the non-variable bits of an instruction. */ -#define M(a, b, c, d, e, f) \ - ((a) << OP_SH \ - | (b) << RS_SH \ - | (c) << RT_SH \ - | (d) << RD_SH \ - | (e) << RE_SH \ - | (f) << FUNC_SH) - -static struct insn insn_table[] __uasminitdata = { - { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, - { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, - { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, - { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM }, - { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM }, - { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM }, - { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM }, - { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD }, - { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE }, - { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, - { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET}, - { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET}, - { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, - { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, - { insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE }, - { insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE }, - { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE }, - { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, - { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, - { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, - { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, - { insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE }, - { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE }, - { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, - { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, - { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, - { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, - { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, - { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM }, - { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, - { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, - { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, - { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, - { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, - { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 }, - { insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE }, - { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, - { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, - { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, - { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, - { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, - { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 }, - { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 }, - { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 }, - { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, - { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, - { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, - { insn_invalid, 0, 0 } -}; - -#undef M - static inline __uasminit u32 build_rs(u32 arg) { WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n"); @@ -199,24 +106,6 @@ static inline __uasminit u32 build_uimm(u32 arg) return arg & IMM_MASK; } -static inline __uasminit u32 build_bimm(s32 arg) -{ - WARN(arg > 0x1ffff || arg < -0x20000, - KERN_WARNING "Micro-assembler field overflow\n"); - - WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n"); - - return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); -} - -static inline __uasminit u32 build_jimm(u32 arg) -{ - WARN(arg & ~(JIMM_MASK << 2), - KERN_WARNING "Micro-assembler field overflow\n"); - - return (arg >> 2) & JIMM_MASK; -} - static inline __uasminit u32 build_scimm(u32 arg) { WARN(arg & ~SCIMM_MASK, @@ -239,55 +128,7 @@ static inline __uasminit u32 build_set(u32 arg) return arg & SET_MASK; } -/* - * The order of opcode arguments is implicitly left to right, - * starting with RS and ending with FUNC or IMM. - */ -static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) -{ - struct insn *ip = NULL; - unsigned int i; - va_list ap; - u32 op; - - for (i = 0; insn_table[i].opcode != insn_invalid; i++) - if (insn_table[i].opcode == opc) { - ip = &insn_table[i]; - break; - } - - if (!ip || (opc == insn_daddiu && r4k_daddiu_bug())) - panic("Unsupported Micro-assembler instruction %d", opc); - - op = ip->match; - va_start(ap, opc); - if (ip->fields & RS) - op |= build_rs(va_arg(ap, u32)); - if (ip->fields & RT) - op |= build_rt(va_arg(ap, u32)); - if (ip->fields & RD) - op |= build_rd(va_arg(ap, u32)); - if (ip->fields & RE) - op |= build_re(va_arg(ap, u32)); - if (ip->fields & SIMM) - op |= build_simm(va_arg(ap, s32)); - if (ip->fields & UIMM) - op |= build_uimm(va_arg(ap, u32)); - if (ip->fields & BIMM) - op |= build_bimm(va_arg(ap, s32)); - if (ip->fields & JIMM) - op |= build_jimm(va_arg(ap, u32)); - if (ip->fields & FUNC) - op |= build_func(va_arg(ap, u32)); - if (ip->fields & SET) - op |= build_set(va_arg(ap, u32)); - if (ip->fields & SCIMM) - op |= build_scimm(va_arg(ap, u32)); - va_end(ap); - - **buf = op; - (*buf)++; -} +static void __uasminit build_insn(u32 **buf, enum opcode opc, ...); #define I_u1u2u3(op) \ Ip_u1u2u3(op) \ @@ -445,7 +286,7 @@ I_u3u1u2(_ldx) #ifdef CONFIG_CPU_CAVIUM_OCTEON #include <asm/octeon/octeon.h> -void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b, +void __uasminit ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b, unsigned int c) { if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5) @@ -457,21 +298,21 @@ void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b, else build_insn(buf, insn_pref, c, a, b); } -UASM_EXPORT_SYMBOL(uasm_i_pref); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_i_pref)); #else I_u2s3u1(_pref) #endif /* Handle labels. */ -void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) +void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid) { (*lab)->addr = addr; (*lab)->lab = lid; (*lab)++; } -UASM_EXPORT_SYMBOL(uasm_build_label); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label)); -int __uasminit uasm_in_compat_space_p(long addr) +int __uasminit ISAFUNC(uasm_in_compat_space_p)(long addr) { /* Is this address in 32bit compat space? */ #ifdef CONFIG_64BIT @@ -480,7 +321,7 @@ int __uasminit uasm_in_compat_space_p(long addr) return 1; #endif } -UASM_EXPORT_SYMBOL(uasm_in_compat_space_p); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p)); static int __uasminit uasm_rel_highest(long val) { @@ -500,77 +341,66 @@ static int __uasminit uasm_rel_higher(long val) #endif } -int __uasminit uasm_rel_hi(long val) +int __uasminit ISAFUNC(uasm_rel_hi)(long val) { return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; } -UASM_EXPORT_SYMBOL(uasm_rel_hi); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi)); -int __uasminit uasm_rel_lo(long val) +int __uasminit ISAFUNC(uasm_rel_lo)(long val) { return ((val & 0xffff) ^ 0x8000) - 0x8000; } -UASM_EXPORT_SYMBOL(uasm_rel_lo); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo)); -void __uasminit UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr) +void __uasminit ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr) { - if (!uasm_in_compat_space_p(addr)) { - uasm_i_lui(buf, rs, uasm_rel_highest(addr)); + if (!ISAFUNC(uasm_in_compat_space_p)(addr)) { + ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr)); if (uasm_rel_higher(addr)) - uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr)); - if (uasm_rel_hi(addr)) { - uasm_i_dsll(buf, rs, rs, 16); - uasm_i_daddiu(buf, rs, rs, uasm_rel_hi(addr)); - uasm_i_dsll(buf, rs, rs, 16); + ISAFUNC(uasm_i_daddiu)(buf, rs, rs, uasm_rel_higher(addr)); + if (ISAFUNC(uasm_rel_hi(addr))) { + ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16); + ISAFUNC(uasm_i_daddiu)(buf, rs, rs, + ISAFUNC(uasm_rel_hi)(addr)); + ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16); } else - uasm_i_dsll32(buf, rs, rs, 0); + ISAFUNC(uasm_i_dsll32)(buf, rs, rs, 0); } else - uasm_i_lui(buf, rs, uasm_rel_hi(addr)); + ISAFUNC(uasm_i_lui)(buf, rs, ISAFUNC(uasm_rel_hi(addr))); } -UASM_EXPORT_SYMBOL(UASM_i_LA_mostly); +UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly)); -void __uasminit UASM_i_LA(u32 **buf, unsigned int rs, long addr) +void __uasminit ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr) { - UASM_i_LA_mostly(buf, rs, addr); - if (uasm_rel_lo(addr)) { - if (!uasm_in_compat_space_p(addr)) - uasm_i_daddiu(buf, rs, rs, uasm_rel_lo(addr)); + ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr); + if (ISAFUNC(uasm_rel_lo(addr))) { + if (!ISAFUNC(uasm_in_compat_space_p)(addr)) + ISAFUNC(uasm_i_daddiu)(buf, rs, rs, + ISAFUNC(uasm_rel_lo(addr))); else - uasm_i_addiu(buf, rs, rs, uasm_rel_lo(addr)); + ISAFUNC(uasm_i_addiu)(buf, rs, rs, + ISAFUNC(uasm_rel_lo(addr))); } } -UASM_EXPORT_SYMBOL(UASM_i_LA); +UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA)); /* Handle relocations. */ void __uasminit -uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid) +ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid) { (*rel)->addr = addr; (*rel)->type = R_MIPS_PC16; (*rel)->lab = lid; (*rel)++; } -UASM_EXPORT_SYMBOL(uasm_r_mips_pc16); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16)); static inline void __uasminit -__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) -{ - long laddr = (long)lab->addr; - long raddr = (long)rel->addr; - - switch (rel->type) { - case R_MIPS_PC16: - *rel->addr |= build_bimm(laddr - (raddr + 4)); - break; - - default: - panic("Unsupported Micro-assembler relocation %d", - rel->type); - } -} +__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab); void __uasminit -uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) +ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, struct uasm_label *lab) { struct uasm_label *l; @@ -579,40 +409,40 @@ uasm_resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) if (rel->lab == l->lab) __resolve_relocs(rel, l); } -UASM_EXPORT_SYMBOL(uasm_resolve_relocs); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs)); void __uasminit -uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end, long off) +ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, long off) { for (; rel->lab != UASM_LABEL_INVALID; rel++) if (rel->addr >= first && rel->addr < end) rel->addr += off; } -UASM_EXPORT_SYMBOL(uasm_move_relocs); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs)); void __uasminit -uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end, long off) +ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, long off) { for (; lab->lab != UASM_LABEL_INVALID; lab++) if (lab->addr >= first && lab->addr < end) lab->addr += off; } -UASM_EXPORT_SYMBOL(uasm_move_labels); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels)); void __uasminit -uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, +ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, u32 *end, u32 *target) { long off = (long)(target - first); memcpy(target, first, (end - first) * sizeof(u32)); - uasm_move_relocs(rel, first, end, off); - uasm_move_labels(lab, first, end, off); + ISAFUNC(uasm_move_relocs(rel, first, end, off)); + ISAFUNC(uasm_move_labels(lab, first, end, off)); } -UASM_EXPORT_SYMBOL(uasm_copy_handler); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler)); -int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) +int __uasminit ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr) { for (; rel->lab != UASM_LABEL_INVALID; rel++) { if (rel->addr == addr @@ -623,88 +453,88 @@ int __uasminit uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr) return 0; } -UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay)); /* Convenience functions for labeled branches. */ void __uasminit -uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_bltz(p, reg, 0); + ISAFUNC(uasm_i_bltz)(p, reg, 0); } -UASM_EXPORT_SYMBOL(uasm_il_bltz); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz)); void __uasminit -uasm_il_b(u32 **p, struct uasm_reloc **r, int lid) +ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_b(p, 0); + ISAFUNC(uasm_i_b)(p, 0); } -UASM_EXPORT_SYMBOL(uasm_il_b); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); void __uasminit -uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_beqz(p, reg, 0); + ISAFUNC(uasm_i_beqz)(p, reg, 0); } -UASM_EXPORT_SYMBOL(uasm_il_beqz); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz)); void __uasminit -uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_beqzl(p, reg, 0); + ISAFUNC(uasm_i_beqzl)(p, reg, 0); } -UASM_EXPORT_SYMBOL(uasm_il_beqzl); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl)); void __uasminit -uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, +ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1, unsigned int reg2, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_bne(p, reg1, reg2, 0); + ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0); } -UASM_EXPORT_SYMBOL(uasm_il_bne); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne)); void __uasminit -uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_bnez(p, reg, 0); + ISAFUNC(uasm_i_bnez)(p, reg, 0); } -UASM_EXPORT_SYMBOL(uasm_il_bnez); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez)); void __uasminit -uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_bgezl(p, reg, 0); + ISAFUNC(uasm_i_bgezl)(p, reg, 0); } -UASM_EXPORT_SYMBOL(uasm_il_bgezl); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl)); void __uasminit -uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_bgez(p, reg, 0); + ISAFUNC(uasm_i_bgez)(p, reg, 0); } -UASM_EXPORT_SYMBOL(uasm_il_bgez); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez)); void __uasminit -uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, +ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_bbit0(p, reg, bit, 0); + ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0); } -UASM_EXPORT_SYMBOL(uasm_il_bbit0); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0)); void __uasminit -uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, +ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); - uasm_i_bbit1(p, reg, bit, 0); + ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0); } -UASM_EXPORT_SYMBOL(uasm_il_bbit1); +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit1)); diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 6079ef33b5f0..0388fc8b5613 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -5,9 +5,8 @@ # Copyright (C) 2008 Wind River Systems, Inc. # written by Ralf Baechle <ralf@linux-mips.org> # -obj-y := malta-amon.o malta-cmdline.o \ - malta-display.o malta-init.o malta-int.o \ - malta-memory.o malta-platform.o \ +obj-y := malta-amon.o malta-display.o malta-init.o \ + malta-int.o malta-memory.o malta-platform.o \ malta-reset.o malta-setup.o malta-time.o obj-$(CONFIG_EARLY_PRINTK) += malta-console.o diff --git a/arch/mips/mti-malta/Platform b/arch/mips/mti-malta/Platform index 5b548b5a4fcf..2cc72c9b38e3 100644 --- a/arch/mips/mti-malta/Platform +++ b/arch/mips/mti-malta/Platform @@ -3,5 +3,9 @@ # platform-$(CONFIG_MIPS_MALTA) += mti-malta/ cflags-$(CONFIG_MIPS_MALTA) += -I$(srctree)/arch/mips/include/asm/mach-malta -load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 +ifdef CONFIG_KVM_GUEST + load-$(CONFIG_MIPS_MALTA) += 0x0000000040100000 +else + load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 +endif all-$(CONFIG_MIPS_MALTA) := $(COMPRESSION_FNAME).bin diff --git a/arch/mips/mti-malta/malta-cmdline.c b/arch/mips/mti-malta/malta-cmdline.c deleted file mode 100644 index 5576a306a145..000000000000 --- a/arch/mips/mti-malta/malta-cmdline.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute 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 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. - * - * Kernel command line creation using the prom monitor (YAMON) argc/argv. - */ -#include <linux/init.h> -#include <linux/string.h> - -#include <asm/bootinfo.h> - -extern int prom_argc; -extern int *_prom_argv; - -/* - * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. - * This macro take care of sign extension. - */ -#define prom_argv(index) ((char *)(long)_prom_argv[(index)]) - -char * __init prom_getcmdline(void) -{ - return &(arcs_cmdline[0]); -} - - -void __init prom_init_cmdline(void) -{ - char *cp; - int actr; - - actr = 1; /* Always ignore argv[0] */ - - cp = &(arcs_cmdline[0]); - while(actr < prom_argc) { - strcpy(cp, prom_argv(actr)); - cp += strlen(prom_argv(actr)); - *cp++ = ' '; - actr++; - } - if (cp != &(arcs_cmdline[0])) { - /* get rid of trailing space */ - --cp; - *cp = '\0'; - } -} diff --git a/arch/mips/mti-malta/malta-display.c b/arch/mips/mti-malta/malta-display.c index 9bc58a24e80a..d4f807191ecd 100644 --- a/arch/mips/mti-malta/malta-display.c +++ b/arch/mips/mti-malta/malta-display.c @@ -1,28 +1,20 @@ /* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute 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 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. + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * * Display routines for display messages in MIPS boards ascii display. + * + * Copyright (C) 1999,2000,2012 MIPS Technologies, Inc. + * All rights reserved. + * Authors: Carsten Langgaard <carstenl@mips.com> + * Steven J. Hill <sjhill@mips.com> */ - #include <linux/compiler.h> #include <linux/timer.h> -#include <asm/io.h> +#include <linux/io.h> + #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/prom.h> extern const char display_string[]; static unsigned int display_count; @@ -36,11 +28,11 @@ void mips_display_message(const char *str) if (unlikely(display == NULL)) display = ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int)); - for (i = 0; i <= 14; i=i+2) { - if (*str) - __raw_writel(*str++, display + i); - else - __raw_writel(' ', display + i); + for (i = 0; i <= 14; i += 2) { + if (*str) + __raw_writel(*str++, display + i); + else + __raw_writel(' ', display + i); } } diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index c2cbce9e435e..ff8caffd3266 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c @@ -1,54 +1,28 @@ /* - * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc. - * All rights reserved. - * Authors: Carsten Langgaard <carstenl@mips.com> - * Maciej W. Rozycki <macro@mips.com> - * - * This program is free software; you can distribute 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 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. + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * * PROM library initialisation code. + * + * Copyright (C) 1999,2000,2004,2005,2012 MIPS Technologies, Inc. + * All rights reserved. + * Authors: Carsten Langgaard <carstenl@mips.com> + * Maciej W. Rozycki <macro@mips.com> + * Steven J. Hill <sjhill@mips.com> */ #include <linux/init.h> #include <linux/string.h> #include <linux/kernel.h> -#include <asm/bootinfo.h> -#include <asm/gt64120.h> -#include <asm/io.h> #include <asm/cacheflush.h> #include <asm/smp-ops.h> #include <asm/traps.h> - +#include <asm/fw/fw.h> #include <asm/gcmpregs.h> -#include <asm/mips-boards/prom.h> #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/bonito64.h> -#include <asm/mips-boards/msc01_pci.h> - #include <asm/mips-boards/malta.h> -int prom_argc; -int *_prom_argv, *_prom_envp; - -/* - * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. - * This macro take care of sign extension, if running in 64-bit mode. - */ -#define prom_envp(index) ((char *)(long)_prom_envp[(index)]) - -int init_debug; - static int mips_revision_corid; int mips_revision_sconid; @@ -62,74 +36,6 @@ unsigned long _pcictrl_gt64120; /* MIPS System controller register base */ unsigned long _pcictrl_msc; -char *prom_getenv(char *envname) -{ - /* - * Return a pointer to the given environment variable. - * In 64-bit mode: we're using 64-bit pointers, but all pointers - * in the PROM structures are only 32-bit, so we need some - * workarounds, if we are running in 64-bit mode. - */ - int i, index=0; - - i = strlen(envname); - - while (prom_envp(index)) { - if(strncmp(envname, prom_envp(index), i) == 0) { - return(prom_envp(index+1)); - } - index += 2; - } - - return NULL; -} - -static inline unsigned char str2hexnum(unsigned char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - return 0; /* foo */ -} - -static inline void str2eaddr(unsigned char *ea, unsigned char *str) -{ - int i; - - for (i = 0; i < 6; i++) { - unsigned char num; - - if((*str == '.') || (*str == ':')) - str++; - num = str2hexnum(*str++) << 4; - num |= (str2hexnum(*str++)); - ea[i] = num; - } -} - -int get_ethernet_addr(char *ethernet_addr) -{ - char *ethaddr_str; - - ethaddr_str = prom_getenv("ethaddr"); - if (!ethaddr_str) { - printk("ethaddr not set in boot prom\n"); - return -1; - } - str2eaddr(ethernet_addr, ethaddr_str); - - if (init_debug > 1) { - int i; - printk("get_ethernet_addr: "); - for (i=0; i<5; i++) - printk("%02x:", (unsigned char)*(ethernet_addr+i)); - printk("%02x\n", *(ethernet_addr+i)); - } - - return 0; -} - #ifdef CONFIG_SERIAL_8250_CONSOLE static void __init console_config(void) { @@ -138,17 +44,23 @@ static void __init console_config(void) char parity = '\0', bits = '\0', flow = '\0'; char *s; - if ((strstr(prom_getcmdline(), "console=")) == NULL) { - s = prom_getenv("modetty0"); + if ((strstr(fw_getcmdline(), "console=")) == NULL) { + s = fw_getenv("modetty0"); if (s) { while (*s >= '0' && *s <= '9') baud = baud*10 + *s++ - '0'; - if (*s == ',') s++; - if (*s) parity = *s++; - if (*s == ',') s++; - if (*s) bits = *s++; - if (*s == ',') s++; - if (*s == 'h') flow = 'r'; + if (*s == ',') + s++; + if (*s) + parity = *s++; + if (*s == ',') + s++; + if (*s) + bits = *s++; + if (*s == ',') + s++; + if (*s == 'h') + flow = 'r'; } if (baud == 0) baud = 38400; @@ -158,8 +70,9 @@ static void __init console_config(void) bits = '8'; if (flow == '\0') flow = 'r'; - sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow); - strcat(prom_getcmdline(), console_string); + sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, + parity, bits, flow); + strcat(fw_getcmdline(), console_string); pr_info("Config serial console:%s\n", console_string); } } @@ -193,10 +106,6 @@ extern struct plat_smp_ops msmtc_smp_ops; void __init prom_init(void) { - prom_argc = fw_arg0; - _prom_argv = (int *) fw_arg1; - _prom_envp = (int *) fw_arg2; - mips_display_message("LINUX"); /* @@ -306,7 +215,7 @@ void __init prom_init(void) case MIPS_REVISION_SCON_SOCIT: case MIPS_REVISION_SCON_ROCIT: _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000); - mips_pci_controller: +mips_pci_controller: mb(); MSC_READ(MSC01_PCI_CFG, data); MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT); @@ -348,13 +257,13 @@ void __init prom_init(void) default: /* Unknown system controller */ mips_display_message("SC Error"); - while (1); /* We die here... */ + while (1); /* We die here... */ } board_nmi_handler_setup = mips_nmi_setup; board_ejtag_handler_setup = mips_ejtag_setup; - prom_init_cmdline(); - prom_meminit(); + fw_init_cmdline(); + fw_meminit(); #ifdef CONFIG_SERIAL_8250_CONSOLE console_config(); #endif diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index e364af70e6cf..0a1339ac3ec8 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -47,7 +47,6 @@ #include <asm/setup.h> int gcmp_present = -1; -int gic_present; static unsigned long _msc01_biu_base; static unsigned long _gcmp_base; static unsigned int ipi_map[NR_CPUS]; @@ -134,6 +133,9 @@ static void malta_ipi_irqdispatch(void) { int irq; + if (gic_compare_int()) + do_IRQ(MIPS_GIC_IRQ_BASE); + irq = gic_get_int(); if (irq < 0) return; /* interrupt has already been cleared */ diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c index f3d43aa023a9..1f73d63e92a7 100644 --- a/arch/mips/mti-malta/malta-memory.c +++ b/arch/mips/mti-malta/malta-memory.c @@ -1,73 +1,45 @@ /* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute 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 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. + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * * PROM library functions for acquiring/using memory descriptors given to * us from the YAMON. + * + * Copyright (C) 1999,2000,2012 MIPS Technologies, Inc. + * All rights reserved. + * Authors: Carsten Langgaard <carstenl@mips.com> + * Steven J. Hill <sjhill@mips.com> */ #include <linux/init.h> -#include <linux/mm.h> #include <linux/bootmem.h> -#include <linux/pfn.h> #include <linux/string.h> #include <asm/bootinfo.h> -#include <asm/page.h> #include <asm/sections.h> +#include <asm/fw/fw.h> -#include <asm/mips-boards/prom.h> - -/*#define DEBUG*/ - -enum yamon_memtypes { - yamon_dontuse, - yamon_prom, - yamon_free, -}; -static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; - -#ifdef DEBUG -static char *mtypes[3] = { - "Dont use memory", - "YAMON PROM memory", - "Free memory", -}; -#endif +static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS]; /* determined physical memory size, not overridden by command line args */ unsigned long physical_memsize = 0L; -static struct prom_pmemblock * __init prom_getmdesc(void) +fw_memblock_t * __init fw_getmdesc(void) { - char *memsize_str; + char *memsize_str, *ptr; unsigned int memsize; - char *ptr; static char cmdline[COMMAND_LINE_SIZE] __initdata; + long val; + int tmp; /* otherwise look in the environment */ - memsize_str = prom_getenv("memsize"); + memsize_str = fw_getenv("memsize"); if (!memsize_str) { - printk(KERN_WARNING - "memsize not set in boot prom, set to default (32Mb)\n"); + pr_warn("memsize not set in YAMON, set to default (32Mb)\n"); physical_memsize = 0x02000000; } else { -#ifdef DEBUG - pr_debug("prom_memsize = %s\n", memsize_str); -#endif - physical_memsize = simple_strtol(memsize_str, NULL, 0); + tmp = kstrtol(memsize_str, 0, &val); + physical_memsize = (unsigned long)val; } #ifdef CONFIG_CPU_BIG_ENDIAN @@ -90,11 +62,11 @@ static struct prom_pmemblock * __init prom_getmdesc(void) memset(mdesc, 0, sizeof(mdesc)); - mdesc[0].type = yamon_dontuse; + mdesc[0].type = fw_dontuse; mdesc[0].base = 0x00000000; mdesc[0].size = 0x00001000; - mdesc[1].type = yamon_prom; + mdesc[1].type = fw_code; mdesc[1].base = 0x00001000; mdesc[1].size = 0x000ef000; @@ -105,55 +77,45 @@ static struct prom_pmemblock * __init prom_getmdesc(void) * This mean that this area can't be used as DMA memory for PCI * devices. */ - mdesc[2].type = yamon_dontuse; + mdesc[2].type = fw_dontuse; mdesc[2].base = 0x000f0000; mdesc[2].size = 0x00010000; - mdesc[3].type = yamon_dontuse; + mdesc[3].type = fw_dontuse; mdesc[3].base = 0x00100000; - mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base; + mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - + mdesc[3].base; - mdesc[4].type = yamon_free; + mdesc[4].type = fw_free; mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); mdesc[4].size = memsize - mdesc[4].base; return &mdesc[0]; } -static int __init prom_memtype_classify(unsigned int type) +static int __init fw_memtype_classify(unsigned int type) { switch (type) { - case yamon_free: + case fw_free: return BOOT_MEM_RAM; - case yamon_prom: + case fw_code: return BOOT_MEM_ROM_DATA; default: return BOOT_MEM_RESERVED; } } -void __init prom_meminit(void) +void __init fw_meminit(void) { - struct prom_pmemblock *p; + fw_memblock_t *p; -#ifdef DEBUG - pr_debug("YAMON MEMORY DESCRIPTOR dump:\n"); - p = prom_getmdesc(); - while (p->size) { - int i = 0; - pr_debug("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n", - i, p, p->base, p->size, mtypes[p->type]); - p++; - i++; - } -#endif - p = prom_getmdesc(); + p = fw_getmdesc(); while (p->size) { long type; unsigned long base, size; - type = prom_memtype_classify(p->type); + type = fw_memtype_classify(p->type); base = p->base; size = p->size; @@ -172,7 +134,7 @@ void __init prom_free_prom_memory(void) continue; addr = boot_mem_map.map[i].addr; - free_init_pages("prom memory", + free_init_pages("YAMON memory", addr, addr + boot_mem_map.map[i].size); } } diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c index 200f64df2c9b..c72a06936781 100644 --- a/arch/mips/mti-malta/malta-setup.c +++ b/arch/mips/mti-malta/malta-setup.c @@ -25,13 +25,13 @@ #include <linux/screen_info.h> #include <linux/time.h> -#include <asm/bootinfo.h> +#include <asm/fw/fw.h> #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/prom.h> #include <asm/mips-boards/malta.h> #include <asm/mips-boards/maltaint.h> #include <asm/dma.h> #include <asm/traps.h> +#include <asm/gcmpregs.h> #ifdef CONFIG_VT #include <linux/console.h> #endif @@ -105,6 +105,66 @@ static void __init fd_activate(void) } #endif +static int __init plat_enable_iocoherency(void) +{ + int supported = 0; + if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) { + if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) { + BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN; + pr_info("Enabled Bonito CPU coherency\n"); + supported = 1; + } + if (strstr(fw_getcmdline(), "iobcuncached")) { + BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN; + BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & + ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | + BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); + pr_info("Disabled Bonito IOBC coherency\n"); + } else { + BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN; + BONITO_PCIMEMBASECFG |= + (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | + BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); + pr_info("Enabled Bonito IOBC coherency\n"); + } + } else if (gcmp_niocu() != 0) { + /* Nothing special needs to be done to enable coherency */ + pr_info("CMP IOCU detected\n"); + if ((*(unsigned int *)0xbf403000 & 0x81) != 0x81) { + pr_crit("IOCU OPERATION DISABLED BY SWITCH - DEFAULTING TO SW IO COHERENCY\n"); + return 0; + } + supported = 1; + } + hw_coherentio = supported; + return supported; +} + +static void __init plat_setup_iocoherency(void) +{ +#ifdef CONFIG_DMA_NONCOHERENT + /* + * Kernel has been configured with software coherency + * but we might choose to turn it off and use hardware + * coherency instead. + */ + if (plat_enable_iocoherency()) { + if (coherentio == 0) + pr_info("Hardware DMA cache coherency disabled\n"); + else + pr_info("Hardware DMA cache coherency enabled\n"); + } else { + if (coherentio == 1) + pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n"); + else + pr_info("Software DMA cache coherency enabled\n"); + } +#else + if (!plat_enable_iocoherency()) + panic("Hardware DMA cache coherency not supported!"); +#endif +} + #ifdef CONFIG_BLK_DEV_IDE static void __init pci_clock_check(void) { @@ -115,16 +175,15 @@ static void __init pci_clock_check(void) 33, 20, 25, 30, 12, 16, 37, 10 }; int pciclock = pciclocks[jmpr]; - char *argptr = prom_getcmdline(); + char *argptr = fw_getcmdline(); if (pciclock != 33 && !strstr(argptr, "idebus=")) { - printk(KERN_WARNING "WARNING: PCI clock is %dMHz, " - "setting idebus\n", pciclock); + pr_warn("WARNING: PCI clock is %dMHz, setting idebus\n", + pciclock); argptr += strlen(argptr); sprintf(argptr, " idebus=%d", pciclock); if (pciclock < 20 || pciclock > 66) - printk(KERN_WARNING "WARNING: IDE timing " - "calculations will be incorrect\n"); + pr_warn("WARNING: IDE timing calculations will be incorrect\n"); } } #endif @@ -153,31 +212,31 @@ static void __init bonito_quirks_setup(void) { char *argptr; - argptr = prom_getcmdline(); + argptr = fw_getcmdline(); if (strstr(argptr, "debug")) { BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE; - printk(KERN_INFO "Enabled Bonito debug mode\n"); + pr_info("Enabled Bonito debug mode\n"); } else BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE; #ifdef CONFIG_DMA_COHERENT if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) { BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN; - printk(KERN_INFO "Enabled Bonito CPU coherency\n"); + pr_info("Enabled Bonito CPU coherency\n"); - argptr = prom_getcmdline(); + argptr = fw_getcmdline(); if (strstr(argptr, "iobcuncached")) { BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN; BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); - printk(KERN_INFO "Disabled Bonito IOBC coherency\n"); + pr_info("Disabled Bonito IOBC coherency\n"); } else { BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN; BONITO_PCIMEMBASECFG |= (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); - printk(KERN_INFO "Enabled Bonito IOBC coherency\n"); + pr_info("Enabled Bonito IOBC coherency\n"); } } else panic("Hardware DMA cache coherency not supported"); @@ -207,6 +266,8 @@ void __init plat_mem_setup(void) if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) bonito_quirks_setup(); + plat_setup_iocoherency(); + #ifdef CONFIG_BLK_DEV_IDE pci_clock_check(); #endif diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index a144b89cf9ba..0ad305f75802 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -39,12 +39,9 @@ #include <asm/gic.h> #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/prom.h> - #include <asm/mips-boards/maltaint.h> unsigned long cpu_khz; -int gic_frequency; static int mips_cpu_timer_irq; static int mips_cpu_perf_irq; @@ -74,7 +71,24 @@ static void __init estimate_frequencies(void) { unsigned long flags; unsigned int count, start; +#ifdef CONFIG_IRQ_GIC unsigned int giccount = 0, gicstart = 0; +#endif + +#if defined (CONFIG_KVM_GUEST) && defined (CONFIG_KVM_HOST_FREQ) + unsigned int prid = read_c0_prid() & 0xffff00; + + /* + * XXXKYMA: hardwire the CPU frequency to Host Freq/4 + */ + count = (CONFIG_KVM_HOST_FREQ * 1000000) >> 3; + if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && + (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) + count *= 2; + + mips_hpt_frequency = count; + return; +#endif local_irq_save(flags); @@ -84,26 +98,32 @@ static void __init estimate_frequencies(void) /* Initialize counters. */ start = read_c0_count(); +#ifdef CONFIG_IRQ_GIC if (gic_present) GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), gicstart); +#endif /* Read counter exactly on falling edge of update flag. */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); count = read_c0_count(); +#ifdef CONFIG_IRQ_GIC if (gic_present) GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), giccount); +#endif local_irq_restore(flags); count -= start; - if (gic_present) - giccount -= gicstart; - mips_hpt_frequency = count; - if (gic_present) + +#ifdef CONFIG_IRQ_GIC + if (gic_present) { + giccount -= gicstart; gic_frequency = giccount; + } +#endif } void read_persistent_clock(struct timespec *ts) @@ -159,24 +179,27 @@ void __init plat_time_init(void) (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) freq *= 2; freq = freqround(freq, 5000); - pr_debug("CPU frequency %d.%02d MHz\n", freq/1000000, + printk("CPU frequency %d.%02d MHz\n", freq/1000000, (freq%1000000)*100/1000000); cpu_khz = freq / 1000; - if (gic_present) { - freq = freqround(gic_frequency, 5000); - pr_debug("GIC frequency %d.%02d MHz\n", freq/1000000, - (freq%1000000)*100/1000000); - gic_clocksource_init(gic_frequency); - } else - init_r4k_clocksource(); + mips_scroll_message(); #ifdef CONFIG_I8253 /* Only Malta has a PIT. */ setup_pit_timer(); #endif - mips_scroll_message(); +#ifdef CONFIG_IRQ_GIC + if (gic_present) { + freq = freqround(gic_frequency, 5000); + printk("GIC frequency %d.%02d MHz\n", freq/1000000, + (freq%1000000)*100/1000000); +#ifdef CONFIG_CSRC_GIC + gic_clocksource_init(gic_frequency); +#endif + } +#endif plat_perf_setup(); } diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index 10ec701ce6c7..be114209217c 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -8,10 +8,10 @@ # Copyright (C) 2012 MIPS Technoligies, Inc. All rights reserved. # Steven J. Hill <sjhill@mips.com> # -obj-y := sead3-lcd.o sead3-cmdline.o \ - sead3-display.o sead3-init.o sead3-int.o \ - sead3-mtd.o sead3-net.o sead3-platform.o \ - sead3-reset.o sead3-setup.o sead3-time.o +obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ + sead3-int.o sead3-mtd.o sead3-net.o \ + sead3-platform.o sead3-reset.o \ + sead3-setup.o sead3-time.o obj-y += sead3-i2c-dev.o sead3-i2c.o \ sead3-pic32-i2c-drv.o sead3-pic32-bus.o \ diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c index 322148c353ed..0a168c948b01 100644 --- a/arch/mips/mti-sead3/leds-sead3.c +++ b/arch/mips/mti-sead3/leds-sead3.c @@ -34,33 +34,15 @@ static void sead3_fled_set(struct led_classdev *led_cdev, static struct led_classdev sead3_pled = { .name = "sead3::pled", .brightness_set = sead3_pled_set, + .flags = LED_CORE_SUSPENDRESUME, }; static struct led_classdev sead3_fled = { .name = "sead3::fled", .brightness_set = sead3_fled_set, + .flags = LED_CORE_SUSPENDRESUME, }; -#ifdef CONFIG_PM -static int sead3_led_suspend(struct platform_device *dev, - pm_message_t state) -{ - led_classdev_suspend(&sead3_pled); - led_classdev_suspend(&sead3_fled); - return 0; -} - -static int sead3_led_resume(struct platform_device *dev) -{ - led_classdev_resume(&sead3_pled); - led_classdev_resume(&sead3_fled); - return 0; -} -#else -#define sead3_led_suspend NULL -#define sead3_led_resume NULL -#endif - static int sead3_led_probe(struct platform_device *pdev) { int ret; @@ -86,8 +68,6 @@ static int sead3_led_remove(struct platform_device *pdev) static struct platform_driver sead3_led_driver = { .probe = sead3_led_probe, .remove = sead3_led_remove, - .suspend = sead3_led_suspend, - .resume = sead3_led_resume, .driver = { .name = DRVNAME, .owner = THIS_MODULE, diff --git a/arch/mips/mti-sead3/sead3-cmdline.c b/arch/mips/mti-sead3/sead3-cmdline.c deleted file mode 100644 index a2e6cec67f57..000000000000 --- a/arch/mips/mti-sead3/sead3-cmdline.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/string.h> - -#include <asm/bootinfo.h> - -extern int prom_argc; -extern int *_prom_argv; - -/* - * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. - * This macro take care of sign extension. - */ -#define prom_argv(index) ((char *)(long)_prom_argv[(index)]) - -char * __init prom_getcmdline(void) -{ - return &(arcs_cmdline[0]); -} - -void __init prom_init_cmdline(void) -{ - char *cp; - int actr; - - actr = 1; /* Always ignore argv[0] */ - - cp = &(arcs_cmdline[0]); - while (actr < prom_argc) { - strcpy(cp, prom_argv(actr)); - cp += strlen(prom_argv(actr)); - *cp++ = ' '; - actr++; - } - if (cp != &(arcs_cmdline[0])) { - /* get rid of trailing space */ - --cp; - *cp = '\0'; - } -} diff --git a/arch/mips/mti-sead3/sead3-console.c b/arch/mips/mti-sead3/sead3-console.c index 2ddef19a9adc..031f47d69770 100644 --- a/arch/mips/mti-sead3/sead3-console.c +++ b/arch/mips/mti-sead3/sead3-console.c @@ -26,7 +26,7 @@ static inline void serial_out(int offset, int value, unsigned int base_addr) __raw_writel(value, PORT(base_addr, offset)); } -void __init prom_init_early_console(char port) +void __init fw_init_early_console(char port) { console_port = port; } diff --git a/arch/mips/mti-sead3/sead3-display.c b/arch/mips/mti-sead3/sead3-display.c index e389326cfa42..94875991907b 100644 --- a/arch/mips/mti-sead3/sead3-display.c +++ b/arch/mips/mti-sead3/sead3-display.c @@ -8,7 +8,6 @@ #include <linux/timer.h> #include <linux/io.h> #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/prom.h> static unsigned int display_count; static unsigned int max_display_count; diff --git a/arch/mips/mti-sead3/sead3-init.c b/arch/mips/mti-sead3/sead3-init.c index f95abaa1aa5d..bfbd17b120a2 100644 --- a/arch/mips/mti-sead3/sead3-init.c +++ b/arch/mips/mti-sead3/sead3-init.c @@ -12,38 +12,51 @@ #include <asm/cacheflush.h> #include <asm/traps.h> #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/prom.h> - -extern void prom_init_early_console(char port); +#include <asm/fw/fw.h> extern char except_vec_nmi; extern char except_vec_ejtag_debug; -int prom_argc; -int *_prom_argv, *_prom_envp; - -#define prom_envp(index) ((char *)(long)_prom_envp[(index)]) - -char *prom_getenv(char *envname) +#ifdef CONFIG_SERIAL_8250_CONSOLE +static void __init console_config(void) { - /* - * Return a pointer to the given environment variable. - * In 64-bit mode: we're using 64-bit pointers, but all pointers - * in the PROM structures are only 32-bit, so we need some - * workarounds, if we are running in 64-bit mode. - */ - int i, index = 0; - - i = strlen(envname); - - while (prom_envp(index)) { - if (strncmp(envname, prom_envp(index), i) == 0) - return prom_envp(index+1); - index += 2; + char console_string[40]; + int baud = 0; + char parity = '\0', bits = '\0', flow = '\0'; + char *s; + + if ((strstr(fw_getcmdline(), "console=")) == NULL) { + s = fw_getenv("modetty0"); + if (s) { + while (*s >= '0' && *s <= '9') + baud = baud*10 + *s++ - '0'; + if (*s == ',') + s++; + if (*s) + parity = *s++; + if (*s == ',') + s++; + if (*s) + bits = *s++; + if (*s == ',') + s++; + if (*s == 'h') + flow = 'r'; + } + if (baud == 0) + baud = 38400; + if (parity != 'n' && parity != 'o' && parity != 'e') + parity = 'n'; + if (bits != '7' && bits != '8') + bits = '8'; + if (flow == '\0') + flow = 'r'; + sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, + parity, bits, flow); + strcat(fw_getcmdline(), console_string); } - - return NULL; } +#endif static void __init mips_nmi_setup(void) { @@ -52,7 +65,41 @@ static void __init mips_nmi_setup(void) base = cpu_has_veic ? (void *)(CAC_BASE + 0xa80) : (void *)(CAC_BASE + 0x380); +#ifdef CONFIG_CPU_MICROMIPS + /* + * Decrement the exception vector address by one for microMIPS. + */ + memcpy(base, (&except_vec_nmi - 1), 0x80); + + /* + * This is a hack. We do not know if the boot loader was built with + * microMIPS instructions or not. If it was not, the NMI exception + * code at 0x80000a80 will be taken in MIPS32 mode. The hand coded + * assembly below forces us into microMIPS mode if we are a pure + * microMIPS kernel. The assembly instructions are: + * + * 3C1A8000 lui k0,0x8000 + * 375A0381 ori k0,k0,0x381 + * 03400008 jr k0 + * 00000000 nop + * + * The mode switch occurs by jumping to the unaligned exception + * vector address at 0x80000381 which would have been 0x80000380 + * in MIPS32 mode. The jump to the unaligned address transitions + * us into microMIPS mode. + */ + if (!cpu_has_veic) { + void *base2 = (void *)(CAC_BASE + 0xa80); + *((unsigned int *)base2) = 0x3c1a8000; + *((unsigned int *)base2 + 1) = 0x375a0381; + *((unsigned int *)base2 + 2) = 0x03400008; + *((unsigned int *)base2 + 3) = 0x00000000; + flush_icache_range((unsigned long)base2, + (unsigned long)base2 + 0x10); + } +#else memcpy(base, &except_vec_nmi, 0x80); +#endif flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); } @@ -63,29 +110,40 @@ static void __init mips_ejtag_setup(void) base = cpu_has_veic ? (void *)(CAC_BASE + 0xa00) : (void *)(CAC_BASE + 0x300); +#ifdef CONFIG_CPU_MICROMIPS + /* Deja vu... */ + memcpy(base, (&except_vec_ejtag_debug - 1), 0x80); + if (!cpu_has_veic) { + void *base2 = (void *)(CAC_BASE + 0xa00); + *((unsigned int *)base2) = 0x3c1a8000; + *((unsigned int *)base2 + 1) = 0x375a0301; + *((unsigned int *)base2 + 2) = 0x03400008; + *((unsigned int *)base2 + 3) = 0x00000000; + flush_icache_range((unsigned long)base2, + (unsigned long)base2 + 0x10); + } +#else memcpy(base, &except_vec_ejtag_debug, 0x80); +#endif flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); } void __init prom_init(void) { - prom_argc = fw_arg0; - _prom_argv = (int *) fw_arg1; - _prom_envp = (int *) fw_arg2; - board_nmi_handler_setup = mips_nmi_setup; board_ejtag_handler_setup = mips_ejtag_setup; - prom_init_cmdline(); + fw_init_cmdline(); #ifdef CONFIG_EARLY_PRINTK - if ((strstr(prom_getcmdline(), "console=ttyS0")) != NULL) - prom_init_early_console(0); - else if ((strstr(prom_getcmdline(), "console=ttyS1")) != NULL) - prom_init_early_console(1); + if ((strstr(fw_getcmdline(), "console=ttyS0")) != NULL) + fw_init_early_console(0); + else if ((strstr(fw_getcmdline(), "console=ttyS1")) != NULL) + fw_init_early_console(1); #endif #ifdef CONFIG_SERIAL_8250_CONSOLE - if ((strstr(prom_getcmdline(), "console=")) == NULL) - strcat(prom_getcmdline(), " console=ttyS0,38400n8r"); + if ((strstr(fw_getcmdline(), "console=")) == NULL) + strcat(fw_getcmdline(), " console=ttyS0,38400n8r"); + console_config(); #endif } diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c index e26e08274fc5..6a560ac03def 100644 --- a/arch/mips/mti-sead3/sead3-int.c +++ b/arch/mips/mti-sead3/sead3-int.c @@ -20,7 +20,6 @@ #define SEAD_CONFIG_BASE 0x1b100110 #define SEAD_CONFIG_SIZE 4 -int gic_present; static unsigned long sead3_config_reg; /* diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c index f012fd164cee..b5059dc899f4 100644 --- a/arch/mips/mti-sead3/sead3-setup.c +++ b/arch/mips/mti-sead3/sead3-setup.c @@ -11,10 +11,6 @@ #include <linux/bootmem.h> #include <asm/mips-boards/generic.h> -#include <asm/prom.h> - -int coherentio; /* 0 => no DMA cache coherency (may be set by user) */ -int hw_coherentio; /* 0 => no HW DMA cache coherency (reflects real HW) */ const char *get_system_type(void) { diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c index 239e4e32757f..96b42eb9b5e2 100644 --- a/arch/mips/mti-sead3/sead3-time.c +++ b/arch/mips/mti-sead3/sead3-time.c @@ -11,7 +11,6 @@ #include <asm/time.h> #include <asm/irq.h> #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/prom.h> unsigned long cpu_khz; diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index 3c05bf9e280a..e0873a31ebaa 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -2,13 +2,22 @@ if NLM_XLP_BOARD || NLM_XLR_BOARD if NLM_XLP_BOARD config DT_XLP_EVP - bool "Built-in device tree for XLP EVP/SVP boards" + bool "Built-in device tree for XLP EVP boards" default y help - Add an FDT blob for XLP EVP and SVP boards into the kernel. + Add an FDT blob for XLP EVP boards into the kernel. This DTB will be used if the firmware does not pass in a DTB - pointer to the kernel. The corresponding DTS file is at - arch/mips/netlogic/dts/xlp_evp.dts + pointer to the kernel. The corresponding DTS file is at + arch/mips/netlogic/dts/xlp_evp.dts + +config DT_XLP_SVP + bool "Built-in device tree for XLP SVP boards" + default y + help + Add an FDT blob for XLP VP boards into the kernel. + This DTB will be used if the firmware does not pass in a DTB + pointer to the kernel. The corresponding DTS file is at + arch/mips/netlogic/dts/xlp_svp.dts config NLM_MULTINODE bool "Support for multi-chip boards" diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index 2bb95dcfe20a..ffba52489bef 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -148,8 +148,7 @@ void nlm_cpus_done(void) int nlm_cpu_ready[NR_CPUS]; unsigned long nlm_next_gp; unsigned long nlm_next_sp; - -cpumask_t phys_cpu_present_map; +static cpumask_t phys_cpu_present_mask; void nlm_boot_secondary(int logical_cpu, struct task_struct *idle) { @@ -169,11 +168,12 @@ void __init nlm_smp_setup(void) { unsigned int boot_cpu; int num_cpus, i, ncore; + char buf[64]; boot_cpu = hard_smp_processor_id(); - cpumask_clear(&phys_cpu_present_map); + cpumask_clear(&phys_cpu_present_mask); - cpumask_set_cpu(boot_cpu, &phys_cpu_present_map); + cpumask_set_cpu(boot_cpu, &phys_cpu_present_mask); __cpu_number_map[boot_cpu] = 0; __cpu_logical_map[0] = boot_cpu; set_cpu_possible(0, true); @@ -185,7 +185,7 @@ void __init nlm_smp_setup(void) * it is only set for ASPs (see smpboot.S) */ if (nlm_cpu_ready[i]) { - cpumask_set_cpu(i, &phys_cpu_present_map); + cpumask_set_cpu(i, &phys_cpu_present_mask); __cpu_number_map[i] = num_cpus; __cpu_logical_map[num_cpus] = i; set_cpu_possible(num_cpus, true); @@ -193,16 +193,19 @@ void __init nlm_smp_setup(void) } } + cpumask_scnprintf(buf, ARRAY_SIZE(buf), &phys_cpu_present_mask); + pr_info("Physical CPU mask: %s\n", buf); + cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask); + pr_info("Possible CPU mask: %s\n", buf); + /* check with the cores we have worken up */ for (ncore = 0, i = 0; i < NLM_NR_NODES; i++) ncore += hweight32(nlm_get_node(i)->coremask); - pr_info("Phys CPU present map: %lx, possible map %lx\n", - (unsigned long)cpumask_bits(&phys_cpu_present_map)[0], - (unsigned long)cpumask_bits(cpu_possible_mask)[0]); - pr_info("Detected (%dc%dt) %d Slave CPU(s)\n", ncore, nlm_threads_per_core, num_cpus); + + /* switch NMI handler to boot CPUs */ nlm_set_nmi_handler(nlm_boot_secondary_cpus); } diff --git a/arch/mips/netlogic/dts/Makefile b/arch/mips/netlogic/dts/Makefile index d117d46413aa..aecb6fa9a9c3 100644 --- a/arch/mips/netlogic/dts/Makefile +++ b/arch/mips/netlogic/dts/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_DT_XLP_EVP) := xlp_evp.dtb.o +obj-$(CONFIG_DT_XLP_SVP) += xlp_svp.dtb.o diff --git a/arch/mips/netlogic/dts/xlp_evp.dts b/arch/mips/netlogic/dts/xlp_evp.dts index 7628b5464fc7..e14f42308064 100644 --- a/arch/mips/netlogic/dts/xlp_evp.dts +++ b/arch/mips/netlogic/dts/xlp_evp.dts @@ -20,7 +20,7 @@ #address-cells = <2>; #size-cells = <1>; compatible = "simple-bus"; - ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG + ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG 1 0 0 0x16000000 0x01000000>; // GBU chipselects serial0: serial@30000 { diff --git a/arch/mips/netlogic/dts/xlp_svp.dts b/arch/mips/netlogic/dts/xlp_svp.dts new file mode 100644 index 000000000000..8af4bdbe5d99 --- /dev/null +++ b/arch/mips/netlogic/dts/xlp_svp.dts @@ -0,0 +1,124 @@ +/* + * XLP3XX Device Tree Source for SVP boards + */ + +/dts-v1/; +/ { + model = "netlogic,XLP-SVP"; + compatible = "netlogic,xlp"; + #address-cells = <2>; + #size-cells = <2>; + + memory { + device_type = "memory"; + reg = <0 0x00100000 0 0x0FF00000 // 255M at 1M + 0 0x20000000 0 0xa0000000 // 2560M at 512M + 0 0xe0000000 0 0x40000000>; + }; + + soc { + #address-cells = <2>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0 0 0 0x18000000 0x04000000 // PCIe CFG + 1 0 0 0x16000000 0x01000000>; // GBU chipselects + + serial0: serial@30000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0 0x30100 0xa00>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <133333333>; + interrupt-parent = <&pic>; + interrupts = <17>; + }; + serial1: serial@31000 { + device_type = "serial"; + compatible = "ns16550"; + reg = <0 0x31100 0xa00>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <133333333>; + interrupt-parent = <&pic>; + interrupts = <18>; + }; + i2c0: ocores@32000 { + compatible = "opencores,i2c-ocores"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0 0x32100 0xa00>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <32000000>; + interrupt-parent = <&pic>; + interrupts = <30>; + }; + i2c1: ocores@33000 { + compatible = "opencores,i2c-ocores"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0 0x33100 0xa00>; + reg-shift = <2>; + reg-io-width = <4>; + clock-frequency = <32000000>; + interrupt-parent = <&pic>; + interrupts = <31>; + + rtc@68 { + compatible = "dallas,ds1374"; + reg = <0x68>; + }; + + dtt@4c { + compatible = "national,lm90"; + reg = <0x4c>; + }; + }; + pic: pic@4000 { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + reg = <0 0x4000 0x200>; + }; + + nor_flash@1,0 { + compatible = "cfi-flash"; + #address-cells = <1>; + #size-cells = <1>; + bank-width = <2>; + reg = <1 0 0x1000000>; + + partition@0 { + label = "x-loader"; + reg = <0x0 0x100000>; /* 1M */ + read-only; + }; + + partition@100000 { + label = "u-boot"; + reg = <0x100000 0x100000>; /* 1M */ + }; + + partition@200000 { + label = "kernel"; + reg = <0x200000 0x500000>; /* 5M */ + }; + + partition@700000 { + label = "rootfs"; + reg = <0x700000 0x800000>; /* 8M */ + }; + + partition@f00000 { + label = "env"; + reg = <0xf00000 0x100000>; /* 1M */ + read-only; + }; + }; + }; + + chosen { + bootargs = "console=ttyS0,115200 rdinit=/sbin/init"; + }; +}; diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index c68fd4026104..87560e4db35f 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -61,43 +61,61 @@ void nlm_node_init(int node) int nlm_irq_to_irt(int irq) { - if (!PIC_IRQ_IS_IRT(irq)) - return -1; + uint64_t pcibase; + int devoff, irt; switch (irq) { case PIC_UART_0_IRQ: - return PIC_IRT_UART_0_INDEX; + devoff = XLP_IO_UART0_OFFSET(0); + break; case PIC_UART_1_IRQ: - return PIC_IRT_UART_1_INDEX; - case PIC_PCIE_LINK_0_IRQ: - return PIC_IRT_PCIE_LINK_0_INDEX; - case PIC_PCIE_LINK_1_IRQ: - return PIC_IRT_PCIE_LINK_1_INDEX; - case PIC_PCIE_LINK_2_IRQ: - return PIC_IRT_PCIE_LINK_2_INDEX; - case PIC_PCIE_LINK_3_IRQ: - return PIC_IRT_PCIE_LINK_3_INDEX; + devoff = XLP_IO_UART1_OFFSET(0); + break; case PIC_EHCI_0_IRQ: - return PIC_IRT_EHCI_0_INDEX; + devoff = XLP_IO_USB_EHCI0_OFFSET(0); + break; case PIC_EHCI_1_IRQ: - return PIC_IRT_EHCI_1_INDEX; + devoff = XLP_IO_USB_EHCI1_OFFSET(0); + break; case PIC_OHCI_0_IRQ: - return PIC_IRT_OHCI_0_INDEX; + devoff = XLP_IO_USB_OHCI0_OFFSET(0); + break; case PIC_OHCI_1_IRQ: - return PIC_IRT_OHCI_1_INDEX; + devoff = XLP_IO_USB_OHCI1_OFFSET(0); + break; case PIC_OHCI_2_IRQ: - return PIC_IRT_OHCI_2_INDEX; + devoff = XLP_IO_USB_OHCI2_OFFSET(0); + break; case PIC_OHCI_3_IRQ: - return PIC_IRT_OHCI_3_INDEX; + devoff = XLP_IO_USB_OHCI3_OFFSET(0); + break; case PIC_MMC_IRQ: - return PIC_IRT_MMC_INDEX; + devoff = XLP_IO_SD_OFFSET(0); + break; case PIC_I2C_0_IRQ: - return PIC_IRT_I2C_0_INDEX; + devoff = XLP_IO_I2C0_OFFSET(0); + break; case PIC_I2C_1_IRQ: - return PIC_IRT_I2C_1_INDEX; + devoff = XLP_IO_I2C1_OFFSET(0); + break; default: - return -1; + devoff = 0; + break; } + + if (devoff != 0) { + pcibase = nlm_pcicfg_base(devoff); + irt = nlm_read_reg(pcibase, XLP_PCI_IRTINFO_REG) & 0xffff; + /* HW bug, I2C 1 irt entry is off by one */ + if (irq == PIC_I2C_1_IRQ) + irt = irt + 1; + } else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) { + /* HW bug, PCI IRT entries are bad on early silicon, fix */ + irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ); + } else { + irt = -1; + } + return irt; } unsigned int nlm_get_core_frequency(int node, int core) diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 4894d62043ac..af319143b591 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -56,7 +56,7 @@ uint64_t nlm_io_base; struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; cpumask_t nlm_cpumask = CPU_MASK_CPU0; unsigned int nlm_threads_per_core; -extern u32 __dtb_start[]; +extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_start[]; static void nlm_linux_exit(void) { @@ -82,8 +82,24 @@ void __init plat_mem_setup(void) * 64-bit, so convert pointer. */ fdtp = (void *)(long)fw_arg0; - if (!fdtp) - fdtp = __dtb_start; + if (!fdtp) { + switch (current_cpu_data.processor_id & 0xff00) { +#ifdef CONFIG_DT_XLP_SVP + case PRID_IMP_NETLOGIC_XLP3XX: + fdtp = __dtb_xlp_svp_begin; + break; +#endif +#ifdef CONFIG_DT_XLP_EVP + case PRID_IMP_NETLOGIC_XLP8XX: + fdtp = __dtb_xlp_evp_begin; + break; +#endif + default: + /* Pick a built-in if any, and hope for the best */ + fdtp = __dtb_start; + break; + } + } fdtp = phys_to_virt(__pa(fdtp)); early_init_devtree(fdtp); } diff --git a/arch/mips/netlogic/xlp/usb-init.c b/arch/mips/netlogic/xlp/usb-init.c index 1d0b66c62fd1..9c401dd78337 100644 --- a/arch/mips/netlogic/xlp/usb-init.c +++ b/arch/mips/netlogic/xlp/usb-init.c @@ -42,7 +42,30 @@ #include <asm/netlogic/haldefs.h> #include <asm/netlogic/xlp-hal/iomap.h> #include <asm/netlogic/xlp-hal/xlp.h> -#include <asm/netlogic/xlp-hal/usb.h> + +/* + * USB glue logic registers, used only during initialization + */ +#define USB_CTL_0 0x01 +#define USB_PHY_0 0x0A +#define USB_PHY_RESET 0x01 +#define USB_PHY_PORT_RESET_0 0x10 +#define USB_PHY_PORT_RESET_1 0x20 +#define USB_CONTROLLER_RESET 0x01 +#define USB_INT_STATUS 0x0E +#define USB_INT_EN 0x0F +#define USB_PHY_INTERRUPT_EN 0x01 +#define USB_OHCI_INTERRUPT_EN 0x02 +#define USB_OHCI_INTERRUPT1_EN 0x04 +#define USB_OHCI_INTERRUPT2_EN 0x08 +#define USB_CTRL_INTERRUPT_EN 0x10 + +#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r) +#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) +#define nlm_get_usb_pcibase(node, inst) \ + nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst)) +#define nlm_get_usb_regbase(node, inst) \ + (nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) static void nlm_usb_intr_en(int node, int port) { @@ -99,23 +122,23 @@ static void nlm_usb_fixup_final(struct pci_dev *dev) dev->dev.coherent_dma_mask = DMA_BIT_MASK(64); switch (dev->devfn) { case 0x10: - dev->irq = PIC_EHCI_0_IRQ; - break; + dev->irq = PIC_EHCI_0_IRQ; + break; case 0x11: - dev->irq = PIC_OHCI_0_IRQ; - break; + dev->irq = PIC_OHCI_0_IRQ; + break; case 0x12: - dev->irq = PIC_OHCI_1_IRQ; - break; + dev->irq = PIC_OHCI_1_IRQ; + break; case 0x13: - dev->irq = PIC_EHCI_1_IRQ; - break; + dev->irq = PIC_EHCI_1_IRQ; + break; case 0x14: - dev->irq = PIC_OHCI_2_IRQ; - break; + dev->irq = PIC_OHCI_2_IRQ; + break; case 0x15: - dev->irq = PIC_OHCI_3_IRQ; - break; + dev->irq = PIC_OHCI_3_IRQ; + break; } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI, diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 1fd361462c03..e4b1140cdae0 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -41,7 +41,7 @@ static int (*save_perf_irq)(void); * first hardware thread in the core for setup and init. * Skip CPUs with non-zero hardware thread id (4 hwt per core) */ -#ifdef CONFIG_CPU_XLR +#if defined(CONFIG_CPU_XLR) && defined(CONFIG_SMP) #define oprofile_skip_cpu(c) ((cpu_logical_map(c) & 0x3) != 0) #else #define oprofile_skip_cpu(c) 0 diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c index 412ec025cf55..18517dd0f709 100644 --- a/arch/mips/pci/pci-ar71xx.c +++ b/arch/mips/pci/pci-ar71xx.c @@ -366,9 +366,9 @@ static int ar71xx_pci_probe(struct platform_device *pdev) if (!res) return -EINVAL; - apc->cfg_base = devm_request_and_ioremap(&pdev->dev, res); - if (!apc->cfg_base) - return -ENOMEM; + apc->cfg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->cfg_base)) + return PTR_ERR(apc->cfg_base); apc->irq = platform_get_irq(pdev, 0); if (apc->irq < 0) diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 8a0700d448fe..65ec032fa0b4 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -365,25 +365,25 @@ static int ar724x_pci_probe(struct platform_device *pdev) if (!res) return -EINVAL; - apc->ctrl_base = devm_request_and_ioremap(&pdev->dev, res); - if (apc->ctrl_base == NULL) - return -EBUSY; + apc->ctrl_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->ctrl_base)) + return PTR_ERR(apc->ctrl_base); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); if (!res) return -EINVAL; - apc->devcfg_base = devm_request_and_ioremap(&pdev->dev, res); - if (!apc->devcfg_base) - return -EBUSY; + apc->devcfg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->devcfg_base)) + return PTR_ERR(apc->devcfg_base); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base"); if (!res) return -EINVAL; - apc->crp_base = devm_request_and_ioremap(&pdev->dev, res); - if (apc->crp_base == NULL) - return -EBUSY; + apc->crp_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->crp_base)) + return PTR_ERR(apc->crp_base); apc->irq = platform_get_irq(pdev, 0); if (apc->irq < 0) diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c index 88e781c6b5ba..2eb954239bc5 100644 --- a/arch/mips/pci/pci-bcm63xx.c +++ b/arch/mips/pci/pci-bcm63xx.c @@ -121,11 +121,17 @@ void __iomem *pci_iospace_start; static void __init bcm63xx_reset_pcie(void) { u32 val; + u32 reg; /* enable SERDES */ - val = bcm_misc_readl(MISC_SERDES_CTRL_REG); + if (BCMCPU_IS_6328()) + reg = MISC_SERDES_CTRL_6328_REG; + else + reg = MISC_SERDES_CTRL_6362_REG; + + val = bcm_misc_readl(reg); val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN; - bcm_misc_writel(val, MISC_SERDES_CTRL_REG); + bcm_misc_writel(val, reg); /* reset the PCIe core */ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1); @@ -330,6 +336,7 @@ static int __init bcm63xx_pci_init(void) switch (bcm63xx_get_cpu_id()) { case BCM6328_CPU_ID: + case BCM6362_CPU_ID: return bcm63xx_register_pcie(); case BCM6348_CPU_ID: case BCM6358_CPU_ID: diff --git a/arch/mips/pmcs-msp71xx/msp_prom.c b/arch/mips/pmcs-msp71xx/msp_prom.c index 0edb89a63516..1c9897531660 100644 --- a/arch/mips/pmcs-msp71xx/msp_prom.c +++ b/arch/mips/pmcs-msp71xx/msp_prom.c @@ -83,7 +83,7 @@ static inline unsigned char str2hexnum(unsigned char c) return 0; /* foo */ } -static inline int str2eaddr(unsigned char *ea, unsigned char *str) +int str2eaddr(unsigned char *ea, unsigned char *str) { int index = 0; unsigned char num = 0; diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c index 5bd9d8f468cc..a01baff52cae 100644 --- a/arch/mips/powertv/init.c +++ b/arch/mips/powertv/init.c @@ -29,10 +29,11 @@ #include <asm/cacheflush.h> #include <asm/traps.h> -#include <asm/mips-boards/prom.h> #include <asm/mips-boards/generic.h> #include <asm/mach-powertv/asic.h> +#include "init.h" + static int *_prom_envp; unsigned long _prom_memsize; diff --git a/arch/mips/powertv/init.h b/arch/mips/powertv/init.h index b194c34ca966..c1a8bd0dbe4b 100644 --- a/arch/mips/powertv/init.h +++ b/arch/mips/powertv/init.h @@ -23,4 +23,6 @@ #ifndef _POWERTV_INIT_H #define _POWERTV_INIT_H extern unsigned long _prom_memsize; +extern void prom_meminit(void); +extern char *prom_getenv(char *name); #endif diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c index 6e5f1bdc59b5..bc2f3ca22b41 100644 --- a/arch/mips/powertv/memory.c +++ b/arch/mips/powertv/memory.c @@ -29,7 +29,6 @@ #include <asm/page.h> #include <asm/sections.h> -#include <asm/mips-boards/prom.h> #include <asm/mach-powertv/asic.h> #include <asm/mach-powertv/ioremap.h> diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c index 820b8480f222..24689bff1039 100644 --- a/arch/mips/powertv/powertv_setup.c +++ b/arch/mips/powertv/powertv_setup.c @@ -31,7 +31,6 @@ #include <asm/bootinfo.h> #include <asm/irq.h> #include <asm/mips-boards/generic.h> -#include <asm/mips-boards/prom.h> #include <asm/dma.h> #include <asm/asm.h> #include <asm/traps.h> diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig index a0b0197cab0a..026e823d871d 100644 --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig @@ -6,12 +6,23 @@ choice help Select Ralink MIPS SoC type. + config SOC_RT288X + bool "RT288x" + config SOC_RT305X bool "RT305x" select USB_ARCH_HAS_HCD select USB_ARCH_HAS_OHCI select USB_ARCH_HAS_EHCI + config SOC_RT3883 + bool "RT3883" + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI + + config SOC_MT7620 + bool "MT7620" + endchoice choice @@ -23,10 +34,22 @@ choice config DTB_RT_NONE bool "None" + config DTB_RT2880_EVAL + bool "RT2880 eval kit" + depends on SOC_RT288X + config DTB_RT305X_EVAL bool "RT305x eval kit" depends on SOC_RT305X + config DTB_RT3883_EVAL + bool "RT3883 eval kit" + depends on SOC_RT3883 + + config DTB_MT7620A_EVAL + bool "MT7620A eval kit" + depends on SOC_MT7620 + endchoice endif diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile index 939757f0e71f..38cf1a880aaa 100644 --- a/arch/mips/ralink/Makefile +++ b/arch/mips/ralink/Makefile @@ -8,7 +8,10 @@ obj-y := prom.o of.o reset.o clk.o irq.o +obj-$(CONFIG_SOC_RT288X) += rt288x.o obj-$(CONFIG_SOC_RT305X) += rt305x.o +obj-$(CONFIG_SOC_RT3883) += rt3883.o +obj-$(CONFIG_SOC_MT7620) += mt7620.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform index 6babd65765e6..cda4b6645c50 100644 --- a/arch/mips/ralink/Platform +++ b/arch/mips/ralink/Platform @@ -5,6 +5,24 @@ core-$(CONFIG_RALINK) += arch/mips/ralink/ cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink # +# Ralink RT288x +# +load-$(CONFIG_SOC_RT288X) += 0xffffffff88000000 +cflags-$(CONFIG_SOC_RT288X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt288x + +# # Ralink RT305x # load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000 +cflags-$(CONFIG_SOC_RT305X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt305x + +# +# Ralink RT3883 +# +load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000 +cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt3883 + +# +# Ralink MT7620 +# +load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000 diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h index 300990313e1b..83144c3fc5ac 100644 --- a/arch/mips/ralink/common.h +++ b/arch/mips/ralink/common.h @@ -22,13 +22,22 @@ struct ralink_pinmux { struct ralink_pinmux_grp *mode; struct ralink_pinmux_grp *uart; int uart_shift; + u32 uart_mask; void (*wdt_reset)(void); + struct ralink_pinmux_grp *pci; + int pci_shift; + u32 pci_mask; }; -extern struct ralink_pinmux gpio_pinmux; +extern struct ralink_pinmux rt_gpio_pinmux; struct ralink_soc_info { unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; unsigned char *compatible; + + unsigned long mem_base; + unsigned long mem_size; + unsigned long mem_size_min; + unsigned long mem_size_max; }; extern struct ralink_soc_info soc_info; diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile index 1a69fb300955..18194fa93e80 100644 --- a/arch/mips/ralink/dts/Makefile +++ b/arch/mips/ralink/dts/Makefile @@ -1 +1,4 @@ +obj-$(CONFIG_DTB_RT2880_EVAL) := rt2880_eval.dtb.o obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o +obj-$(CONFIG_DTB_RT3883_EVAL) := rt3883_eval.dtb.o +obj-$(CONFIG_DTB_MT7620A_EVAL) := mt7620a_eval.dtb.o diff --git a/arch/mips/ralink/dts/mt7620a.dtsi b/arch/mips/ralink/dts/mt7620a.dtsi new file mode 100644 index 000000000000..08bf24fefe9f --- /dev/null +++ b/arch/mips/ralink/dts/mt7620a.dtsi @@ -0,0 +1,58 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,mtk7620a-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,mt7620a-sysc"; + reg = <0x0 0x100>; + }; + + intc: intc@200 { + compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + }; + + uartlite@c00 { + compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + }; + }; +}; diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts new file mode 100644 index 000000000000..35eb874ab7f1 --- /dev/null +++ b/arch/mips/ralink/dts/mt7620a_eval.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; + model = "Ralink MT7620A evaluation board"; + + memory@0 { + reg = <0x0 0x2000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; +}; diff --git a/arch/mips/ralink/dts/rt2880.dtsi b/arch/mips/ralink/dts/rt2880.dtsi new file mode 100644 index 000000000000..182afde2f2e1 --- /dev/null +++ b/arch/mips/ralink/dts/rt2880.dtsi @@ -0,0 +1,58 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,rt2880-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips4KEc"; + }; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@300000 { + compatible = "palmbus"; + reg = <0x300000 0x200000>; + ranges = <0x0 0x300000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,rt2880-sysc"; + reg = <0x0 0x100>; + }; + + intc: intc@200 { + compatible = "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,rt2880-memc"; + reg = <0x300 0x100>; + }; + + uartlite@c00 { + compatible = "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + interrupt-parent = <&intc>; + interrupts = <8>; + + reg-shift = <2>; + }; + }; +}; diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts new file mode 100644 index 000000000000..322d7002595b --- /dev/null +++ b/arch/mips/ralink/dts/rt2880_eval.dts @@ -0,0 +1,46 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + compatible = "ralink,rt2880-eval-board", "ralink,rt2880-soc"; + model = "Ralink RT2880 evaluation board"; + + memory@0 { + reg = <0x8000000 0x2000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x400000>; + + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + partition@40000 { + label = "calibration"; + reg = <0x40000 0x10000>; + read-only; + }; + partition@50000 { + label = "linux"; + reg = <0x50000 0x3b0000>; + }; + }; +}; diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi index 069d0660e1dd..e3203d414fee 100644 --- a/arch/mips/ralink/dts/rt3050.dtsi +++ b/arch/mips/ralink/dts/rt3050.dtsi @@ -1,7 +1,7 @@ / { #address-cells = <1>; #size-cells = <1>; - compatible = "ralink,rt3050-soc", "ralink,rt3052-soc"; + compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc"; cpus { cpu@0 { @@ -9,10 +9,6 @@ }; }; - chosen { - bootargs = "console=ttyS0,57600 init=/init"; - }; - cpuintc: cpuintc@0 { #address-cells = <0>; #interrupt-cells = <1>; @@ -23,7 +19,7 @@ palmbus@10000000 { compatible = "palmbus"; reg = <0x10000000 0x200000>; - ranges = <0x0 0x10000000 0x1FFFFF>; + ranges = <0x0 0x10000000 0x1FFFFF>; #address-cells = <1>; #size-cells = <1>; @@ -33,11 +29,6 @@ reg = <0x0 0x100>; }; - timer@100 { - compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt"; - reg = <0x100 0x100>; - }; - intc: intc@200 { compatible = "ralink,rt3052-intc", "ralink,rt2880-intc"; reg = <0x200 0x100>; @@ -54,45 +45,6 @@ reg = <0x300 0x100>; }; - gpio0: gpio@600 { - compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; - reg = <0x600 0x34>; - - gpio-controller; - #gpio-cells = <2>; - - ralink,ngpio = <24>; - ralink,regs = [ 00 04 08 0c - 20 24 28 2c - 30 34 ]; - }; - - gpio1: gpio@638 { - compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; - reg = <0x638 0x24>; - - gpio-controller; - #gpio-cells = <2>; - - ralink,ngpio = <16>; - ralink,regs = [ 00 04 08 0c - 10 14 18 1c - 20 24 ]; - }; - - gpio2: gpio@660 { - compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio"; - reg = <0x660 0x24>; - - gpio-controller; - #gpio-cells = <2>; - - ralink,ngpio = <12>; - ralink,regs = [ 00 04 08 0c - 10 14 18 1c - 20 24 ]; - }; - uartlite@c00 { compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a"; reg = <0xc00 0x100>; @@ -103,4 +55,14 @@ reg-shift = <2>; }; }; + + usb@101c0000 { + compatible = "ralink,rt3050-usb", "snps,dwc2"; + reg = <0x101c0000 40000>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + status = "disabled"; + }; }; diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts index 148a590bc419..0ac73ea28198 100644 --- a/arch/mips/ralink/dts/rt3052_eval.dts +++ b/arch/mips/ralink/dts/rt3052_eval.dts @@ -1,10 +1,8 @@ /dts-v1/; -/include/ "rt3050.dtsi" +#include "rt3050.dtsi" / { - #address-cells = <1>; - #size-cells = <1>; compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc"; model = "Ralink RT3052 evaluation board"; @@ -12,12 +10,8 @@ reg = <0x0 0x2000000>; }; - palmbus@10000000 { - sysc@0 { - ralink,pinmmux = "uartlite", "spi"; - ralink,uartmux = "gpio"; - ralink,wdtmux = <0>; - }; + chosen { + bootargs = "console=ttyS0,57600"; }; cfi@1f000000 { @@ -49,4 +43,8 @@ reg = <0x50000 0x7b0000>; }; }; + + usb@101c0000 { + status = "ok"; + }; }; diff --git a/arch/mips/ralink/dts/rt3883.dtsi b/arch/mips/ralink/dts/rt3883.dtsi new file mode 100644 index 000000000000..3b131dd0d5ac --- /dev/null +++ b/arch/mips/ralink/dts/rt3883.dtsi @@ -0,0 +1,58 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,rt3883-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips74Kc"; + }; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + + intc: intc@200 { + compatible = "ralink,rt3883-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,rt3883-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + }; + + uartlite@c00 { + compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + }; + }; +}; diff --git a/arch/mips/ralink/dts/rt3883_eval.dts b/arch/mips/ralink/dts/rt3883_eval.dts new file mode 100644 index 000000000000..2fa6b330bf4f --- /dev/null +++ b/arch/mips/ralink/dts/rt3883_eval.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "ralink,rt3883-eval-board", "ralink,rt3883-soc"; + model = "Ralink RT3883 evaluation board"; + + memory@0 { + reg = <0x0 0x2000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; +}; diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c index c4ae47eb24ab..b46d0419d09b 100644 --- a/arch/mips/ralink/early_printk.c +++ b/arch/mips/ralink/early_printk.c @@ -11,7 +11,11 @@ #include <asm/addrspace.h> +#ifdef CONFIG_SOC_RT288X +#define EARLY_UART_BASE 0x300c00 +#else #define EARLY_UART_BASE 0x10000c00 +#endif #define UART_REG_RX 0x00 #define UART_REG_TX 0x04 diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c index 6d054c5ec9ab..320b1f1043ff 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c @@ -31,6 +31,7 @@ #define INTC_INT_GLOBAL BIT(31) #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2) +#define RALINK_CPU_IRQ_PCI (MIPS_CPU_IRQ_BASE + 4) #define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5) #define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6) #define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7) @@ -104,6 +105,9 @@ asmlinkage void plat_irq_dispatch(void) else if (pending & STATUSF_IP6) do_IRQ(RALINK_CPU_IRQ_WIFI); + else if (pending & STATUSF_IP4) + do_IRQ(RALINK_CPU_IRQ_PCI); + else if (pending & STATUSF_IP2) do_IRQ(RALINK_CPU_IRQ_INTC); @@ -162,6 +166,7 @@ static int __init intc_of_init(struct device_node *node, irq_set_chained_handler(irq, ralink_intc_irq_handler); irq_set_handler_data(irq, domain); + /* tell the kernel which irq is used for performance monitoring */ cp0_perfcount_irq = irq_create_mapping(domain, 9); return 0; diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c new file mode 100644 index 000000000000..0018b1a661f6 --- /dev/null +++ b/arch/mips/ralink/mt7620.c @@ -0,0 +1,234 @@ +/* + * 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. + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> + +#include <asm/mipsregs.h> +#include <asm/mach-ralink/ralink_regs.h> +#include <asm/mach-ralink/mt7620.h> + +#include "common.h" + +/* does the board have sdram or ddram */ +static int dram_type; + +/* the pll dividers */ +static u32 mt7620_clk_divider[] = { 2, 3, 4, 8 }; + +static struct ralink_pinmux_grp mode_mux[] = { + { + .name = "i2c", + .mask = MT7620_GPIO_MODE_I2C, + .gpio_first = 1, + .gpio_last = 2, + }, { + .name = "spi", + .mask = MT7620_GPIO_MODE_SPI, + .gpio_first = 3, + .gpio_last = 6, + }, { + .name = "uartlite", + .mask = MT7620_GPIO_MODE_UART1, + .gpio_first = 15, + .gpio_last = 16, + }, { + .name = "wdt", + .mask = MT7620_GPIO_MODE_WDT, + .gpio_first = 17, + .gpio_last = 17, + }, { + .name = "mdio", + .mask = MT7620_GPIO_MODE_MDIO, + .gpio_first = 22, + .gpio_last = 23, + }, { + .name = "rgmii1", + .mask = MT7620_GPIO_MODE_RGMII1, + .gpio_first = 24, + .gpio_last = 35, + }, { + .name = "spi refclk", + .mask = MT7620_GPIO_MODE_SPI_REF_CLK, + .gpio_first = 37, + .gpio_last = 39, + }, { + .name = "jtag", + .mask = MT7620_GPIO_MODE_JTAG, + .gpio_first = 40, + .gpio_last = 44, + }, { + /* shared lines with jtag */ + .name = "ephy", + .mask = MT7620_GPIO_MODE_EPHY, + .gpio_first = 40, + .gpio_last = 44, + }, { + .name = "nand", + .mask = MT7620_GPIO_MODE_JTAG, + .gpio_first = 45, + .gpio_last = 59, + }, { + .name = "rgmii2", + .mask = MT7620_GPIO_MODE_RGMII2, + .gpio_first = 60, + .gpio_last = 71, + }, { + .name = "wled", + .mask = MT7620_GPIO_MODE_WLED, + .gpio_first = 72, + .gpio_last = 72, + }, {0} +}; + +static struct ralink_pinmux_grp uart_mux[] = { + { + .name = "uartf", + .mask = MT7620_GPIO_MODE_UARTF, + .gpio_first = 7, + .gpio_last = 14, + }, { + .name = "pcm uartf", + .mask = MT7620_GPIO_MODE_PCM_UARTF, + .gpio_first = 7, + .gpio_last = 14, + }, { + .name = "pcm i2s", + .mask = MT7620_GPIO_MODE_PCM_I2S, + .gpio_first = 7, + .gpio_last = 14, + }, { + .name = "i2s uartf", + .mask = MT7620_GPIO_MODE_I2S_UARTF, + .gpio_first = 7, + .gpio_last = 14, + }, { + .name = "pcm gpio", + .mask = MT7620_GPIO_MODE_PCM_GPIO, + .gpio_first = 11, + .gpio_last = 14, + }, { + .name = "gpio uartf", + .mask = MT7620_GPIO_MODE_GPIO_UARTF, + .gpio_first = 7, + .gpio_last = 10, + }, { + .name = "gpio i2s", + .mask = MT7620_GPIO_MODE_GPIO_I2S, + .gpio_first = 7, + .gpio_last = 10, + }, { + .name = "gpio", + .mask = MT7620_GPIO_MODE_GPIO, + }, {0} +}; + +struct ralink_pinmux rt_gpio_pinmux = { + .mode = mode_mux, + .uart = uart_mux, + .uart_shift = MT7620_GPIO_MODE_UART0_SHIFT, + .uart_mask = MT7620_GPIO_MODE_UART0_MASK, +}; + +void __init ralink_clk_init(void) +{ + unsigned long cpu_rate, sys_rate; + u32 c0 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG0); + u32 c1 = rt_sysc_r32(SYSC_REG_CPLL_CONFIG1); + u32 swconfig = (c0 >> CPLL_SW_CONFIG_SHIFT) & CPLL_SW_CONFIG_MASK; + u32 cpu_clk = (c1 >> CPLL_CPU_CLK_SHIFT) & CPLL_CPU_CLK_MASK; + + if (cpu_clk) { + cpu_rate = 480000000; + } else if (!swconfig) { + cpu_rate = 600000000; + } else { + u32 m = (c0 >> CPLL_MULT_RATIO_SHIFT) & CPLL_MULT_RATIO; + u32 d = (c0 >> CPLL_DIV_RATIO_SHIFT) & CPLL_DIV_RATIO; + + cpu_rate = ((40 * (m + 24)) / mt7620_clk_divider[d]) * 1000000; + } + + if (dram_type == SYSCFG0_DRAM_TYPE_SDRAM) + sys_rate = cpu_rate / 4; + else + sys_rate = cpu_rate / 3; + + ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("10000100.timer", 40000000); + ralink_clk_add("10000500.uart", 40000000); + ralink_clk_add("10000c00.uartlite", 40000000); +} + +void __init ralink_of_remap(void) +{ + rt_sysc_membase = plat_of_remap_node("ralink,mt7620a-sysc"); + rt_memc_membase = plat_of_remap_node("ralink,mt7620a-memc"); + + if (!rt_sysc_membase || !rt_memc_membase) + panic("Failed to remap core resources"); +} + +void prom_soc_init(struct ralink_soc_info *soc_info) +{ + void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE); + unsigned char *name = NULL; + u32 n0; + u32 n1; + u32 rev; + u32 cfg0; + + n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); + n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); + + if (n0 == MT7620N_CHIP_NAME0 && n1 == MT7620N_CHIP_NAME1) { + name = "MT7620N"; + soc_info->compatible = "ralink,mt7620n-soc"; + } else if (n0 == MT7620A_CHIP_NAME0 && n1 == MT7620A_CHIP_NAME1) { + name = "MT7620A"; + soc_info->compatible = "ralink,mt7620a-soc"; + } else { + panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1); + } + + rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, + "Ralink %s ver:%u eco:%u", + name, + (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, + (rev & CHIP_REV_ECO_MASK)); + + cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); + dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + + switch (dram_type) { + case SYSCFG0_DRAM_TYPE_SDRAM: + soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; + soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; + break; + + case SYSCFG0_DRAM_TYPE_DDR1: + soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; + soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; + break; + + case SYSCFG0_DRAM_TYPE_DDR2: + soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; + soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; + break; + default: + BUG(); + } + soc_info->mem_base = MT7620_DRAM_BASE; +} diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index 4165e70775be..fb1569580def 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -11,6 +11,7 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/init.h> +#include <linux/sizes.h> #include <linux/of_fdt.h> #include <linux/kernel.h> #include <linux/bootmem.h> @@ -85,6 +86,14 @@ void __init plat_mem_setup(void) * parsed resulting in our memory appearing */ __dt_setup_arch(&__dtb_start); + + if (soc_info.mem_size) + add_memory_region(soc_info.mem_base, soc_info.mem_size, + BOOT_MEM_RAM); + else + detect_memory_region(soc_info.mem_base, + soc_info.mem_size_min * SZ_1M, + soc_info.mem_size_max * SZ_1M); } static int __init plat_of_setup(void) diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c new file mode 100644 index 000000000000..f87de1ab2198 --- /dev/null +++ b/arch/mips/ralink/rt288x.c @@ -0,0 +1,143 @@ +/* + * 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. + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> + +#include <asm/mipsregs.h> +#include <asm/mach-ralink/ralink_regs.h> +#include <asm/mach-ralink/rt288x.h> + +#include "common.h" + +static struct ralink_pinmux_grp mode_mux[] = { + { + .name = "i2c", + .mask = RT2880_GPIO_MODE_I2C, + .gpio_first = 1, + .gpio_last = 2, + }, { + .name = "spi", + .mask = RT2880_GPIO_MODE_SPI, + .gpio_first = 3, + .gpio_last = 6, + }, { + .name = "uartlite", + .mask = RT2880_GPIO_MODE_UART0, + .gpio_first = 7, + .gpio_last = 14, + }, { + .name = "jtag", + .mask = RT2880_GPIO_MODE_JTAG, + .gpio_first = 17, + .gpio_last = 21, + }, { + .name = "mdio", + .mask = RT2880_GPIO_MODE_MDIO, + .gpio_first = 22, + .gpio_last = 23, + }, { + .name = "sdram", + .mask = RT2880_GPIO_MODE_SDRAM, + .gpio_first = 24, + .gpio_last = 39, + }, { + .name = "pci", + .mask = RT2880_GPIO_MODE_PCI, + .gpio_first = 40, + .gpio_last = 71, + }, {0} +}; + +static void rt288x_wdt_reset(void) +{ + u32 t; + + /* enable WDT reset output on pin SRAM_CS_N */ + t = rt_sysc_r32(SYSC_REG_CLKCFG); + t |= CLKCFG_SRAM_CS_N_WDT; + rt_sysc_w32(t, SYSC_REG_CLKCFG); +} + +struct ralink_pinmux rt_gpio_pinmux = { + .mode = mode_mux, + .wdt_reset = rt288x_wdt_reset, +}; + +void __init ralink_clk_init(void) +{ + unsigned long cpu_rate; + u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); + t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); + + switch (t) { + case SYSTEM_CONFIG_CPUCLK_250: + cpu_rate = 250000000; + break; + case SYSTEM_CONFIG_CPUCLK_266: + cpu_rate = 266666667; + break; + case SYSTEM_CONFIG_CPUCLK_280: + cpu_rate = 280000000; + break; + case SYSTEM_CONFIG_CPUCLK_300: + cpu_rate = 300000000; + break; + } + + ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("300100.timer", cpu_rate / 2); + ralink_clk_add("300120.watchdog", cpu_rate / 2); + ralink_clk_add("300500.uart", cpu_rate / 2); + ralink_clk_add("300c00.uartlite", cpu_rate / 2); + ralink_clk_add("400000.ethernet", cpu_rate / 2); +} + +void __init ralink_of_remap(void) +{ + rt_sysc_membase = plat_of_remap_node("ralink,rt2880-sysc"); + rt_memc_membase = plat_of_remap_node("ralink,rt2880-memc"); + + if (!rt_sysc_membase || !rt_memc_membase) + panic("Failed to remap core resources"); +} + +void prom_soc_init(struct ralink_soc_info *soc_info) +{ + void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT2880_SYSC_BASE); + const char *name; + u32 n0; + u32 n1; + u32 id; + + n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); + n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); + id = __raw_readl(sysc + SYSC_REG_CHIP_ID); + + if (n0 == RT2880_CHIP_NAME0 && n1 == RT2880_CHIP_NAME1) { + soc_info->compatible = "ralink,r2880-soc"; + name = "RT2880"; + } else { + panic("rt288x: unknown SoC, n0:%08x n1:%08x", n0, n1); + } + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, + "Ralink %s id:%u rev:%u", + name, + (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, + (id & CHIP_ID_REV_MASK)); + + soc_info->mem_base = RT2880_SDRAM_BASE; + soc_info->mem_size_min = RT2880_MEM_SIZE_MIN; + soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; +} diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c index 0a4bbdcf59d9..ca7ee3a33790 100644 --- a/arch/mips/ralink/rt305x.c +++ b/arch/mips/ralink/rt305x.c @@ -22,7 +22,7 @@ enum rt305x_soc_type rt305x_soc; -struct ralink_pinmux_grp mode_mux[] = { +static struct ralink_pinmux_grp mode_mux[] = { { .name = "i2c", .mask = RT305X_GPIO_MODE_I2C, @@ -61,7 +61,7 @@ struct ralink_pinmux_grp mode_mux[] = { }, {0} }; -struct ralink_pinmux_grp uart_mux[] = { +static struct ralink_pinmux_grp uart_mux[] = { { .name = "uartf", .mask = RT305X_GPIO_MODE_UARTF, @@ -91,19 +91,19 @@ struct ralink_pinmux_grp uart_mux[] = { .name = "gpio uartf", .mask = RT305X_GPIO_MODE_GPIO_UARTF, .gpio_first = RT305X_GPIO_7, - .gpio_last = RT305X_GPIO_14, + .gpio_last = RT305X_GPIO_10, }, { .name = "gpio i2s", .mask = RT305X_GPIO_MODE_GPIO_I2S, .gpio_first = RT305X_GPIO_7, - .gpio_last = RT305X_GPIO_14, + .gpio_last = RT305X_GPIO_10, }, { .name = "gpio", .mask = RT305X_GPIO_MODE_GPIO, }, {0} }; -void rt305x_wdt_reset(void) +static void rt305x_wdt_reset(void) { u32 t; @@ -114,16 +114,53 @@ void rt305x_wdt_reset(void) rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG); } -struct ralink_pinmux gpio_pinmux = { +struct ralink_pinmux rt_gpio_pinmux = { .mode = mode_mux, .uart = uart_mux, .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, + .uart_mask = RT305X_GPIO_MODE_UART0_MASK, .wdt_reset = rt305x_wdt_reset, }; +static unsigned long rt5350_get_mem_size(void) +{ + void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); + unsigned long ret; + u32 t; + + t = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG); + t = (t >> RT5350_SYSCFG0_DRAM_SIZE_SHIFT) & + RT5350_SYSCFG0_DRAM_SIZE_MASK; + + switch (t) { + case RT5350_SYSCFG0_DRAM_SIZE_2M: + ret = 2; + break; + case RT5350_SYSCFG0_DRAM_SIZE_8M: + ret = 8; + break; + case RT5350_SYSCFG0_DRAM_SIZE_16M: + ret = 16; + break; + case RT5350_SYSCFG0_DRAM_SIZE_32M: + ret = 32; + break; + case RT5350_SYSCFG0_DRAM_SIZE_64M: + ret = 64; + break; + default: + panic("rt5350: invalid DRAM size: %u", t); + break; + } + + return ret; +} + void __init ralink_clk_init(void) { unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate; + unsigned long wmac_rate = 40000000; + u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); if (soc_is_rt305x() || soc_is_rt3350()) { @@ -176,11 +213,21 @@ void __init ralink_clk_init(void) BUG(); } + if (soc_is_rt3352() || soc_is_rt5350()) { + u32 val = rt_sysc_r32(RT3352_SYSC_REG_SYSCFG0); + + if (!(val & RT3352_CLKCFG0_XTAL_SEL)) + wmac_rate = 20000000; + } + ralink_clk_add("cpu", cpu_rate); ralink_clk_add("10000b00.spi", sys_rate); ralink_clk_add("10000100.timer", wdt_rate); + ralink_clk_add("10000120.watchdog", wdt_rate); ralink_clk_add("10000500.uart", uart_rate); ralink_clk_add("10000c00.uartlite", uart_rate); + ralink_clk_add("10100000.ethernet", sys_rate); + ralink_clk_add("10180000.wmac", wmac_rate); } void __init ralink_of_remap(void) @@ -239,4 +286,15 @@ void prom_soc_init(struct ralink_soc_info *soc_info) name, (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK, (id & CHIP_ID_REV_MASK)); + + soc_info->mem_base = RT305X_SDRAM_BASE; + if (soc_is_rt5350()) { + soc_info->mem_size = rt5350_get_mem_size(); + } else if (soc_is_rt305x() || soc_is_rt3350()) { + soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; + soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; + } else if (soc_is_rt3352()) { + soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; + soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; + } } diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c new file mode 100644 index 000000000000..b474ac284b83 --- /dev/null +++ b/arch/mips/ralink/rt3883.c @@ -0,0 +1,246 @@ +/* + * 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. + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> + +#include <asm/mipsregs.h> +#include <asm/mach-ralink/ralink_regs.h> +#include <asm/mach-ralink/rt3883.h> + +#include "common.h" + +static struct ralink_pinmux_grp mode_mux[] = { + { + .name = "i2c", + .mask = RT3883_GPIO_MODE_I2C, + .gpio_first = RT3883_GPIO_I2C_SD, + .gpio_last = RT3883_GPIO_I2C_SCLK, + }, { + .name = "spi", + .mask = RT3883_GPIO_MODE_SPI, + .gpio_first = RT3883_GPIO_SPI_CS0, + .gpio_last = RT3883_GPIO_SPI_MISO, + }, { + .name = "uartlite", + .mask = RT3883_GPIO_MODE_UART1, + .gpio_first = RT3883_GPIO_UART1_TXD, + .gpio_last = RT3883_GPIO_UART1_RXD, + }, { + .name = "jtag", + .mask = RT3883_GPIO_MODE_JTAG, + .gpio_first = RT3883_GPIO_JTAG_TDO, + .gpio_last = RT3883_GPIO_JTAG_TCLK, + }, { + .name = "mdio", + .mask = RT3883_GPIO_MODE_MDIO, + .gpio_first = RT3883_GPIO_MDIO_MDC, + .gpio_last = RT3883_GPIO_MDIO_MDIO, + }, { + .name = "ge1", + .mask = RT3883_GPIO_MODE_GE1, + .gpio_first = RT3883_GPIO_GE1_TXD0, + .gpio_last = RT3883_GPIO_GE1_RXCLK, + }, { + .name = "ge2", + .mask = RT3883_GPIO_MODE_GE2, + .gpio_first = RT3883_GPIO_GE2_TXD0, + .gpio_last = RT3883_GPIO_GE2_RXCLK, + }, { + .name = "pci", + .mask = RT3883_GPIO_MODE_PCI, + .gpio_first = RT3883_GPIO_PCI_AD0, + .gpio_last = RT3883_GPIO_PCI_AD31, + }, { + .name = "lna a", + .mask = RT3883_GPIO_MODE_LNA_A, + .gpio_first = RT3883_GPIO_LNA_PE_A0, + .gpio_last = RT3883_GPIO_LNA_PE_A2, + }, { + .name = "lna g", + .mask = RT3883_GPIO_MODE_LNA_G, + .gpio_first = RT3883_GPIO_LNA_PE_G0, + .gpio_last = RT3883_GPIO_LNA_PE_G2, + }, {0} +}; + +static struct ralink_pinmux_grp uart_mux[] = { + { + .name = "uartf", + .mask = RT3883_GPIO_MODE_UARTF, + .gpio_first = RT3883_GPIO_7, + .gpio_last = RT3883_GPIO_14, + }, { + .name = "pcm uartf", + .mask = RT3883_GPIO_MODE_PCM_UARTF, + .gpio_first = RT3883_GPIO_7, + .gpio_last = RT3883_GPIO_14, + }, { + .name = "pcm i2s", + .mask = RT3883_GPIO_MODE_PCM_I2S, + .gpio_first = RT3883_GPIO_7, + .gpio_last = RT3883_GPIO_14, + }, { + .name = "i2s uartf", + .mask = RT3883_GPIO_MODE_I2S_UARTF, + .gpio_first = RT3883_GPIO_7, + .gpio_last = RT3883_GPIO_14, + }, { + .name = "pcm gpio", + .mask = RT3883_GPIO_MODE_PCM_GPIO, + .gpio_first = RT3883_GPIO_11, + .gpio_last = RT3883_GPIO_14, + }, { + .name = "gpio uartf", + .mask = RT3883_GPIO_MODE_GPIO_UARTF, + .gpio_first = RT3883_GPIO_7, + .gpio_last = RT3883_GPIO_10, + }, { + .name = "gpio i2s", + .mask = RT3883_GPIO_MODE_GPIO_I2S, + .gpio_first = RT3883_GPIO_7, + .gpio_last = RT3883_GPIO_10, + }, { + .name = "gpio", + .mask = RT3883_GPIO_MODE_GPIO, + }, {0} +}; + +static struct ralink_pinmux_grp pci_mux[] = { + { + .name = "pci-dev", + .mask = 0, + .gpio_first = RT3883_GPIO_PCI_AD0, + .gpio_last = RT3883_GPIO_PCI_AD31, + }, { + .name = "pci-host2", + .mask = 1, + .gpio_first = RT3883_GPIO_PCI_AD0, + .gpio_last = RT3883_GPIO_PCI_AD31, + }, { + .name = "pci-host1", + .mask = 2, + .gpio_first = RT3883_GPIO_PCI_AD0, + .gpio_last = RT3883_GPIO_PCI_AD31, + }, { + .name = "pci-fnc", + .mask = 3, + .gpio_first = RT3883_GPIO_PCI_AD0, + .gpio_last = RT3883_GPIO_PCI_AD31, + }, { + .name = "pci-gpio", + .mask = 7, + .gpio_first = RT3883_GPIO_PCI_AD0, + .gpio_last = RT3883_GPIO_PCI_AD31, + }, {0} +}; + +static void rt3883_wdt_reset(void) +{ + u32 t; + + /* enable WDT reset output on GPIO 2 */ + t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); + t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT; + rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); +} + +struct ralink_pinmux rt_gpio_pinmux = { + .mode = mode_mux, + .uart = uart_mux, + .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT, + .uart_mask = RT3883_GPIO_MODE_UART0_MASK, + .wdt_reset = rt3883_wdt_reset, + .pci = pci_mux, + .pci_shift = RT3883_GPIO_MODE_PCI_SHIFT, + .pci_mask = RT3883_GPIO_MODE_PCI_MASK, +}; + +void __init ralink_clk_init(void) +{ + unsigned long cpu_rate, sys_rate; + u32 syscfg0; + u32 clksel; + u32 ddr2; + + syscfg0 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG0); + clksel = ((syscfg0 >> RT3883_SYSCFG0_CPUCLK_SHIFT) & + RT3883_SYSCFG0_CPUCLK_MASK); + ddr2 = syscfg0 & RT3883_SYSCFG0_DRAM_TYPE_DDR2; + + switch (clksel) { + case RT3883_SYSCFG0_CPUCLK_250: + cpu_rate = 250000000; + sys_rate = (ddr2) ? 125000000 : 83000000; + break; + case RT3883_SYSCFG0_CPUCLK_384: + cpu_rate = 384000000; + sys_rate = (ddr2) ? 128000000 : 96000000; + break; + case RT3883_SYSCFG0_CPUCLK_480: + cpu_rate = 480000000; + sys_rate = (ddr2) ? 160000000 : 120000000; + break; + case RT3883_SYSCFG0_CPUCLK_500: + cpu_rate = 500000000; + sys_rate = (ddr2) ? 166000000 : 125000000; + break; + } + + ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("10000100.timer", sys_rate); + ralink_clk_add("10000120.watchdog", sys_rate); + ralink_clk_add("10000500.uart", 40000000); + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000c00.uartlite", 40000000); + ralink_clk_add("10100000.ethernet", sys_rate); +} + +void __init ralink_of_remap(void) +{ + rt_sysc_membase = plat_of_remap_node("ralink,rt3883-sysc"); + rt_memc_membase = plat_of_remap_node("ralink,rt3883-memc"); + + if (!rt_sysc_membase || !rt_memc_membase) + panic("Failed to remap core resources"); +} + +void prom_soc_init(struct ralink_soc_info *soc_info) +{ + void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT3883_SYSC_BASE); + const char *name; + u32 n0; + u32 n1; + u32 id; + + n0 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID0_3); + n1 = __raw_readl(sysc + RT3883_SYSC_REG_CHIPID4_7); + id = __raw_readl(sysc + RT3883_SYSC_REG_REVID); + + if (n0 == RT3883_CHIP_NAME0 && n1 == RT3883_CHIP_NAME1) { + soc_info->compatible = "ralink,rt3883-soc"; + name = "RT3883"; + } else { + panic("rt3883: unknown SoC, n0:%08x n1:%08x", n0, n1); + } + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, + "Ralink %s ver:%u eco:%u", + name, + (id >> RT3883_REVID_VER_ID_SHIFT) & RT3883_REVID_VER_ID_MASK, + (id & RT3883_REVID_ECO_ID_MASK)); + + soc_info->mem_base = RT3883_SDRAM_BASE; + soc_info->mem_size_min = RT3883_MEM_SIZE_MIN; + soc_info->mem_size_max = RT3883_MEM_SIZE_MAX; +} diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c index 1d1919a44e88..7a53b1e28a93 100644 --- a/arch/mips/sgi-ip27/ip27-klnuma.c +++ b/arch/mips/sgi-ip27/ip27-klnuma.c @@ -114,7 +114,7 @@ void __init replicate_kernel_text() * data structures on the first couple of pages of the first slot of each * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). */ -pfn_t node_getfirstfree(cnodeid_t cnode) +unsigned long node_getfirstfree(cnodeid_t cnode) { unsigned long loadbase = REP_BASE; nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index 5f2bddb1860e..1230f56429d7 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -255,14 +255,14 @@ static void __init dump_topology(void) } } -static pfn_t __init slot_getbasepfn(cnodeid_t cnode, int slot) +static unsigned long __init slot_getbasepfn(cnodeid_t cnode, int slot) { nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); - return ((pfn_t)nasid << PFN_NASIDSHFT) | (slot << SLOT_PFNSHIFT); + return ((unsigned long)nasid << PFN_NASIDSHFT) | (slot << SLOT_PFNSHIFT); } -static pfn_t __init slot_psize_compute(cnodeid_t node, int slot) +static unsigned long __init slot_psize_compute(cnodeid_t node, int slot) { nasid_t nasid; lboard_t *brd; @@ -353,7 +353,7 @@ static void __init mlreset(void) static void __init szmem(void) { - pfn_t slot_psize, slot0sz = 0, nodebytes; /* Hack to detect problem configs */ + unsigned long slot_psize, slot0sz = 0, nodebytes; /* Hack to detect problem configs */ int slot; cnodeid_t node; @@ -390,10 +390,10 @@ static void __init szmem(void) static void __init node_mem_init(cnodeid_t node) { - pfn_t slot_firstpfn = slot_getbasepfn(node, 0); - pfn_t slot_freepfn = node_getfirstfree(node); + unsigned long slot_firstpfn = slot_getbasepfn(node, 0); + unsigned long slot_freepfn = node_getfirstfree(node); unsigned long bootmap_size; - pfn_t start_pfn, end_pfn; + unsigned long start_pfn, end_pfn; get_pfn_range_for_nid(node, &start_pfn, &end_pfn); @@ -467,7 +467,7 @@ void __init paging_init(void) pagetable_init(); for_each_online_node(node) { - pfn_t start_pfn, end_pfn; + unsigned long start_pfn, end_pfn; get_pfn_range_for_nid(node, &start_pfn, &end_pfn); diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index fff58ac176f3..2e21b761cb9c 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -69,7 +69,7 @@ static void rt_set_mode(enum clock_event_mode mode, /* Nothing to do ... */ } -int rt_timer_irq; +unsigned int rt_timer_irq; static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); static DEFINE_PER_CPU(char [11], hub_rt_name); diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 5524f2c7b05c..5364aabc2102 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -118,7 +118,7 @@ EXPORT_SYMBOL(clk_put); /* GPIO support */ -#ifdef CONFIG_GENERIC_GPIO +#ifdef CONFIG_GPIOLIB int gpio_to_irq(unsigned gpio) { return -EINVAL; diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 81b9ddbc9166..1072bfd18c50 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -44,9 +44,6 @@ config GENERIC_HWEIGHT config NO_IOPORT def_bool y -config GENERIC_GPIO - def_bool y - config TRACE_IRQFLAGS_SUPPORT def_bool y diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 433e75a2ee9a..6507dabdd5dd 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -13,6 +13,7 @@ config PARISC select BUG select HAVE_PERF_EVENTS select GENERIC_ATOMIC64 if !64BIT + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select HAVE_GENERIC_HARDIRQS select BROKEN_RODATA select GENERIC_IRQ_PROBE @@ -242,6 +243,14 @@ config SMP If you don't know what to do here, say N. +config IRQSTACKS + bool "Use separate kernel stacks when processing interrupts" + default y + help + If you say Y here the kernel will use separate kernel stacks + for handling hard and soft interrupts. This can help avoid + overflowing the process kernel stacks. + config HOTPLUG_CPU bool default y if SMP diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index bc989e522a04..08a332f6ee87 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug @@ -13,3 +13,14 @@ config DEBUG_RODATA If in doubt, say "N". endmenu + +config DEBUG_STACKOVERFLOW + bool "Check for stack overflows" + default y + depends on DEBUG_KERNEL + ---help--- + Say Y here if you want to check the overflows of kernel, IRQ + and exception stacks. This option will cause messages of the + stacks in detail when free stack space drops below a certain + limit. + If in doubt, say "N". diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 113e28206503..197690068f88 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -23,26 +23,21 @@ NM = sh $(srctree)/arch/parisc/nm CHECKFLAGS += -D__hppa__=1 LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) -MACHINE := $(shell uname -m) -ifeq ($(MACHINE),parisc*) -NATIVE := 1 -endif - ifdef CONFIG_64BIT UTS_MACHINE := parisc64 CHECKFLAGS += -D__LP64__=1 -m64 -WIDTH := 64 +CC_ARCHES = hppa64 else # 32-bit -WIDTH := +CC_ARCHES = hppa hppa2.0 hppa1.1 endif -# attempt to help out folks who are cross-compiling -ifeq ($(NATIVE),1) -CROSS_COMPILE := hppa$(WIDTH)-linux- -else - ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := hppa$(WIDTH)-linux-gnu- - endif +ifneq ($(SUBARCH),$(UTS_MACHINE)) + ifeq ($(CROSS_COMPILE),) + CC_SUFFIXES = linux linux-gnu unknown-linux-gnu + CROSS_COMPILE := $(call cc-cross-prefix, \ + $(foreach a,$(CC_ARCHES), \ + $(foreach s,$(CC_SUFFIXES),$(a)-$(s)-))) + endif endif OBJCOPY_FLAGS =-O binary -R .note -R .comment -S diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index f38e1984b242..472886ceab1d 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -229,6 +229,29 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +/* + * atomic64_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic_t + * + * The function returns the old value of *v minus 1, even if + * the atomic variable, v, was not decremented. + */ +static inline long atomic64_dec_if_positive(atomic64_t *v) +{ + long c, old, dec; + c = atomic64_read(v); + for (;;) { + dec = c - 1; + if (unlikely(dec < 0)) + break; + old = atomic64_cmpxchg((v), c, dec); + if (likely(old == c)) + break; + c = old; + } + return dec; +} + #endif /* !CONFIG_64BIT */ diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h index 106b395688e1..d0eae5f2bd87 100644 --- a/arch/parisc/include/asm/dma-mapping.h +++ b/arch/parisc/include/asm/dma-mapping.h @@ -46,6 +46,9 @@ extern struct hppa_dma_ops pcx_dma_ops; extern struct hppa_dma_ops *hppa_dma_ops; +#define dma_alloc_attrs(d, s, h, f, a) dma_alloc_coherent(d, s, h, f) +#define dma_free_attrs(d, s, h, f, a) dma_free_coherent(d, s, h, f) + static inline void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) diff --git a/arch/parisc/include/asm/hardirq.h b/arch/parisc/include/asm/hardirq.h index 0d68184a76cb..c19f7138ba48 100644 --- a/arch/parisc/include/asm/hardirq.h +++ b/arch/parisc/include/asm/hardirq.h @@ -1,11 +1,50 @@ /* hardirq.h: PA-RISC hard IRQ support. * * Copyright (C) 2001 Matthew Wilcox <matthew@wil.cx> + * Copyright (C) 2013 Helge Deller <deller@gmx.de> */ #ifndef _PARISC_HARDIRQ_H #define _PARISC_HARDIRQ_H -#include <asm-generic/hardirq.h> +#include <linux/cache.h> +#include <linux/threads.h> +#include <linux/irq.h> + +#ifdef CONFIG_IRQSTACKS +#define __ARCH_HAS_DO_SOFTIRQ +#endif + +typedef struct { + unsigned int __softirq_pending; +#ifdef CONFIG_DEBUG_STACKOVERFLOW + unsigned int kernel_stack_usage; +#ifdef CONFIG_IRQSTACKS + unsigned int irq_stack_usage; + unsigned int irq_stack_counter; +#endif +#endif +#ifdef CONFIG_SMP + unsigned int irq_resched_count; + unsigned int irq_call_count; +#endif + unsigned int irq_tlb_count; +} ____cacheline_aligned irq_cpustat_t; + +DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); + +#define __ARCH_IRQ_STAT +#define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) +#define inc_irq_stat(member) this_cpu_inc(irq_stat.member) +#define __inc_irq_stat(member) __this_cpu_inc(irq_stat.member) +#define local_softirq_pending() this_cpu_read(irq_stat.__softirq_pending) + +#define __ARCH_SET_SOFTIRQ_PENDING + +#define set_softirq_pending(x) \ + this_cpu_write(irq_stat.__softirq_pending, (x)) +#define or_softirq_pending(x) this_cpu_or(irq_stat.__softirq_pending, (x)) + +#define ack_bad_irq(irq) WARN(1, "unexpected IRQ trap at vector %02x\n", irq) #endif /* _PARISC_HARDIRQ_H */ diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 09b54a57a48d..cfbc43929cf6 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -20,8 +20,6 @@ #endif /* __ASSEMBLY__ */ -#define KERNEL_STACK_SIZE (4*PAGE_SIZE) - /* * Default implementation of macro that returns current * instruction pointer ("program counter"). @@ -61,6 +59,26 @@ #ifndef __ASSEMBLY__ /* + * IRQ STACK - used for irq handler + */ +#ifdef __KERNEL__ + +#include <linux/spinlock_types.h> + +#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */ + +union irq_stack_union { + unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)]; + raw_spinlock_t lock; +}; + +DECLARE_PER_CPU(union irq_stack_union, irq_stack_union); + +void call_on_stack(unsigned long p1, void *func, unsigned long new_stack); + +#endif /* __KERNEL__ */ + +/* * Data detected about CPUs at boot time which is the same for all CPU's. * HP boxes are SMP - ie identical processors. * @@ -97,7 +115,6 @@ struct cpuinfo_parisc { unsigned long txn_addr; /* MMIO addr of EIR or id_eid */ #ifdef CONFIG_SMP unsigned long pending_ipi; /* bitmap of type ipi_message_type */ - unsigned long ipi_count; /* number ipi Interrupts */ #endif unsigned long bh_count; /* number of times bh was invoked */ unsigned long prof_counter; /* per CPU profiling support */ diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h index 6182832e5b6c..540c88fa8f86 100644 --- a/arch/parisc/include/asm/thread_info.h +++ b/arch/parisc/include/asm/thread_info.h @@ -40,7 +40,7 @@ struct thread_info { /* thread information allocation */ -#define THREAD_SIZE_ORDER 2 +#define THREAD_SIZE_ORDER 2 /* PA-RISC requires at least 16k stack */ /* Be sure to hunt all references to this down when you change the size of * the kernel stack */ #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index 8f1a8100bf2d..5273da991e06 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h @@ -22,6 +22,8 @@ extern spinlock_t pa_tlb_lock; extern void flush_tlb_all(void); extern void flush_tlb_all_local(void *); +#define smp_flush_tlb_all() flush_tlb_all() + /* * flush_tlb_mm() * diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 83ded26cad06..65fb4cbc3a0f 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -606,7 +606,7 @@ void clear_user_highpage(struct page *page, unsigned long vaddr) /* Clear using TMPALIAS region. The page doesn't need to be flushed but the kernel mapping needs to be purged. */ - vto = kmap_atomic(page, KM_USER0); + vto = kmap_atomic(page); /* The PA-RISC 2.0 Architecture book states on page F-6: "Before a write-capable translation is enabled, *all* @@ -641,8 +641,8 @@ void copy_user_highpage(struct page *to, struct page *from, the `to' page must be flushed in copy_user_page_asm since it can be used to bring in executable code. */ - vfrom = kmap_atomic(from, KM_USER0); - vto = kmap_atomic(to, KM_USER1); + vfrom = kmap_atomic(from); + vto = kmap_atomic(to); purge_kernel_dcache_page_asm((unsigned long)vto); purge_tlb_start(flags); diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index f33201bf8977..ae27cb6ce19a 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -400,7 +400,15 @@ #if PT_NLEVELS == 3 extru \va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index #else +# if defined(CONFIG_64BIT) + extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index + #else + # if PAGE_SIZE > 4096 + extru \va,31-ASM_PGDIR_SHIFT,32-ASM_PGDIR_SHIFT,\index + # else extru \va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index + # endif +# endif #endif dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */ copy %r0,\pte @@ -444,9 +452,41 @@ L2_ptep \pgd,\pte,\index,\va,\fault .endm + /* Acquire pa_dbit_lock lock. */ + .macro dbit_lock spc,tmp,tmp1 +#ifdef CONFIG_SMP + cmpib,COND(=),n 0,\spc,2f + load32 PA(pa_dbit_lock),\tmp +1: LDCW 0(\tmp),\tmp1 + cmpib,COND(=) 0,\tmp1,1b + nop +2: +#endif + .endm + + /* Release pa_dbit_lock lock without reloading lock address. */ + .macro dbit_unlock0 spc,tmp +#ifdef CONFIG_SMP + or,COND(=) %r0,\spc,%r0 + stw \spc,0(\tmp) +#endif + .endm + + /* Release pa_dbit_lock lock. */ + .macro dbit_unlock1 spc,tmp +#ifdef CONFIG_SMP + load32 PA(pa_dbit_lock),\tmp + dbit_unlock0 \spc,\tmp +#endif + .endm + /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and * don't needlessly dirty the cache line if it was already set */ - .macro update_ptep ptep,pte,tmp,tmp1 + .macro update_ptep spc,ptep,pte,tmp,tmp1 +#ifdef CONFIG_SMP + or,COND(=) %r0,\spc,%r0 + LDREG 0(\ptep),\pte +#endif ldi _PAGE_ACCESSED,\tmp1 or \tmp1,\pte,\tmp and,COND(<>) \tmp1,\pte,%r0 @@ -455,7 +495,11 @@ /* Set the dirty bit (and accessed bit). No need to be * clever, this is only used from the dirty fault */ - .macro update_dirty ptep,pte,tmp + .macro update_dirty spc,ptep,pte,tmp +#ifdef CONFIG_SMP + or,COND(=) %r0,\spc,%r0 + LDREG 0(\ptep),\pte +#endif ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp or \tmp,\pte,\pte STREG \pte,0(\ptep) @@ -615,7 +659,7 @@ .text - .align PAGE_SIZE + .align 4096 ENTRY(fault_vector_20) /* First vector is invalid (0) */ @@ -825,11 +869,6 @@ ENTRY(syscall_exit_rfi) STREG %r19,PT_SR7(%r16) intr_return: - /* NOTE: Need to enable interrupts incase we schedule. */ - ssm PSW_SM_I, %r0 - -intr_check_resched: - /* check for reschedule */ mfctl %cr30,%r1 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ @@ -856,6 +895,11 @@ intr_check_sig: LDREG PT_IASQ1(%r16), %r20 cmpib,COND(=),n 0,%r20,intr_restore /* backward */ + /* NOTE: We need to enable interrupts if we have to deliver + * signals. We used to do this earlier but it caused kernel + * stack overflows. */ + ssm PSW_SM_I, %r0 + copy %r0, %r25 /* long in_syscall = 0 */ #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ @@ -907,6 +951,10 @@ intr_do_resched: cmpib,COND(=) 0, %r20, intr_do_preempt nop + /* NOTE: We need to enable interrupts if we schedule. We used + * to do this earlier but it caused kernel stack overflows. */ + ssm PSW_SM_I, %r0 + #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif @@ -1099,11 +1147,13 @@ dtlb_miss_20w: L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1123,11 +1173,13 @@ nadtlb_miss_20w: L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1149,7 +1201,8 @@ dtlb_miss_11: L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot @@ -1160,6 +1213,7 @@ dtlb_miss_11: idtlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ + dbit_unlock1 spc,t0 rfir nop @@ -1180,7 +1234,8 @@ nadtlb_miss_11: L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot @@ -1192,6 +1247,7 @@ nadtlb_miss_11: idtlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ + dbit_unlock1 spc,t0 rfir nop @@ -1212,13 +1268,15 @@ dtlb_miss_20: L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot f_extend pte,t0 idtlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1238,13 +1296,15 @@ nadtlb_miss_20: L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot f_extend pte,t0 idtlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1345,11 +1405,13 @@ itlb_miss_20w: L3_ptep ptp,pte,t0,va,itlb_fault - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot iitlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1367,11 +1429,13 @@ naitlb_miss_20w: L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot iitlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1393,7 +1457,8 @@ itlb_miss_11: L2_ptep ptp,pte,t0,va,itlb_fault - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot @@ -1404,6 +1469,7 @@ itlb_miss_11: iitlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ + dbit_unlock1 spc,t0 rfir nop @@ -1415,7 +1481,8 @@ naitlb_miss_11: L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot @@ -1426,6 +1493,7 @@ naitlb_miss_11: iitlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ + dbit_unlock1 spc,t0 rfir nop @@ -1447,13 +1515,15 @@ itlb_miss_20: L2_ptep ptp,pte,t0,va,itlb_fault - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot f_extend pte,t0 iitlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1465,13 +1535,15 @@ naitlb_miss_20: L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 - update_ptep ptp,pte,t0,t1 + dbit_lock spc,t0,t1 + update_ptep spc,ptp,pte,t0,t1 make_insert_tlb spc,pte,prot f_extend pte,t0 iitlbt pte,prot + dbit_unlock1 spc,t0 rfir nop @@ -1495,29 +1567,13 @@ dbit_trap_20w: L3_ptep ptp,pte,t0,va,dbit_fault -#ifdef CONFIG_SMP - cmpib,COND(=),n 0,spc,dbit_nolock_20w - load32 PA(pa_dbit_lock),t0 - -dbit_spin_20w: - LDCW 0(t0),t1 - cmpib,COND(=) 0,t1,dbit_spin_20w - nop - -dbit_nolock_20w: -#endif - update_dirty ptp,pte,t1 + dbit_lock spc,t0,t1 + update_dirty spc,ptp,pte,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot -#ifdef CONFIG_SMP - cmpib,COND(=),n 0,spc,dbit_nounlock_20w - ldi 1,t1 - stw t1,0(t0) - -dbit_nounlock_20w: -#endif + dbit_unlock0 spc,t0 rfir nop @@ -1531,18 +1587,8 @@ dbit_trap_11: L2_ptep ptp,pte,t0,va,dbit_fault -#ifdef CONFIG_SMP - cmpib,COND(=),n 0,spc,dbit_nolock_11 - load32 PA(pa_dbit_lock),t0 - -dbit_spin_11: - LDCW 0(t0),t1 - cmpib,= 0,t1,dbit_spin_11 - nop - -dbit_nolock_11: -#endif - update_dirty ptp,pte,t1 + dbit_lock spc,t0,t1 + update_dirty spc,ptp,pte,t1 make_insert_tlb_11 spc,pte,prot @@ -1553,13 +1599,7 @@ dbit_nolock_11: idtlbp prot,(%sr1,va) mtsp t1, %sr1 /* Restore sr1 */ -#ifdef CONFIG_SMP - cmpib,COND(=),n 0,spc,dbit_nounlock_11 - ldi 1,t1 - stw t1,0(t0) - -dbit_nounlock_11: -#endif + dbit_unlock0 spc,t0 rfir nop @@ -1571,32 +1611,15 @@ dbit_trap_20: L2_ptep ptp,pte,t0,va,dbit_fault -#ifdef CONFIG_SMP - cmpib,COND(=),n 0,spc,dbit_nolock_20 - load32 PA(pa_dbit_lock),t0 - -dbit_spin_20: - LDCW 0(t0),t1 - cmpib,= 0,t1,dbit_spin_20 - nop - -dbit_nolock_20: -#endif - update_dirty ptp,pte,t1 + dbit_lock spc,t0,t1 + update_dirty spc,ptp,pte,t1 make_insert_tlb spc,pte,prot f_extend pte,t1 idtlbt pte,prot - -#ifdef CONFIG_SMP - cmpib,COND(=),n 0,spc,dbit_nounlock_20 - ldi 1,t1 - stw t1,0(t0) - -dbit_nounlock_20: -#endif + dbit_unlock0 spc,t0 rfir nop @@ -1694,7 +1717,8 @@ ENTRY(sys_\name\()_wrapper) ldo TASK_REGS(%r1),%r1 reg_save %r1 mfctl %cr27, %r28 - b sys_\name + ldil L%sys_\name, %r31 + be R%sys_\name(%sr4,%r31) STREG %r28, PT_CR27(%r1) ENDPROC(sys_\name\()_wrapper) .endm @@ -1997,6 +2021,47 @@ ftrace_stub: ENDPROC(return_to_handler) #endif /* CONFIG_FUNCTION_TRACER */ +#ifdef CONFIG_IRQSTACKS +/* void call_on_stack(unsigned long param1, void *func, + unsigned long new_stack) */ +ENTRY(call_on_stack) + copy %sp, %r1 + + /* Regarding the HPPA calling conventions for function pointers, + we assume the PIC register is not changed across call. For + CONFIG_64BIT, the argument pointer is left to point at the + argument region allocated for the call to call_on_stack. */ +# ifdef CONFIG_64BIT + /* Switch to new stack. We allocate two 128 byte frames. */ + ldo 256(%arg2), %sp + /* Save previous stack pointer and return pointer in frame marker */ + STREG %rp, -144(%sp) + /* Calls always use function descriptor */ + LDREG 16(%arg1), %arg1 + bve,l (%arg1), %rp + STREG %r1, -136(%sp) + LDREG -144(%sp), %rp + bve (%rp) + LDREG -136(%sp), %sp +# else + /* Switch to new stack. We allocate two 64 byte frames. */ + ldo 128(%arg2), %sp + /* Save previous stack pointer and return pointer in frame marker */ + STREG %r1, -68(%sp) + STREG %rp, -84(%sp) + /* Calls use function descriptor if PLABEL bit is set */ + bb,>=,n %arg1, 30, 1f + depwi 0,31,2, %arg1 + LDREG 0(%arg1), %arg1 +1: + be,l 0(%sr4,%arg1), %sr0, %r31 + copy %r31, %rp + LDREG -84(%sp), %rp + bv (%rp) + LDREG -68(%sp), %sp +# endif /* CONFIG_64BIT */ +ENDPROC(call_on_stack) +#endif /* CONFIG_IRQSTACKS */ get_register: /* diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S index 5595a2f31181..e158b6fbf1b4 100644 --- a/arch/parisc/kernel/hpmc.S +++ b/arch/parisc/kernel/hpmc.S @@ -55,13 +55,13 @@ * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc. */ - .align PAGE_SIZE + .align 4096 hpmc_stack: .block 16384 #define HPMC_IODC_BUF_SIZE 0x8000 - .align PAGE_SIZE + .align 4096 hpmc_iodc_buf: .block HPMC_IODC_BUF_SIZE diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 8094d3ed3b64..55237a70e197 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -152,6 +152,49 @@ static struct irq_chip cpu_interrupt_type = { .irq_retrigger = NULL, }; +DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); +#define irq_stats(x) (&per_cpu(irq_stat, x)) + +/* + * /proc/interrupts printing for arch specific interrupts + */ +int arch_show_interrupts(struct seq_file *p, int prec) +{ + int j; + +#ifdef CONFIG_DEBUG_STACKOVERFLOW + seq_printf(p, "%*s: ", prec, "STK"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->kernel_stack_usage); + seq_puts(p, " Kernel stack usage\n"); +# ifdef CONFIG_IRQSTACKS + seq_printf(p, "%*s: ", prec, "IST"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_stack_usage); + seq_puts(p, " Interrupt stack usage\n"); + seq_printf(p, "%*s: ", prec, "ISC"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_stack_counter); + seq_puts(p, " Interrupt stack usage counter\n"); +# endif +#endif +#ifdef CONFIG_SMP + seq_printf(p, "%*s: ", prec, "RES"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count); + seq_puts(p, " Rescheduling interrupts\n"); + seq_printf(p, "%*s: ", prec, "CAL"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_call_count); + seq_puts(p, " Function call interrupts\n"); +#endif + seq_printf(p, "%*s: ", prec, "TLB"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); + seq_puts(p, " TLB shootdowns\n"); + return 0; +} + int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v, j; @@ -219,6 +262,9 @@ int show_interrupts(struct seq_file *p, void *v) raw_spin_unlock_irqrestore(&desc->lock, flags); } + if (i == NR_IRQS) + arch_show_interrupts(p, 3); + return 0; } @@ -330,6 +376,129 @@ static inline int eirr_to_irq(unsigned long eirr) return (BITS_PER_LONG - bit) + TIMER_IRQ; } +int sysctl_panic_on_stackoverflow = 1; + +static inline void stack_overflow_check(struct pt_regs *regs) +{ +#ifdef CONFIG_DEBUG_STACKOVERFLOW + #define STACK_MARGIN (256*6) + + /* Our stack starts directly behind the thread_info struct. */ + unsigned long stack_start = (unsigned long) current_thread_info(); + unsigned long sp = regs->gr[30]; + unsigned long stack_usage; + unsigned int *last_usage; + int cpu = smp_processor_id(); + + /* if sr7 != 0, we interrupted a userspace process which we do not want + * to check for stack overflow. We will only check the kernel stack. */ + if (regs->sr[7]) + return; + + /* calculate kernel stack usage */ + stack_usage = sp - stack_start; +#ifdef CONFIG_IRQSTACKS + if (likely(stack_usage <= THREAD_SIZE)) + goto check_kernel_stack; /* found kernel stack */ + + /* check irq stack usage */ + stack_start = (unsigned long) &per_cpu(irq_stack_union, cpu).stack; + stack_usage = sp - stack_start; + + last_usage = &per_cpu(irq_stat.irq_stack_usage, cpu); + if (unlikely(stack_usage > *last_usage)) + *last_usage = stack_usage; + + if (likely(stack_usage < (IRQ_STACK_SIZE - STACK_MARGIN))) + return; + + pr_emerg("stackcheck: %s will most likely overflow irq stack " + "(sp:%lx, stk bottom-top:%lx-%lx)\n", + current->comm, sp, stack_start, stack_start + IRQ_STACK_SIZE); + goto panic_check; + +check_kernel_stack: +#endif + + /* check kernel stack usage */ + last_usage = &per_cpu(irq_stat.kernel_stack_usage, cpu); + + if (unlikely(stack_usage > *last_usage)) + *last_usage = stack_usage; + + if (likely(stack_usage < (THREAD_SIZE - STACK_MARGIN))) + return; + + pr_emerg("stackcheck: %s will most likely overflow kernel stack " + "(sp:%lx, stk bottom-top:%lx-%lx)\n", + current->comm, sp, stack_start, stack_start + THREAD_SIZE); + +#ifdef CONFIG_IRQSTACKS +panic_check: +#endif + if (sysctl_panic_on_stackoverflow) + panic("low stack detected by irq handler - check messages\n"); +#endif +} + +#ifdef CONFIG_IRQSTACKS +DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = { + .lock = __RAW_SPIN_LOCK_UNLOCKED((irq_stack_union).lock) + }; + +static void execute_on_irq_stack(void *func, unsigned long param1) +{ + union irq_stack_union *union_ptr; + unsigned long irq_stack; + raw_spinlock_t *irq_stack_in_use; + + union_ptr = &per_cpu(irq_stack_union, smp_processor_id()); + irq_stack = (unsigned long) &union_ptr->stack; + irq_stack = ALIGN(irq_stack + sizeof(irq_stack_union.lock), + 64); /* align for stack frame usage */ + + /* We may be called recursive. If we are already using the irq stack, + * just continue to use it. Use spinlocks to serialize + * the irq stack usage. + */ + irq_stack_in_use = &union_ptr->lock; + if (!raw_spin_trylock(irq_stack_in_use)) { + void (*direct_call)(unsigned long p1) = func; + + /* We are using the IRQ stack already. + * Do direct call on current stack. */ + direct_call(param1); + return; + } + + /* This is where we switch to the IRQ stack. */ + call_on_stack(param1, func, irq_stack); + + __inc_irq_stat(irq_stack_counter); + + /* free up irq stack usage. */ + do_raw_spin_unlock(irq_stack_in_use); +} + +asmlinkage void do_softirq(void) +{ + __u32 pending; + unsigned long flags; + + if (in_interrupt()) + return; + + local_irq_save(flags); + + pending = local_softirq_pending(); + + if (pending) + execute_on_irq_stack(__do_softirq, 0); + + local_irq_restore(flags); +} +#endif /* CONFIG_IRQSTACKS */ + /* ONLY called from entry.S:intr_extint() */ void do_cpu_irq_mask(struct pt_regs *regs) { @@ -364,7 +533,13 @@ void do_cpu_irq_mask(struct pt_regs *regs) goto set_out; } #endif + stack_overflow_check(regs); + +#ifdef CONFIG_IRQSTACKS + execute_on_irq_stack(&generic_handle_irq, irq); +#else generic_handle_irq(irq); +#endif /* CONFIG_IRQSTACKS */ out: irq_exit(); @@ -420,6 +595,4 @@ void __init init_IRQ(void) cpu_eiem = EIEM_MASK(TIMER_IRQ); #endif set_eiem(cpu_eiem); /* EIEM : enable all external intr */ - } - diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 312b48422a56..5e1de6072be5 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -563,6 +563,15 @@ ENDPROC(copy_page_asm) * %r23 physical page (shifted for tlb insert) of "from" translation */ + /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ + #define PAGE_ADD_SHIFT (PAGE_SHIFT-12) + .macro convert_phys_for_tlb_insert20 phys + extrd,u \phys, 56-PAGE_ADD_SHIFT, 32-PAGE_ADD_SHIFT, \phys +#if _PAGE_SIZE_ENCODING_DEFAULT + depdi _PAGE_SIZE_ENCODING_DEFAULT, 63, (63-58), \phys +#endif + .endm + /* * We can't do this since copy_user_page is used to bring in * file data that might have instructions. Since the data would @@ -589,15 +598,14 @@ ENTRY(copy_user_page_asm) sub %r25, %r1, %r23 ldil L%(TMPALIAS_MAP_START), %r28 - /* FIXME for different page sizes != 4k */ #ifdef CONFIG_64BIT #if (TMPALIAS_MAP_START >= 0x80000000) depdi 0, 31,32, %r28 /* clear any sign extension */ #endif - extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */ - extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */ + convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ + convert_phys_for_tlb_insert20 %r23 /* convert phys addr to tlb insert format */ depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,12, %r28 /* Clear any offset bits */ + depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ copy %r28, %r29 depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */ #else @@ -747,11 +755,10 @@ ENTRY(clear_user_page_asm) #ifdef CONFIG_64BIT #if (TMPALIAS_MAP_START >= 0x80000000) depdi 0, 31,32, %r28 /* clear any sign extension */ - /* FIXME: page size dependend */ #endif - extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ + convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,12, %r28 /* Clear any offset bits */ + depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ #else extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ @@ -832,11 +839,10 @@ ENTRY(flush_dcache_page_asm) #ifdef CONFIG_64BIT #if (TMPALIAS_MAP_START >= 0x80000000) depdi 0, 31,32, %r28 /* clear any sign extension */ - /* FIXME: page size dependend */ #endif - extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ + convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,12, %r28 /* Clear any offset bits */ + depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ #else extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ @@ -909,11 +915,10 @@ ENTRY(flush_icache_page_asm) #ifdef CONFIG_64BIT #if (TMPALIAS_MAP_START >= 0x80000000) depdi 0, 31,32, %r28 /* clear any sign extension */ - /* FIXME: page size dependend */ #endif - extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */ + convert_phys_for_tlb_insert20 %r26 /* convert phys addr to tlb insert format */ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */ - depdi 0, 63,12, %r28 /* Clear any offset bits */ + depdi 0, 63,PAGE_SHIFT, %r28 /* Clear any offset bits */ #else extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */ @@ -959,7 +964,7 @@ ENTRY(flush_icache_page_asm) fic,m %r1(%sr4,%r28) fic,m %r1(%sr4,%r28) fic,m %r1(%sr4,%r28) - cmpb,COND(<<) %r28, %r25,1b + cmpb,COND(<<) %r28, %r25,1b fic,m %r1(%sr4,%r28) sync diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c index a3328c2616b0..76b63e726a53 100644 --- a/arch/parisc/kernel/setup.c +++ b/arch/parisc/kernel/setup.c @@ -129,6 +129,8 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "The 32-bit Kernel has started...\n"); #endif + printk(KERN_INFO "Default page size is %dKB.\n", (int)(PAGE_SIZE / 1024)); + pdc_console_init(); #ifdef CONFIG_64BIT diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index fd1bb1519c2b..e3614fb343e5 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -127,7 +127,7 @@ ipi_interrupt(int irq, void *dev_id) unsigned long flags; /* Count this now; we may make a call that never returns. */ - p->ipi_count++; + inc_irq_stat(irq_call_count); mb(); /* Order interrupt and bit testing. */ @@ -155,6 +155,7 @@ ipi_interrupt(int irq, void *dev_id) case IPI_RESCHEDULE: smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu); + inc_irq_stat(irq_resched_count); scheduler_ipi(); break; @@ -263,17 +264,6 @@ void arch_send_call_function_single_ipi(int cpu) } /* - * Flush all other CPU's tlb and then mine. Do this with on_each_cpu() - * as we want to ensure all TLB's flushed before proceeding. - */ - -void -smp_flush_tlb_all(void) -{ - on_each_cpu(flush_tlb_all_local, NULL, 1); -} - -/* * Called by secondaries to update state and initialize CPU registers. */ static void __init diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index f517e08e7f0d..a134ff4da12e 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -59,11 +59,3 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, current->comm, current->pid, r20); return -ENOSYS; } - -asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi, - u32 mask_lo, int fd, - const char __user *pathname) -{ - return sys_fanotify_mark(fan_fd, flags, ((u64)mask_hi << 32) | mask_lo, - fd, pathname); -} diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 5e055240f00b..e767ab733e32 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -1,12 +1,35 @@ /* * Linux/PA-RISC Project (http://www.parisc-linux.org/) * - * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai> + * System call entry code / Linux gateway page + * Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai> * Licensed under the GNU GPL. * thanks to Philipp Rumpf, Mike Shaver and various others * sorry about the wall, puffin.. */ +/* +How does the Linux gateway page on PA-RISC work? +------------------------------------------------ +The Linux gateway page on PA-RISC is "special". +It actually has PAGE_GATEWAY bits set (this is linux terminology; in parisc +terminology it's Execute, promote to PL0) in the page map. So anything +executing on this page executes with kernel level privilege (there's more to it +than that: to have this happen, you also have to use a branch with a ,gate +completer to activate the privilege promotion). The upshot is that everything +that runs on the gateway page runs at kernel privilege but with the current +user process address space (although you have access to kernel space via %sr2). +For the 0x100 syscall entry, we redo the space registers to point to the kernel +address space (preserving the user address space in %sr3), move to wide mode if +required, save the user registers and branch into the kernel syscall entry +point. For all the other functions, we execute at kernel privilege but don't +flip address spaces. The basic upshot of this is that these code snippets are +executed atomically (because the kernel can't be pre-empted) and they may +perform architecturally forbidden (to PL3) operations (like setting control +registers). +*/ + + #include <asm/asm-offsets.h> #include <asm/unistd.h> #include <asm/errno.h> @@ -15,6 +38,7 @@ #include <asm/thread_info.h> #include <asm/assembly.h> #include <asm/processor.h> +#include <asm/cache.h> #include <linux/linkage.h> @@ -643,7 +667,7 @@ ENTRY(end_linux_gateway_page) .section .rodata,"a" - .align PAGE_SIZE + .align 8 /* Light-weight-syscall table */ /* Start of lws table. */ ENTRY(lws_table) @@ -652,13 +676,13 @@ ENTRY(lws_table) END(lws_table) /* End of lws table */ - .align PAGE_SIZE + .align 8 ENTRY(sys_call_table) #include "syscall_table.S" END(sys_call_table) #ifdef CONFIG_64BIT - .align PAGE_SIZE + .align 8 ENTRY(sys_call_table64) #define SYSCALL_TABLE_64BIT #include "syscall_table.S" @@ -674,7 +698,7 @@ END(sys_call_table64) with ldcw. */ .section .data - .align PAGE_SIZE + .align L1_CACHE_BYTES ENTRY(lws_lock_start) /* lws locks */ .rept 16 diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index f702bff0bed9..fe41a98043bb 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -522,10 +522,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs) */ if (((unsigned long)regs->iaoq[0] & 3) && ((unsigned long)regs->iasq[0] != (unsigned long)regs->sr[7])) { - /* Kill the user process later */ - regs->iaoq[0] = 0 | 3; + /* Kill the user process later */ + regs->iaoq[0] = 0 | 3; regs->iaoq[1] = regs->iaoq[0] + 4; - regs->iasq[0] = regs->iasq[1] = regs->sr[7]; + regs->iasq[0] = regs->iasq[1] = regs->sr[7]; regs->gr[0] &= ~PSW_B; return; } @@ -541,8 +541,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs) /* set up a new led state on systems shipped with a LED State panel */ pdc_chassis_send_status(PDC_CHASSIS_DIRECT_HPMC); - - parisc_terminate("High Priority Machine Check (HPMC)", + + parisc_terminate("High Priority Machine Check (HPMC)", regs, code, 0); /* NOT REACHED */ @@ -584,13 +584,13 @@ void notrace handle_interruption(int code, struct pt_regs *regs) /* Break instruction trap */ handle_break(regs); return; - + case 10: /* Privileged operation trap */ die_if_kernel("Privileged operation", regs, code); si.si_code = ILL_PRVOPC; goto give_sigill; - + case 11: /* Privileged register trap */ if ((regs->iir & 0xffdfffe0) == 0x034008a0) { @@ -634,7 +634,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) if(user_mode(regs)){ si.si_signo = SIGFPE; /* Set to zero, and let the userspace app figure it out from - the insn pointed to by si_addr */ + the insn pointed to by si_addr */ si.si_code = 0; si.si_addr = (void __user *) regs->iaoq[0]; force_sig_info(SIGFPE, &si, current); @@ -648,7 +648,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) die_if_kernel("Floating point exception", regs, 0); /* quiet */ handle_fpe(regs); return; - + case 15: /* Data TLB miss fault/Data page fault */ /* Fall through */ @@ -660,15 +660,15 @@ void notrace handle_interruption(int code, struct pt_regs *regs) case 17: /* Non-access data TLB miss fault/Non-access data page fault */ /* FIXME: - Still need to add slow path emulation code here! - If the insn used a non-shadow register, then the tlb + Still need to add slow path emulation code here! + If the insn used a non-shadow register, then the tlb handlers could not have their side-effect (e.g. probe writing to a target register) emulated since rfir would erase the changes to said register. Instead we have to setup everything, call this function we are in, and emulate by hand. Technically we need to emulate: fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw - */ + */ fault_address = regs->ior; fault_space = regs->isr; break; diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 64a999882e4f..4bb095a2f6fc 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -95,7 +95,7 @@ SECTIONS NOTES /* Data */ - RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) + RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, PAGE_SIZE) /* PA-RISC locks requires 16-byte alignment */ . = ALIGN(16); diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 157b931e7b09..1c965642068b 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -1069,6 +1069,7 @@ void flush_tlb_all(void) { int do_recycle; + __inc_irq_stat(irq_tlb_count); do_recycle = 0; spin_lock(&sid_lock); if (dirty_space_ids > RECYCLE_THRESHOLD) { @@ -1089,6 +1090,7 @@ void flush_tlb_all(void) #else void flush_tlb_all(void) { + __inc_irq_stat(irq_tlb_count); spin_lock(&sid_lock); flush_tlb_all_local(NULL); recycle_sids(); diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index bbbe02197afb..c33e3ad2c8fd 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -82,11 +82,6 @@ config GENERIC_HWEIGHT bool default y -config GENERIC_GPIO - bool - help - Generic GPIO API support - config PPC bool default y diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 5416e28a7538..863d877e0b5f 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -262,8 +262,31 @@ config PPC_EARLY_DEBUG_OPAL_HVSI Select this to enable early debugging for the PowerNV platform using an "hvsi" console +config PPC_EARLY_DEBUG_MEMCONS + bool "In memory console" + help + Select this to enable early debugging using an in memory console. + This console provides input and output buffers stored within the + kernel BSS and should be safe to select on any system. A debugger + can then be used to read kernel output or send input to the console. endchoice +config PPC_MEMCONS_OUTPUT_SIZE + int "In memory console output buffer size" + depends on PPC_EARLY_DEBUG_MEMCONS + default 4096 + help + Selects the size of the output buffer (in bytes) of the in memory + console. + +config PPC_MEMCONS_INPUT_SIZE + int "In memory console input buffer size" + depends on PPC_EARLY_DEBUG_MEMCONS + default 128 + help + Selects the size of the input buffer (in bytes) of the in memory + console. + config PPC_EARLY_DEBUG_OPAL def_bool y depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI diff --git a/arch/powerpc/include/asm/context_tracking.h b/arch/powerpc/include/asm/context_tracking.h new file mode 100644 index 000000000000..b6f5a33b8ee2 --- /dev/null +++ b/arch/powerpc/include/asm/context_tracking.h @@ -0,0 +1,10 @@ +#ifndef _ASM_POWERPC_CONTEXT_TRACKING_H +#define _ASM_POWERPC_CONTEXT_TRACKING_H + +#ifdef CONFIG_CONTEXT_TRACKING +#define SCHEDULE_USER bl .schedule_user +#else +#define SCHEDULE_USER bl .schedule +#endif + +#endif diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index fcc54ad159ba..26807e5aff51 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -224,8 +224,10 @@ extern const char *powerpc_base_platform; /* We only set the TM feature if the kernel was compiled with TM supprt */ #ifdef CONFIG_PPC_TRANSACTIONAL_MEM #define CPU_FTR_TM_COMP CPU_FTR_TM +#define PPC_FEATURE2_HTM_COMP PPC_FEATURE2_HTM #else #define CPU_FTR_TM_COMP 0 +#define PPC_FEATURE2_HTM_COMP 0 #endif /* We need to mark all pages as being coherent if we're SMP or we have a diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h index 0df54646f968..681bc0314b6b 100644 --- a/arch/powerpc/include/asm/firmware.h +++ b/arch/powerpc/include/asm/firmware.h @@ -52,6 +52,7 @@ #define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000) #define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000) #define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000) +#define FW_FEATURE_OPALv3 ASM_CONST(0x0000000400000000) #ifndef __ASSEMBLY__ @@ -69,7 +70,8 @@ enum { FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY | FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN, FW_FEATURE_PSERIES_ALWAYS = 0, - FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2, + FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2 | + FW_FEATURE_OPALv3, FW_FEATURE_POWERNV_ALWAYS = 0, FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index e45c4947a772..ba713f166fa5 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -95,15 +95,14 @@ static inline bool arch_irqs_disabled(void) #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) #endif -static inline void hard_irq_disable(void) -{ - __hard_irq_disable(); - get_paca()->soft_enabled = 0; - get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; -} - -/* include/linux/interrupt.h needs hard_irq_disable to be a macro */ -#define hard_irq_disable hard_irq_disable +#define hard_irq_disable() do { \ + u8 _was_enabled = get_paca()->soft_enabled; \ + __hard_irq_disable(); \ + get_paca()->soft_enabled = 0; \ + get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; \ + if (_was_enabled) \ + trace_hardirqs_off(); \ +} while(0) static inline bool lazy_irq_pending(void) { diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 3f3f691be2e7..92386fc4e82a 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -29,6 +29,7 @@ struct rtc_time; struct file; struct pci_controller; struct kimage; +struct pci_host_bridge; struct machdep_calls { char *name; @@ -108,6 +109,8 @@ struct machdep_calls { void (*pcibios_fixup)(void); int (*pci_probe_mode)(struct pci_bus *); void (*pci_irq_fixup)(struct pci_dev *dev); + int (*pcibios_root_bridge_prepare)(struct pci_host_bridge + *bridge); /* To setup PHBs when using automatic OF platform driver for PCI */ int (*pci_setup_phb)(struct pci_controller *host); diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index b6c8b58b1d76..cbb9305ab15a 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -243,7 +243,8 @@ enum OpalMCE_TlbErrorType { enum OpalThreadStatus { OPAL_THREAD_INACTIVE = 0x0, - OPAL_THREAD_STARTED = 0x1 + OPAL_THREAD_STARTED = 0x1, + OPAL_THREAD_UNAVAILABLE = 0x2 /* opal-v3 */ }; enum OpalPciBusCompare { @@ -563,6 +564,8 @@ extern void opal_nvram_init(void); extern int opal_machine_check(struct pt_regs *regs); +extern void opal_shutdown(void); + #endif /* __ASSEMBLY__ */ #endif /* __OPAL_H */ diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ffbc5fd549ac..8b11b5bd9938 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -39,11 +39,6 @@ struct pci_controller { resource_size_t io_base_phys; resource_size_t pci_io_size; - /* Some machines (PReP) have a non 1:1 mapping of - * the PCI memory space in the CPU bus space - */ - resource_size_t pci_mem_offset; - /* Some machines have a special region to forward the ISA * "memory" cycles such as VGA memory regions. Left to 0 * if unsupported @@ -86,6 +81,7 @@ struct pci_controller { */ struct resource io_resource; struct resource mem_resources[3]; + resource_size_t mem_offset[3]; int global_number; /* PCI domain number */ resource_size_t dma_window_base_cur; @@ -163,6 +159,8 @@ struct pci_dn { int pci_ext_config_space; /* for pci devices */ + int force_32bit_msi:1; + struct pci_dev *pcidev; /* back-pointer to the pci device */ #ifdef CONFIG_EEH struct eeh_dev *edev; /* eeh device */ diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index 91acb12bac92..b66ae722a8e9 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h @@ -186,7 +186,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, static inline pgtable_t pmd_pgtable(pmd_t pmd) { - return (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE); + return (pgtable_t)(pmd_val(pmd) & ~PMD_MASKED_BITS); } static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 0c34e4803499..eccfc161e58e 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -115,6 +115,10 @@ #define PPC_INST_MFSPR_DSCR_MASK 0xfc1fffff #define PPC_INST_MTSPR_DSCR 0x7c1103a6 #define PPC_INST_MTSPR_DSCR_MASK 0xfc1fffff +#define PPC_INST_MFSPR_DSCR_USER 0x7c0302a6 +#define PPC_INST_MFSPR_DSCR_USER_MASK 0xfc1fffff +#define PPC_INST_MTSPR_DSCR_USER 0x7c0303a6 +#define PPC_INST_MTSPR_DSCR_USER_MASK 0xfc1fffff #define PPC_INST_SLBFEE 0x7c0007a7 #define PPC_INST_STRING 0x7c00042a diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index 3e13e23e4fdf..d836d945068d 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h @@ -47,7 +47,7 @@ * generic accessors and iterators here */ #define __real_pte(e,p) ((real_pte_t) { \ - (e), ((e) & _PAGE_COMBO) ? \ + (e), (pte_val(e) & _PAGE_COMBO) ? \ (pte_val(*((p) + PTRS_PER_PTE))) : 0 }) #define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \ (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index a8bc2bb4adc9..34fd70488d83 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -264,6 +264,8 @@ extern void rtas_progress(char *s, unsigned short hex); extern void rtas_initialize(void); extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); +extern int rtas_online_cpus_mask(cpumask_var_t cpus); +extern int rtas_offline_cpus_mask(cpumask_var_t cpus); extern int rtas_ibm_suspend_me(struct rtas_args *); struct rtc_time; diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 8ceea14d6fe4..ba7b1973866e 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_PERFMON_CTXSW 6 /* perfmon needs ctxsw calls */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ #define TIF_SINGLESTEP 8 /* singlestepping active */ -#define TIF_MEMDIE 9 /* is terminating due to OOM killer */ +#define TIF_NOHZ 9 /* in adaptive nohz mode */ #define TIF_SECCOMP 10 /* secure computing */ #define TIF_RESTOREALL 11 /* Restore all regs (implies NOERROR) */ #define TIF_NOERROR 12 /* Force successful syscall return */ @@ -106,6 +106,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */ #define TIF_EMULATE_STACK_STORE 16 /* Is an instruction emulation for stack store? */ +#define TIF_MEMDIE 17 /* is terminating due to OOM killer */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) @@ -124,8 +125,10 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_UPROBE (1<<TIF_UPROBE) #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) #define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) +#define _TIF_NOHZ (1<<TIF_NOHZ) #define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ - _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT) + _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ + _TIF_NOHZ) #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ _TIF_NOTIFY_RESUME | _TIF_UPROBE) diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h index 5a7510e9d09d..dc590919f8eb 100644 --- a/arch/powerpc/include/asm/udbg.h +++ b/arch/powerpc/include/asm/udbg.h @@ -52,6 +52,7 @@ extern void __init udbg_init_40x_realmode(void); extern void __init udbg_init_cpm(void); extern void __init udbg_init_usbgecko(void); extern void __init udbg_init_wsp(void); +extern void __init udbg_init_memcons(void); extern void __init udbg_init_ehv_bc(void); extern void __init udbg_init_ps3gelic(void); extern void __init udbg_init_debug_opal_raw(void); diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h index ed9dd8156962..5b7657959faa 100644 --- a/arch/powerpc/include/uapi/asm/cputable.h +++ b/arch/powerpc/include/uapi/asm/cputable.h @@ -1,6 +1,7 @@ #ifndef _UAPI__ASM_POWERPC_CPUTABLE_H #define _UAPI__ASM_POWERPC_CPUTABLE_H +/* in AT_HWCAP */ #define PPC_FEATURE_32 0x80000000 #define PPC_FEATURE_64 0x40000000 #define PPC_FEATURE_601_INSTR 0x20000000 @@ -33,4 +34,12 @@ #define PPC_FEATURE_TRUE_LE 0x00000002 #define PPC_FEATURE_PPC_LE 0x00000001 +/* in AT_HWCAP2 */ +#define PPC_FEATURE2_ARCH_2_07 0x80000000 +#define PPC_FEATURE2_HTM 0x40000000 +#define PPC_FEATURE2_DSCR 0x20000000 +#define PPC_FEATURE2_EBB 0x10000000 +#define PPC_FEATURE2_ISEL 0x08000000 +#define PPC_FEATURE2_TAR 0x04000000 + #endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index ae9f433daabf..c60bbec25c1f 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -98,10 +98,14 @@ extern void __restore_cpu_e6500(void); PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \ PPC_FEATURE_TRUE_LE | \ PPC_FEATURE_PSERIES_PERFMON_COMPAT) +#define COMMON_USER2_POWER7 (PPC_FEATURE2_DSCR) #define COMMON_USER_POWER8 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_06 |\ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \ PPC_FEATURE_TRUE_LE | \ PPC_FEATURE_PSERIES_PERFMON_COMPAT) +#define COMMON_USER2_POWER8 (PPC_FEATURE2_ARCH_2_07 | \ + PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_DSCR | \ + PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR) #define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\ PPC_FEATURE_TRUE_LE | \ PPC_FEATURE_HAS_ALTIVEC_COMP) @@ -428,6 +432,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_name = "POWER7 (architected)", .cpu_features = CPU_FTRS_POWER7, .cpu_user_features = COMMON_USER_POWER7, + .cpu_user_features2 = COMMON_USER2_POWER7, .mmu_features = MMU_FTRS_POWER7, .icache_bsize = 128, .dcache_bsize = 128, @@ -443,6 +448,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_name = "POWER8 (architected)", .cpu_features = CPU_FTRS_POWER8, .cpu_user_features = COMMON_USER_POWER8, + .cpu_user_features2 = COMMON_USER2_POWER8, .mmu_features = MMU_FTRS_POWER8, .icache_bsize = 128, .dcache_bsize = 128, @@ -458,6 +464,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_name = "POWER7 (raw)", .cpu_features = CPU_FTRS_POWER7, .cpu_user_features = COMMON_USER_POWER7, + .cpu_user_features2 = COMMON_USER2_POWER7, .mmu_features = MMU_FTRS_POWER7, .icache_bsize = 128, .dcache_bsize = 128, @@ -475,6 +482,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_name = "POWER7+ (raw)", .cpu_features = CPU_FTRS_POWER7, .cpu_user_features = COMMON_USER_POWER7, + .cpu_user_features = COMMON_USER2_POWER7, .mmu_features = MMU_FTRS_POWER7, .icache_bsize = 128, .dcache_bsize = 128, @@ -492,6 +500,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_name = "POWER8 (raw)", .cpu_features = CPU_FTRS_POWER8, .cpu_user_features = COMMON_USER_POWER8, + .cpu_user_features2 = COMMON_USER2_POWER8, .mmu_features = MMU_FTRS_POWER8, .icache_bsize = 128, .dcache_bsize = 128, @@ -1995,6 +2004,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE_COMP, + .cpu_user_features2 = PPC_FEATURE2_ISEL, .mmu_features = MMU_FTR_TYPE_FSL_E, .icache_bsize = 32, .dcache_bsize = 32, @@ -2014,6 +2024,7 @@ static struct cpu_spec __initdata cpu_specs[] = { PPC_FEATURE_HAS_SPE_COMP | PPC_FEATURE_HAS_EFP_SINGLE_COMP | PPC_FEATURE_HAS_EFP_DOUBLE_COMP, + .cpu_user_features2 = PPC_FEATURE2_ISEL, .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS, .icache_bsize = 32, .dcache_bsize = 32, @@ -2030,6 +2041,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_name = "e500mc", .cpu_features = CPU_FTRS_E500MC, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, + .cpu_user_features2 = PPC_FEATURE2_ISEL, .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | MMU_FTR_USE_TLBILX, .icache_bsize = 64, @@ -2048,6 +2060,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_name = "e5500", .cpu_features = CPU_FTRS_E5500, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, + .cpu_user_features2 = PPC_FEATURE2_ISEL, .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | MMU_FTR_USE_TLBILX, .icache_bsize = 64, @@ -2069,6 +2082,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_features = CPU_FTRS_E6500, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_ALTIVEC_COMP, + .cpu_user_features2 = PPC_FEATURE2_ISEL, .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | MMU_FTR_USE_TLBILX, .icache_bsize = 64, diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index e514de57a125..d22e73e4618b 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -439,8 +439,6 @@ ret_from_fork: ret_from_kernel_thread: REST_NVGPRS(r1) bl schedule_tail - li r3,0 - stw r3,0(r1) mtlr r14 mr r3,r15 PPC440EP_ERR42 diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 3fe5259e2fea..51cfb8fc301f 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -33,6 +33,7 @@ #include <asm/irqflags.h> #include <asm/ftrace.h> #include <asm/hw_irq.h> +#include <asm/context_tracking.h> /* * System calls. @@ -150,7 +151,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) CURRENT_THREAD_INFO(r11, r1) ld r10,TI_FLAGS(r11) andi. r11,r10,_TIF_SYSCALL_T_OR_A - bne- syscall_dotrace + bne syscall_dotrace .Lsyscall_dotrace_cont: cmpldi 0,r0,NR_syscalls bge- syscall_enosys @@ -376,8 +377,6 @@ _GLOBAL(ret_from_fork) _GLOBAL(ret_from_kernel_thread) bl .schedule_tail REST_NVGPRS(r1) - li r3,0 - std r3,0(r1) ld r14, 0(r14) mtlr r14 mr r3,r15 @@ -634,7 +633,7 @@ _GLOBAL(ret_from_except_lite) andi. r0,r4,_TIF_NEED_RESCHED beq 1f bl .restore_interrupts - bl .schedule + SCHEDULE_USER b .ret_from_except_lite 1: bl .save_nvgprs diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 42a756eec9ff..645170a07ada 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S @@ -489,7 +489,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) */ mfspr r14,SPRN_DBSR /* check single-step/branch taken */ - andis. r15,r14,DBSR_IC@h + andis. r15,r14,(DBSR_IC|DBSR_BT)@h beq+ 1f LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) @@ -500,7 +500,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) bge+ cr1,1f /* here it looks like we got an inappropriate debug exception. */ - lis r14,DBSR_IC@h /* clear the IC event */ + lis r14,(DBSR_IC|DBSR_BT)@h /* clear the event */ rlwinm r11,r11,0,~MSR_DE /* clear DE in the CSRR1 value */ mtspr SPRN_DBSR,r14 mtspr SPRN_CSRR1,r11 @@ -555,7 +555,7 @@ kernel_dbg_exc: */ mfspr r14,SPRN_DBSR /* check single-step/branch taken */ - andis. r15,r14,DBSR_IC@h + andis. r15,r14,(DBSR_IC|DBSR_BT)@h beq+ 1f LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) @@ -566,7 +566,7 @@ kernel_dbg_exc: bge+ cr1,1f /* here it looks like we got an inappropriate debug exception. */ - lis r14,DBSR_IC@h /* clear the IC event */ + lis r14,(DBSR_IC|DBSR_BT)@h /* clear the event */ rlwinm r11,r11,0,~MSR_DE /* clear DE in the DSRR1 value */ mtspr SPRN_DBSR,r14 mtspr SPRN_DSRR1,r11 diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 466a2908bb63..611acdf30096 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/kernel.h> #include <linux/cpu.h> +#include <linux/hardirq.h> #include <asm/page.h> #include <asm/current.h> @@ -335,10 +336,13 @@ void default_machine_kexec(struct kimage *image) pr_debug("kexec: Starting switchover sequence.\n"); /* switch to a staticly allocated stack. Based on irq stack code. + * We setup preempt_count to avoid using VMX in memcpy. * XXX: the task struct will likely be invalid once we do the copy! */ kexec_stack.thread_info.task = current_thread_info()->task; kexec_stack.thread_info.flags = 0; + kexec_stack.thread_info.preempt_count = HARDIRQ_OFFSET; + kexec_stack.thread_info.cpu = current_thread_info()->cpu; /* We need a static PACA, too; copy this CPU's PACA over and switch to * it. Also poison per_cpu_offset to catch anyone using non-static diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 19e096bd0e73..e469f30e6eeb 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -657,6 +657,17 @@ _GLOBAL(__ucmpdi2) li r3,2 blr +_GLOBAL(__bswapdi2) + rotlwi r9,r4,8 + rotlwi r10,r3,8 + rlwimi r9,r4,24,0,7 + rlwimi r10,r3,24,0,7 + rlwimi r9,r4,24,16,23 + rlwimi r10,r3,24,16,23 + mr r3,r9 + mr r4,r10 + blr + _GLOBAL(abs) srawi r4,r3,31 xor r3,r3,r4 diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 5cfa8008693b..6820e45f557b 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -234,6 +234,17 @@ _GLOBAL(__flush_dcache_icache) isync blr +_GLOBAL(__bswapdi2) + srdi r8,r3,32 + rlwinm r7,r3,8,0xffffffff + rlwimi r7,r3,24,0,7 + rlwinm r9,r8,8,0xffffffff + rlwimi r7,r3,24,16,23 + rlwimi r9,r8,24,0,7 + rlwimi r9,r8,24,16,23 + sldi r7,r7,32 + or r3,r7,r9 + blr #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) /* diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index f325dc923409..6053f037ef0a 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -359,7 +359,6 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, enum pci_mmap_state mmap_state, int write_combine) { - unsigned long prot = pgprot_val(protection); /* Write combine is always 0 on non-memory space mappings. On * memory space, if the user didn't pass 1, we check for a @@ -376,9 +375,9 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, /* XXX would be nice to have a way to ask for write-through */ if (write_combine) - return pgprot_noncached_wc(prot); + return pgprot_noncached_wc(protection); else - return pgprot_noncached(prot); + return pgprot_noncached(protection); } /* @@ -786,22 +785,8 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, hose->isa_mem_size = size; } - /* We get the PCI/Mem offset from the first range or - * the, current one if the offset came from an ISA - * hole. If they don't match, bugger. - */ - if (memno == 0 || - (isa_hole >= 0 && pci_addr != 0 && - hose->pci_mem_offset == isa_mb)) - hose->pci_mem_offset = cpu_addr - pci_addr; - else if (pci_addr != 0 && - hose->pci_mem_offset != cpu_addr - pci_addr) { - printk(KERN_INFO - " \\--> Skipped (offset mismatch) !\n"); - continue; - } - /* Build resource */ + hose->mem_offset[memno] = cpu_addr - pci_addr; res = &hose->mem_resources[memno++]; res->flags = IORESOURCE_MEM; if (pci_space & 0x40000000) @@ -817,20 +802,6 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, res->child = NULL; } } - - /* If there's an ISA hole and the pci_mem_offset is -not- matching - * the ISA hole offset, then we need to remove the ISA hole from - * the resource list for that brige - */ - if (isa_hole >= 0 && hose->pci_mem_offset != isa_mb) { - unsigned int next = isa_hole + 1; - printk(KERN_INFO " Removing ISA hole at 0x%016llx\n", isa_mb); - if (next < memno) - memmove(&hose->mem_resources[isa_hole], - &hose->mem_resources[next], - sizeof(struct resource) * (memno - next)); - hose->mem_resources[--memno].flags = 0; - } } /* Decide whether to display the domain number in /proc */ @@ -845,6 +816,14 @@ int pci_proc_domain(struct pci_bus *bus) return 1; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + if (ppc_md.pcibios_root_bridge_prepare) + return ppc_md.pcibios_root_bridge_prepare(bridge); + + return 0; +} + /* This header fixup will do the resource fixup for all devices as they are * probed, but not for bridge ranges */ @@ -908,6 +887,7 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus, struct pci_controller *hose = pci_bus_to_host(bus); struct pci_dev *dev = bus->self; resource_size_t offset; + struct pci_bus_region region; u16 command; int i; @@ -917,10 +897,10 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus, /* Job is a bit different between memory and IO */ if (res->flags & IORESOURCE_MEM) { - /* If the BAR is non-0 (res != pci_mem_offset) then it's probably been - * initialized by somebody - */ - if (res->start != hose->pci_mem_offset) + pcibios_resource_to_bus(dev, ®ion, res); + + /* If the BAR is non-0 then it's probably been initialized */ + if (region.start != 0) return 0; /* The BAR is 0, let's check if memory decoding is enabled on @@ -932,11 +912,11 @@ static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus, /* Memory decoding is enabled and the BAR is 0. If any of the bridge * resources covers that starting address (0 then it's good enough for - * us for memory + * us for memory space) */ for (i = 0; i < 3; i++) { if ((hose->mem_resources[i].flags & IORESOURCE_MEM) && - hose->mem_resources[i].start == hose->pci_mem_offset) + hose->mem_resources[i].start == hose->mem_offset[i]) return 0; } @@ -1373,10 +1353,9 @@ static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus) no_io: /* Check for memory */ - offset = hose->pci_mem_offset; - pr_debug("hose mem offset: %016llx\n", (unsigned long long)offset); for (i = 0; i < 3; i++) { pres = &hose->mem_resources[i]; + offset = hose->mem_offset[i]; if (!(pres->flags & IORESOURCE_MEM)) continue; pr_debug("hose mem res: %pR\n", pres); @@ -1516,6 +1495,7 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources) { struct resource *res; + resource_size_t offset; int i; /* Hookup PHB IO resource */ @@ -1525,49 +1505,37 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose, printk(KERN_WARNING "PCI: I/O resource not set for host" " bridge %s (domain %d)\n", hose->dn->full_name, hose->global_number); -#ifdef CONFIG_PPC32 - /* Workaround for lack of IO resource only on 32-bit */ - res->start = (unsigned long)hose->io_base_virt - isa_io_base; - res->end = res->start + IO_SPACE_LIMIT; - res->flags = IORESOURCE_IO; -#endif /* CONFIG_PPC32 */ - } + } else { + offset = pcibios_io_space_offset(hose); - pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", - (unsigned long long)res->start, - (unsigned long long)res->end, - (unsigned long)res->flags); - pci_add_resource_offset(resources, res, pcibios_io_space_offset(hose)); + pr_debug("PCI: PHB IO resource = %08llx-%08llx [%lx] off 0x%08llx\n", + (unsigned long long)res->start, + (unsigned long long)res->end, + (unsigned long)res->flags, + (unsigned long long)offset); + pci_add_resource_offset(resources, res, offset); + } /* Hookup PHB Memory resources */ for (i = 0; i < 3; ++i) { res = &hose->mem_resources[i]; if (!res->flags) { - if (i > 0) - continue; printk(KERN_ERR "PCI: Memory resource 0 not set for " "host bridge %s (domain %d)\n", hose->dn->full_name, hose->global_number); -#ifdef CONFIG_PPC32 - /* Workaround for lack of MEM resource only on 32-bit */ - res->start = hose->pci_mem_offset; - res->end = (resource_size_t)-1LL; - res->flags = IORESOURCE_MEM; -#endif /* CONFIG_PPC32 */ + continue; } + offset = hose->mem_offset[i]; - pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i, + + pr_debug("PCI: PHB MEM resource %d = %08llx-%08llx [%lx] off 0x%08llx\n", i, (unsigned long long)res->start, (unsigned long long)res->end, - (unsigned long)res->flags); - pci_add_resource_offset(resources, res, hose->pci_mem_offset); - } - - pr_debug("PCI: PHB MEM offset = %016llx\n", - (unsigned long long)hose->pci_mem_offset); - pr_debug("PCI: PHB IO offset = %08lx\n", - (unsigned long)hose->io_base_virt - _IO_BASE); + (unsigned long)res->flags, + (unsigned long long)offset); + pci_add_resource_offset(resources, res, offset); + } } /* diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index e37c2152acf4..432459c817fa 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -295,7 +295,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) case IOBASE_BRIDGE_NUMBER: return (long)hose->first_busno; case IOBASE_MEMORY: - return (long)hose->pci_mem_offset; + return (long)hose->mem_offset[0]; case IOBASE_IO: return (long)hose->io_base_phys; case IOBASE_ISA_IO: diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 51a133a78a09..873050d26840 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -246,7 +246,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, case IOBASE_BRIDGE_NUMBER: return (long)hose->first_busno; case IOBASE_MEMORY: - return (long)hose->pci_mem_offset; + return (long)hose->mem_offset[0]; case IOBASE_IO: return (long)hose->io_base_phys; case IOBASE_ISA_IO: diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 78b8766fd79e..c29666586998 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -143,7 +143,8 @@ EXPORT_SYMBOL(__lshrdi3); int __ucmpdi2(unsigned long long, unsigned long long); EXPORT_SYMBOL(__ucmpdi2); #endif - +long long __bswapdi2(long long); +EXPORT_SYMBOL(__bswapdi2); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memmove); diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ceb4e7b62cf4..a902723fdc69 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -339,6 +339,13 @@ static void set_debug_reg_defaults(struct thread_struct *thread) static void prime_debug_regs(struct thread_struct *thread) { + /* + * We could have inherited MSR_DE from userspace, since + * it doesn't get cleared on exception entry. Make sure + * MSR_DE is clear before we enable any debug events. + */ + mtmsr(mfmsr() & ~MSR_DE); + mtspr(SPRN_IAC1, thread->iac1); mtspr(SPRN_IAC2, thread->iac2); #if CONFIG_PPC_ADV_DEBUG_IACS > 2 @@ -971,6 +978,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, * do some house keeping and then return from the fork or clone * system call, using the stack frame created above. */ + ((unsigned long *)sp)[0] = 0; sp -= sizeof(struct pt_regs); kregs = (struct pt_regs *) sp; sp -= STACK_FRAME_OVERHEAD; diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 3b14d320e69f..98c2fc198712 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -32,6 +32,7 @@ #include <trace/syscall.h> #include <linux/hw_breakpoint.h> #include <linux/perf_event.h> +#include <linux/context_tracking.h> #include <asm/uaccess.h> #include <asm/page.h> @@ -1788,6 +1789,8 @@ long do_syscall_trace_enter(struct pt_regs *regs) { long ret = 0; + user_exit(); + secure_computing_strict(regs->gpr[0]); if (test_thread_flag(TIF_SYSCALL_TRACE) && @@ -1832,4 +1835,6 @@ void do_syscall_trace_leave(struct pt_regs *regs) step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); + + user_enter(); } diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 1fd6e7b2f390..52add6f3e201 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/capability.h> #include <linux/delay.h> +#include <linux/cpu.h> #include <linux/smp.h> #include <linux/completion.h> #include <linux/cpumask.h> @@ -807,6 +808,95 @@ static void rtas_percpu_suspend_me(void *info) __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1); } +enum rtas_cpu_state { + DOWN, + UP, +}; + +#ifndef CONFIG_SMP +static int rtas_cpu_state_change_mask(enum rtas_cpu_state state, + cpumask_var_t cpus) +{ + if (!cpumask_empty(cpus)) { + cpumask_clear(cpus); + return -EINVAL; + } else + return 0; +} +#else +/* On return cpumask will be altered to indicate CPUs changed. + * CPUs with states changed will be set in the mask, + * CPUs with status unchanged will be unset in the mask. */ +static int rtas_cpu_state_change_mask(enum rtas_cpu_state state, + cpumask_var_t cpus) +{ + int cpu; + int cpuret = 0; + int ret = 0; + + if (cpumask_empty(cpus)) + return 0; + + for_each_cpu(cpu, cpus) { + switch (state) { + case DOWN: + cpuret = cpu_down(cpu); + break; + case UP: + cpuret = cpu_up(cpu); + break; + } + if (cpuret) { + pr_debug("%s: cpu_%s for cpu#%d returned %d.\n", + __func__, + ((state == UP) ? "up" : "down"), + cpu, cpuret); + if (!ret) + ret = cpuret; + if (state == UP) { + /* clear bits for unchanged cpus, return */ + cpumask_shift_right(cpus, cpus, cpu); + cpumask_shift_left(cpus, cpus, cpu); + break; + } else { + /* clear bit for unchanged cpu, continue */ + cpumask_clear_cpu(cpu, cpus); + } + } + } + + return ret; +} +#endif + +int rtas_online_cpus_mask(cpumask_var_t cpus) +{ + int ret; + + ret = rtas_cpu_state_change_mask(UP, cpus); + + if (ret) { + cpumask_var_t tmp_mask; + + if (!alloc_cpumask_var(&tmp_mask, GFP_TEMPORARY)) + return ret; + + /* Use tmp_mask to preserve cpus mask from first failure */ + cpumask_copy(tmp_mask, cpus); + rtas_offline_cpus_mask(tmp_mask); + free_cpumask_var(tmp_mask); + } + + return ret; +} +EXPORT_SYMBOL(rtas_online_cpus_mask); + +int rtas_offline_cpus_mask(cpumask_var_t cpus) +{ + return rtas_cpu_state_change_mask(DOWN, cpus); +} +EXPORT_SYMBOL(rtas_offline_cpus_mask); + int rtas_ibm_suspend_me(struct rtas_args *args) { long state; @@ -814,6 +904,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args) unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; struct rtas_suspend_me_data data; DECLARE_COMPLETION_ONSTACK(done); + cpumask_var_t offline_mask; + int cpuret; if (!rtas_service_present("ibm,suspend-me")) return -ENOSYS; @@ -837,11 +929,24 @@ int rtas_ibm_suspend_me(struct rtas_args *args) return 0; } + if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) + return -ENOMEM; + atomic_set(&data.working, 0); atomic_set(&data.done, 0); atomic_set(&data.error, 0); data.token = rtas_token("ibm,suspend-me"); data.complete = &done; + + /* All present CPUs must be online */ + cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask); + cpuret = rtas_online_cpus_mask(offline_mask); + if (cpuret) { + pr_err("%s: Could not bring present CPUs online.\n", __func__); + atomic_set(&data.error, cpuret); + goto out; + } + stop_topology_update(); /* Call function on all CPUs. One of us will make the @@ -857,6 +962,14 @@ int rtas_ibm_suspend_me(struct rtas_args *args) start_topology_update(); + /* Take down CPUs not online prior to suspend */ + cpuret = rtas_offline_cpus_mask(offline_mask); + if (cpuret) + pr_warn("%s: Could not restore CPUs to offline state.\n", + __func__); + +out: + free_cpumask_var(offline_mask); return atomic_read(&data.error); } #else /* CONFIG_PPC_PSERIES */ diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 5b3022470126..2f3cdb01506d 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -89,6 +89,7 @@ /* Array sizes */ #define VALIDATE_BUF_SIZE 4096 +#define VALIDATE_MSG_LEN 256 #define RTAS_MSG_MAXLEN 64 /* Quirk - RTAS requires 4k list length and block size */ @@ -466,7 +467,7 @@ static void validate_flash(struct rtas_validate_flash_t *args_buf) } static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, - char *msg) + char *msg, int msglen) { int n; @@ -474,7 +475,8 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, n = sprintf(msg, "%d\n", args_buf->update_results); if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) || (args_buf->update_results == VALIDATE_TMP_UPDATE)) - n += sprintf(msg + n, "%s\n", args_buf->buf); + n += snprintf(msg + n, msglen - n, "%s\n", + args_buf->buf); } else { n = sprintf(msg, "%d\n", args_buf->status); } @@ -486,11 +488,11 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf, { struct rtas_validate_flash_t *const args_buf = &rtas_validate_flash_data; - char msg[RTAS_MSG_MAXLEN]; + char msg[VALIDATE_MSG_LEN]; int msglen; mutex_lock(&rtas_validate_flash_mutex); - msglen = get_validate_flash_msg(args_buf, msg); + msglen = get_validate_flash_msg(args_buf, msg, VALIDATE_MSG_LEN); mutex_unlock(&rtas_validate_flash_mutex); return simple_read_from_buffer(buf, count, ppos, msg, msglen); diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index cf12eae02de5..577a8aa69c6e 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -13,6 +13,7 @@ #include <linux/signal.h> #include <linux/uprobes.h> #include <linux/key.h> +#include <linux/context_tracking.h> #include <asm/hw_breakpoint.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -24,7 +25,7 @@ * through debug.exception-trace sysctl. */ -int show_unhandled_signals = 0; +int show_unhandled_signals = 1; /* * Allocate space for the signal frame @@ -159,6 +160,8 @@ static int do_signal(struct pt_regs *regs) void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) { + user_exit(); + if (thread_info_flags & _TIF_UPROBE) uprobe_notify_resume(regs); @@ -169,4 +172,6 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); } + + user_enter(); } diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index cd6e19d263b3..8a285876aef8 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -126,11 +126,3 @@ asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags, return sys_sync_file_range(fd, offset, nbytes, flags); } - -asmlinkage long compat_sys_fanotify_mark(int fanotify_fd, unsigned int flags, - unsigned mask_hi, unsigned mask_lo, - int dfd, const char __user *pathname) -{ - u64 mask = ((u64)mask_hi << 32) | mask_lo; - return sys_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname); -} diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 3ce1f864c2d3..e68a84568b8b 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -180,7 +180,7 @@ SYSFS_PMCSETUP(dscr, SPRN_DSCR); SYSFS_PMCSETUP(pir, SPRN_PIR); static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); -static DEVICE_ATTR(spurr, 0600, show_spurr, NULL); +static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); static DEVICE_ATTR(purr, 0600, show_purr, store_purr); static DEVICE_ATTR(pir, 0400, show_pir, NULL); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 37cc40ef5043..a7a648f6b750 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -35,6 +35,7 @@ #include <linux/kdebug.h> #include <linux/debugfs.h> #include <linux/ratelimit.h> +#include <linux/context_tracking.h> #include <asm/emulated_ops.h> #include <asm/pgtable.h> @@ -667,6 +668,7 @@ int machine_check_generic(struct pt_regs *regs) void machine_check_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); int recover = 0; __get_cpu_var(irq_stat).mce_exceptions++; @@ -683,7 +685,7 @@ void machine_check_exception(struct pt_regs *regs) recover = cur_cpu_spec->machine_check(regs); if (recover > 0) - return; + goto bail; #if defined(CONFIG_8xx) && defined(CONFIG_PCI) /* the qspan pci read routines can cause machine checks -- Cort @@ -693,20 +695,23 @@ void machine_check_exception(struct pt_regs *regs) * -- BenH */ bad_page_fault(regs, regs->dar, SIGBUS); - return; + goto bail; #endif if (debugger_fault_handler(regs)) - return; + goto bail; if (check_io_access(regs)) - return; + goto bail; die("Machine check", regs, SIGBUS); /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) panic("Unrecoverable Machine check"); + +bail: + exception_exit(prev_state); } void SMIException(struct pt_regs *regs) @@ -716,20 +721,29 @@ void SMIException(struct pt_regs *regs) void unknown_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); + printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n", regs->nip, regs->msr, regs->trap); _exception(SIGTRAP, regs, 0, 0); + + exception_exit(prev_state); } void instruction_breakpoint_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); + if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5, 5, SIGTRAP) == NOTIFY_STOP) - return; + goto bail; if (debugger_iabr_match(regs)) - return; + goto bail; _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); + +bail: + exception_exit(prev_state); } void RunModeException(struct pt_regs *regs) @@ -739,15 +753,20 @@ void RunModeException(struct pt_regs *regs) void __kprobes single_step_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); + clear_single_step(regs); if (notify_die(DIE_SSTEP, "single_step", regs, 5, 5, SIGTRAP) == NOTIFY_STOP) - return; + goto bail; if (debugger_sstep(regs)) - return; + goto bail; _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); + +bail: + exception_exit(prev_state); } /* @@ -970,7 +989,10 @@ static int emulate_instruction(struct pt_regs *regs) #ifdef CONFIG_PPC64 /* Emulate the mfspr rD, DSCR. */ - if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) && + if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) == + PPC_INST_MFSPR_DSCR_USER) || + ((instword & PPC_INST_MFSPR_DSCR_MASK) == + PPC_INST_MFSPR_DSCR)) && cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mfdscr, regs); rd = (instword >> 21) & 0x1f; @@ -978,7 +1000,10 @@ static int emulate_instruction(struct pt_regs *regs) return 0; } /* Emulate the mtspr DSCR, rD. */ - if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) && + if ((((instword & PPC_INST_MTSPR_DSCR_USER_MASK) == + PPC_INST_MTSPR_DSCR_USER) || + ((instword & PPC_INST_MTSPR_DSCR_MASK) == + PPC_INST_MTSPR_DSCR)) && cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mtdscr, regs); rd = (instword >> 21) & 0x1f; @@ -999,6 +1024,7 @@ int is_valid_bugaddr(unsigned long addr) void __kprobes program_check_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); unsigned int reason = get_reason(regs); extern int do_mathemu(struct pt_regs *regs); @@ -1008,26 +1034,26 @@ void __kprobes program_check_exception(struct pt_regs *regs) if (reason & REASON_FP) { /* IEEE FP exception */ parse_fpe(regs); - return; + goto bail; } if (reason & REASON_TRAP) { /* Debugger is first in line to stop recursive faults in * rcu_lock, notify_die, or atomic_notifier_call_chain */ if (debugger_bpt(regs)) - return; + goto bail; /* trap exception */ if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) == NOTIFY_STOP) - return; + goto bail; if (!(regs->msr & MSR_PR) && /* not user-mode */ report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { regs->nip += 4; - return; + goto bail; } _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); - return; + goto bail; } #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (reason & REASON_TM) { @@ -1043,7 +1069,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) if (!user_mode(regs) && report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { regs->nip += 4; - return; + goto bail; } /* If usermode caused this, it's done something illegal and * gets a SIGILL slap on the wrist. We call it an illegal @@ -1053,7 +1079,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) */ if (user_mode(regs)) { _exception(SIGILL, regs, ILL_ILLOPN, regs->nip); - return; + goto bail; } else { printk(KERN_EMERG "Unexpected TM Bad Thing exception " "at %lx (msr 0x%x)\n", regs->nip, reason); @@ -1077,16 +1103,16 @@ void __kprobes program_check_exception(struct pt_regs *regs) switch (do_mathemu(regs)) { case 0: emulate_single_step(regs); - return; + goto bail; case 1: { int code = 0; code = __parse_fpscr(current->thread.fpscr.val); _exception(SIGFPE, regs, code, regs->nip); - return; + goto bail; } case -EFAULT: _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); - return; + goto bail; } /* fall through on any other errors */ #endif /* CONFIG_MATH_EMULATION */ @@ -1097,10 +1123,10 @@ void __kprobes program_check_exception(struct pt_regs *regs) case 0: regs->nip += 4; emulate_single_step(regs); - return; + goto bail; case -EFAULT: _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); - return; + goto bail; } } @@ -1108,10 +1134,14 @@ void __kprobes program_check_exception(struct pt_regs *regs) _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); else _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); + +bail: + exception_exit(prev_state); } void alignment_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); int sig, code, fixed = 0; /* We restore the interrupt state now */ @@ -1125,7 +1155,7 @@ void alignment_exception(struct pt_regs *regs) if (fixed == 1) { regs->nip += 4; /* skip over emulated instruction */ emulate_single_step(regs); - return; + goto bail; } /* Operand address was bad */ @@ -1140,6 +1170,9 @@ void alignment_exception(struct pt_regs *regs) _exception(sig, regs, code, regs->dar); else bad_page_fault(regs, regs->dar, sig); + +bail: + exception_exit(prev_state); } void StackOverflow(struct pt_regs *regs) @@ -1168,23 +1201,32 @@ void trace_syscall(struct pt_regs *regs) void kernel_fp_unavailable_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); + printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " "%lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); + + exception_exit(prev_state); } void altivec_unavailable_exception(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); + if (user_mode(regs)) { /* A user program has executed an altivec instruction, but this kernel doesn't support altivec. */ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); - return; + goto bail; } printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " "%lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); + +bail: + exception_exit(prev_state); } void vsx_unavailable_exception(struct pt_regs *regs) diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 13b867093499..9d3fdcd66290 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -64,6 +64,9 @@ void __init udbg_early_init(void) udbg_init_usbgecko(); #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP) udbg_init_wsp(); +#elif defined(CONFIG_PPC_EARLY_DEBUG_MEMCONS) + /* In memory console */ + udbg_init_memcons(); #elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC) udbg_init_ehv_bc(); #elif defined(CONFIG_PPC_EARLY_DEBUG_PS3GELIC) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 229951ffc351..8726779e1409 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -32,6 +32,7 @@ #include <linux/perf_event.h> #include <linux/magic.h> #include <linux/ratelimit.h> +#include <linux/context_tracking.h> #include <asm/firmware.h> #include <asm/page.h> @@ -196,6 +197,7 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault) int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) { + enum ctx_state prev_state = exception_enter(); struct vm_area_struct * vma; struct mm_struct *mm = current->mm; unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; @@ -204,6 +206,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, int trap = TRAP(regs); int is_exec = trap == 0x400; int fault; + int rc = 0; #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) /* @@ -230,28 +233,30 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, * look at it */ if (error_code & ICSWX_DSI_UCT) { - int rc = acop_handle_fault(regs, address, error_code); + rc = acop_handle_fault(regs, address, error_code); if (rc) - return rc; + goto bail; } #endif /* CONFIG_PPC_ICSWX */ if (notify_page_fault(regs)) - return 0; + goto bail; if (unlikely(debugger_fault_handler(regs))) - return 0; + goto bail; /* On a kernel SLB miss we can only check for a valid exception entry */ - if (!user_mode(regs) && (address >= TASK_SIZE)) - return SIGSEGV; + if (!user_mode(regs) && (address >= TASK_SIZE)) { + rc = SIGSEGV; + goto bail; + } #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE) || \ defined(CONFIG_PPC_BOOK3S_64)) if (error_code & DSISR_DABRMATCH) { /* breakpoint match */ do_break(regs, address, error_code); - return 0; + goto bail; } #endif @@ -260,8 +265,10 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, local_irq_enable(); if (in_atomic() || mm == NULL) { - if (!user_mode(regs)) - return SIGSEGV; + if (!user_mode(regs)) { + rc = SIGSEGV; + goto bail; + } /* in_atomic() in user mode is really bad, as is current->mm == NULL. */ printk(KERN_EMERG "Page fault in user mode with " @@ -417,9 +424,11 @@ good_area: */ fault = handle_mm_fault(mm, vma, address, flags); if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) { - int rc = mm_fault_error(regs, address, fault); + rc = mm_fault_error(regs, address, fault); if (rc >= MM_FAULT_RETURN) - return rc; + goto bail; + else + rc = 0; } /* @@ -454,7 +463,7 @@ good_area: } up_read(&mm->mmap_sem); - return 0; + goto bail; bad_area: up_read(&mm->mmap_sem); @@ -463,7 +472,7 @@ bad_area_nosemaphore: /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { _exception(SIGSEGV, regs, code, address); - return 0; + goto bail; } if (is_exec && (error_code & DSISR_PROTFAULT)) @@ -471,7 +480,11 @@ bad_area_nosemaphore: " page (%lx) - exploit attempt? (uid: %d)\n", address, from_kuid(&init_user_ns, current_uid())); - return SIGSEGV; + rc = SIGSEGV; + +bail: + exception_exit(prev_state); + return rc; } diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 3e4c4ed19335..e303a6d74e3a 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -33,6 +33,7 @@ #include <linux/init.h> #include <linux/signal.h> #include <linux/memblock.h> +#include <linux/context_tracking.h> #include <asm/processor.h> #include <asm/pgtable.h> @@ -954,6 +955,7 @@ void hash_failure_debug(unsigned long ea, unsigned long access, */ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) { + enum ctx_state prev_state = exception_enter(); pgd_t *pgdir; unsigned long vsid; struct mm_struct *mm; @@ -973,7 +975,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) mm = current->mm; if (! mm) { DBG_LOW(" user region with no mm !\n"); - return 1; + rc = 1; + goto bail; } psize = get_slice_psize(mm, ea); ssize = user_segment_size(ea); @@ -992,19 +995,23 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) /* Not a valid range * Send the problem up to do_page_fault */ - return 1; + rc = 1; + goto bail; } DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid); /* Bad address. */ if (!vsid) { DBG_LOW("Bad address!\n"); - return 1; + rc = 1; + goto bail; } /* Get pgdir */ pgdir = mm->pgd; - if (pgdir == NULL) - return 1; + if (pgdir == NULL) { + rc = 1; + goto bail; + } /* Check CPU locality */ tmp = cpumask_of(smp_processor_id()); @@ -1027,7 +1034,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift); if (ptep == NULL || !pte_present(*ptep)) { DBG_LOW(" no PTE !\n"); - return 1; + rc = 1; + goto bail; } /* Add _PAGE_PRESENT to the required access perm */ @@ -1038,13 +1046,16 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) */ if (access & ~pte_val(*ptep)) { DBG_LOW(" no access !\n"); - return 1; + rc = 1; + goto bail; } #ifdef CONFIG_HUGETLB_PAGE - if (hugeshift) - return __hash_page_huge(ea, access, vsid, ptep, trap, local, + if (hugeshift) { + rc = __hash_page_huge(ea, access, vsid, ptep, trap, local, ssize, hugeshift, psize); + goto bail; + } #endif /* CONFIG_HUGETLB_PAGE */ #ifndef CONFIG_PPC_64K_PAGES @@ -1124,6 +1135,9 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) pte_val(*(ptep + PTRS_PER_PTE))); #endif DBG_LOW(" -> rc=%d\n", rc); + +bail: + exception_exit(prev_state); return rc; } EXPORT_SYMBOL_GPL(hash_page); @@ -1230,6 +1244,7 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, * unmapping it first, it may see the speculated version. */ if (local && cpu_has_feature(CPU_FTR_TM) && + current->thread.regs && MSR_TM_ACTIVE(current->thread.regs->msr)) { tm_enable(); tm_abort(TM_CAUSE_TLBI); @@ -1258,6 +1273,8 @@ void flush_hash_range(unsigned long number, int local) */ void low_hash_fault(struct pt_regs *regs, unsigned long address, int rc) { + enum ctx_state prev_state = exception_enter(); + if (user_mode(regs)) { #ifdef CONFIG_PPC_SUBPAGE_PROT if (rc == -2) @@ -1267,6 +1284,8 @@ void low_hash_fault(struct pt_regs *regs, unsigned long address, int rc) _exception(SIGBUS, regs, BUS_ADRERR, address); } else bad_page_fault(regs, address, SIGBUS); + + exception_exit(prev_state); } long hpte_insert_repeating(unsigned long hash, unsigned long vpn, diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index c2787bf779ca..a90b9c458990 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -215,7 +215,8 @@ static void __meminit vmemmap_create_mapping(unsigned long start, unsigned long phys) { int mapped = htab_bolt_mapping(start, start + page_size, phys, - PAGE_KERNEL, mmu_vmemmap_psize, + pgprot_val(PAGE_KERNEL), + mmu_vmemmap_psize, mmu_kernel_ssize); BUG_ON(mapped < 0); } diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index c627843c5b2e..426180b84978 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -13,11 +13,13 @@ #include <linux/perf_event.h> #include <linux/percpu.h> #include <linux/hardirq.h> +#include <linux/uaccess.h> #include <asm/reg.h> #include <asm/pmc.h> #include <asm/machdep.h> #include <asm/firmware.h> #include <asm/ptrace.h> +#include <asm/code-patching.h> #define BHRB_MAX_ENTRIES 32 #define BHRB_TARGET 0x0000000000000002 @@ -100,6 +102,10 @@ static inline int siar_valid(struct pt_regs *regs) return 1; } +static inline void power_pmu_bhrb_enable(struct perf_event *event) {} +static inline void power_pmu_bhrb_disable(struct perf_event *event) {} +void power_pmu_flush_branch_stack(void) {} +static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {} #endif /* CONFIG_PPC32 */ static bool regs_use_siar(struct pt_regs *regs) @@ -308,6 +314,159 @@ static inline int siar_valid(struct pt_regs *regs) return 1; } + +/* Reset all possible BHRB entries */ +static void power_pmu_bhrb_reset(void) +{ + asm volatile(PPC_CLRBHRB); +} + +static void power_pmu_bhrb_enable(struct perf_event *event) +{ + struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); + + if (!ppmu->bhrb_nr) + return; + + /* Clear BHRB if we changed task context to avoid data leaks */ + if (event->ctx->task && cpuhw->bhrb_context != event->ctx) { + power_pmu_bhrb_reset(); + cpuhw->bhrb_context = event->ctx; + } + cpuhw->bhrb_users++; +} + +static void power_pmu_bhrb_disable(struct perf_event *event) +{ + struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); + + if (!ppmu->bhrb_nr) + return; + + cpuhw->bhrb_users--; + WARN_ON_ONCE(cpuhw->bhrb_users < 0); + + if (!cpuhw->disabled && !cpuhw->bhrb_users) { + /* BHRB cannot be turned off when other + * events are active on the PMU. + */ + + /* avoid stale pointer */ + cpuhw->bhrb_context = NULL; + } +} + +/* Called from ctxsw to prevent one process's branch entries to + * mingle with the other process's entries during context switch. + */ +void power_pmu_flush_branch_stack(void) +{ + if (ppmu->bhrb_nr) + power_pmu_bhrb_reset(); +} +/* Calculate the to address for a branch */ +static __u64 power_pmu_bhrb_to(u64 addr) +{ + unsigned int instr; + int ret; + __u64 target; + + if (is_kernel_addr(addr)) + return branch_target((unsigned int *)addr); + + /* Userspace: need copy instruction here then translate it */ + pagefault_disable(); + ret = __get_user_inatomic(instr, (unsigned int __user *)addr); + if (ret) { + pagefault_enable(); + return 0; + } + pagefault_enable(); + + target = branch_target(&instr); + if ((!target) || (instr & BRANCH_ABSOLUTE)) + return target; + + /* Translate relative branch target from kernel to user address */ + return target - (unsigned long)&instr + addr; +} + +/* Processing BHRB entries */ +void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) +{ + u64 val; + u64 addr; + int r_index, u_index, pred; + + r_index = 0; + u_index = 0; + while (r_index < ppmu->bhrb_nr) { + /* Assembly read function */ + val = read_bhrb(r_index++); + if (!val) + /* Terminal marker: End of valid BHRB entries */ + break; + else { + addr = val & BHRB_EA; + pred = val & BHRB_PREDICTION; + + if (!addr) + /* invalid entry */ + continue; + + /* Branches are read most recent first (ie. mfbhrb 0 is + * the most recent branch). + * There are two types of valid entries: + * 1) a target entry which is the to address of a + * computed goto like a blr,bctr,btar. The next + * entry read from the bhrb will be branch + * corresponding to this target (ie. the actual + * blr/bctr/btar instruction). + * 2) a from address which is an actual branch. If a + * target entry proceeds this, then this is the + * matching branch for that target. If this is not + * following a target entry, then this is a branch + * where the target is given as an immediate field + * in the instruction (ie. an i or b form branch). + * In this case we need to read the instruction from + * memory to determine the target/to address. + */ + + if (val & BHRB_TARGET) { + /* Target branches use two entries + * (ie. computed gotos/XL form) + */ + cpuhw->bhrb_entries[u_index].to = addr; + cpuhw->bhrb_entries[u_index].mispred = pred; + cpuhw->bhrb_entries[u_index].predicted = ~pred; + + /* Get from address in next entry */ + val = read_bhrb(r_index++); + addr = val & BHRB_EA; + if (val & BHRB_TARGET) { + /* Shouldn't have two targets in a + row.. Reset index and try again */ + r_index--; + addr = 0; + } + cpuhw->bhrb_entries[u_index].from = addr; + } else { + /* Branches to immediate field + (ie I or B form) */ + cpuhw->bhrb_entries[u_index].from = addr; + cpuhw->bhrb_entries[u_index].to = + power_pmu_bhrb_to(addr); + cpuhw->bhrb_entries[u_index].mispred = pred; + cpuhw->bhrb_entries[u_index].predicted = ~pred; + } + u_index++; + + } + } + cpuhw->bhrb_stack.nr = u_index; + return; +} + #endif /* CONFIG_PPC64 */ static void perf_event_interrupt(struct pt_regs *regs); @@ -904,47 +1063,6 @@ static int collect_events(struct perf_event *group, int max_count, return n; } -/* Reset all possible BHRB entries */ -static void power_pmu_bhrb_reset(void) -{ - asm volatile(PPC_CLRBHRB); -} - -void power_pmu_bhrb_enable(struct perf_event *event) -{ - struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); - - if (!ppmu->bhrb_nr) - return; - - /* Clear BHRB if we changed task context to avoid data leaks */ - if (event->ctx->task && cpuhw->bhrb_context != event->ctx) { - power_pmu_bhrb_reset(); - cpuhw->bhrb_context = event->ctx; - } - cpuhw->bhrb_users++; -} - -void power_pmu_bhrb_disable(struct perf_event *event) -{ - struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); - - if (!ppmu->bhrb_nr) - return; - - cpuhw->bhrb_users--; - WARN_ON_ONCE(cpuhw->bhrb_users < 0); - - if (!cpuhw->disabled && !cpuhw->bhrb_users) { - /* BHRB cannot be turned off when other - * events are active on the PMU. - */ - - /* avoid stale pointer */ - cpuhw->bhrb_context = NULL; - } -} - /* * Add a event to the PMU. * If all events are not already frozen, then we disable and @@ -1180,15 +1298,6 @@ int power_pmu_commit_txn(struct pmu *pmu) return 0; } -/* Called from ctxsw to prevent one process's branch entries to - * mingle with the other process's entries during context switch. - */ -void power_pmu_flush_branch_stack(void) -{ - if (ppmu->bhrb_nr) - power_pmu_bhrb_reset(); -} - /* * Return 1 if we might be able to put event on a limited PMC, * or 0 if not. @@ -1458,77 +1567,6 @@ struct pmu power_pmu = { .flush_branch_stack = power_pmu_flush_branch_stack, }; -/* Processing BHRB entries */ -void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) -{ - u64 val; - u64 addr; - int r_index, u_index, target, pred; - - r_index = 0; - u_index = 0; - while (r_index < ppmu->bhrb_nr) { - /* Assembly read function */ - val = read_bhrb(r_index); - - /* Terminal marker: End of valid BHRB entries */ - if (val == 0) { - break; - } else { - /* BHRB field break up */ - addr = val & BHRB_EA; - pred = val & BHRB_PREDICTION; - target = val & BHRB_TARGET; - - /* Probable Missed entry: Not applicable for POWER8 */ - if ((addr == 0) && (target == 0) && (pred == 1)) { - r_index++; - continue; - } - - /* Real Missed entry: Power8 based missed entry */ - if ((addr == 0) && (target == 1) && (pred == 1)) { - r_index++; - continue; - } - - /* Reserved condition: Not a valid entry */ - if ((addr == 0) && (target == 1) && (pred == 0)) { - r_index++; - continue; - } - - /* Is a target address */ - if (val & BHRB_TARGET) { - /* First address cannot be a target address */ - if (r_index == 0) { - r_index++; - continue; - } - - /* Update target address for the previous entry */ - cpuhw->bhrb_entries[u_index - 1].to = addr; - cpuhw->bhrb_entries[u_index - 1].mispred = pred; - cpuhw->bhrb_entries[u_index - 1].predicted = ~pred; - - /* Dont increment u_index */ - r_index++; - } else { - /* Update address, flags for current entry */ - cpuhw->bhrb_entries[u_index].from = addr; - cpuhw->bhrb_entries[u_index].mispred = pred; - cpuhw->bhrb_entries[u_index].predicted = ~pred; - - /* Successfully popullated one entry */ - u_index++; - r_index++; - } - } - } - cpuhw->bhrb_stack.nr = u_index; - return; -} - /* * A counter has overflowed; update its count and record * things if requested. Note that interrupts are hard-disabled diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index bd40bbb15e14..6e287f1294fa 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig @@ -138,7 +138,6 @@ config PPC4xx_GPIO bool "PPC4xx GPIO support" depends on 40x select ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO help Enable gpiolib support for ppc40x based boards diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 7be93367d92f..d6c7506ec7d9 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -248,7 +248,6 @@ config PPC4xx_GPIO bool "PPC4xx GPIO support" depends on 44x select ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO help Enable gpiolib support for ppc440 based boards diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 8f02b05f4c96..efdd37c775ad 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -203,7 +203,6 @@ config GE_IMP3A select DEFAULT_UIMAGE select SWIOTLB select MMIO_NVRAM - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GE_FPGA help @@ -328,7 +327,7 @@ config B4_QDS select PPC_E500MC select PHYS_64BIT select SWIOTLB - select GENERIC_GPIO + select GPIOLIB select ARCH_REQUIRE_GPIOLIB select HAS_RAPIDIO select PPC_EPAPR_HV_PIC diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 7a6279e38213..1afd1e4a2dd2 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -37,7 +37,6 @@ config GEF_PPC9A bool "GE PPC9A" select DEFAULT_UIMAGE select MMIO_NVRAM - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GE_FPGA help @@ -47,7 +46,6 @@ config GEF_SBC310 bool "GE SBC310" select DEFAULT_UIMAGE select MMIO_NVRAM - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GE_FPGA help @@ -57,7 +55,6 @@ config GEF_SBC610 bool "GE SBC610" select DEFAULT_UIMAGE select MMIO_NVRAM - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GE_FPGA select HAS_RAPIDIO diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index 1fb0b3cddeb3..8dec3c0911ad 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig @@ -114,7 +114,6 @@ config 8xx_COPYBACK config 8xx_GPIO bool "GPIO API Support" - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help Saying Y here will cause the ports on an MPC8xx processor to be used diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 34d224be93ba..b62aab3e22ec 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -128,7 +128,7 @@ config PPC_RTAS_DAEMON config RTAS_PROC bool "Proc interface to RTAS" - depends on PPC_RTAS + depends on PPC_RTAS && PROC_FS default y config RTAS_FLASH @@ -302,7 +302,6 @@ config QUICC_ENGINE config QE_GPIO bool "QE GPIO support" depends on QUICC_ENGINE - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help Say Y here if you're going to use hardware that connects to the @@ -315,7 +314,6 @@ config CPM2 select PPC_LIB_RHEAP select PPC_PCI_CHOICE select ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO help The CPM2 (Communications Processor Module) is a coprocessor on embedded CPUs made by Freescale. Selecting this option means that @@ -353,7 +351,6 @@ config OF_RTC config SIMPLE_GPIO bool "Support for simple, memory-mapped GPIO controllers" depends on PPC - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help Say Y here to support simple, memory-mapped GPIO controllers. @@ -364,7 +361,6 @@ config SIMPLE_GPIO config MCU_MPC8349EMITX bool "MPC8349E-mITX MCU driver" depends on I2C=y && PPC_83xx - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help Say Y here to enable soft power-off functionality on the Freescale diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index e56bb651da1a..946306b1bb4e 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -550,7 +550,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev) */ iommu = cell_iommu_for_node(dev_to_node(dev)); if (iommu == NULL || list_empty(&iommu->windows)) { - printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", + dev_err(dev, "iommu: missing iommu for %s (node %d)\n", of_node_full_name(dev->of_node), dev_to_node(dev)); return NULL; } diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 8b1213993b10..f85db3a69b4a 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -715,7 +715,7 @@ static ssize_t spu_stat_show(struct device *dev, spu->stats.libassist); } -static DEVICE_ATTR(stat, 0644, spu_stat_show, NULL); +static DEVICE_ATTR(stat, 0444, spu_stat_show, NULL); #ifdef CONFIG_KEXEC diff --git a/arch/powerpc/platforms/embedded6xx/mpc10x.h b/arch/powerpc/platforms/embedded6xx/mpc10x.h index b30a6a3b5bd2..b290b63661f1 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc10x.h +++ b/arch/powerpc/platforms/embedded6xx/mpc10x.h @@ -81,17 +81,6 @@ #define MPC10X_MAPB_PCI_MEM_OFFSET (MPC10X_MAPB_ISA_MEM_BASE - \ MPC10X_MAPB_PCI_MEM_START) -/* Set hose members to values appropriate for the mem map used */ -#define MPC10X_SETUP_HOSE(hose, map) { \ - (hose)->pci_mem_offset = MPC10X_MAP##map##_PCI_MEM_OFFSET; \ - (hose)->io_space.start = MPC10X_MAP##map##_PCI_IO_START; \ - (hose)->io_space.end = MPC10X_MAP##map##_PCI_IO_END; \ - (hose)->mem_space.start = MPC10X_MAP##map##_PCI_MEM_START; \ - (hose)->mem_space.end = MPC10X_MAP##map##_PCI_MEM_END; \ - (hose)->io_base_virt = (void *)MPC10X_MAP##map##_ISA_IO_BASE; \ -} - - /* Miscellaneous Configuration register offsets */ #define MPC10X_CFG_PIR_REG 0x09 #define MPC10X_CFG_PIR_HOST_BRIDGE 0x00 diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 2b8af75abc23..cf7009b8c7b6 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -824,6 +824,7 @@ static void __init parse_region_decode(struct pci_controller *hose, hose->mem_resources[cur].name = hose->dn->full_name; hose->mem_resources[cur].start = base; hose->mem_resources[cur].end = end; + hose->mem_offset[cur] = 0; DBG(" %d: 0x%08lx-0x%08lx\n", cur, base, end); } else { DBG(" : -0x%08lx\n", end); @@ -866,7 +867,6 @@ static void __init setup_u3_ht(struct pci_controller* hose) hose->io_resource.start = 0; hose->io_resource.end = 0x003fffff; hose->io_resource.flags = IORESOURCE_IO; - hose->pci_mem_offset = 0; hose->first_busno = 0; hose->last_busno = 0xef; diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index aaa0dba49471..628c564ceadb 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c @@ -15,6 +15,7 @@ #include <linux/of.h> #include <linux/of_platform.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <asm/opal.h> #include <asm/firmware.h> @@ -28,13 +29,14 @@ struct opal { static struct device_node *opal_node; static DEFINE_SPINLOCK(opal_write_lock); extern u64 opal_mc_secondary_handler[]; +static unsigned int *opal_irqs; +static unsigned int opal_irq_count; int __init early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data) { const void *basep, *entryp; unsigned long basesz, entrysz; - u64 glue; if (depth != 1 || strcmp(uname, "ibm,opal") != 0) return 0; @@ -54,13 +56,27 @@ int __init early_init_dt_scan_opal(unsigned long node, opal.entry, entryp, entrysz); powerpc_firmware_features |= FW_FEATURE_OPAL; - if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { + if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { + powerpc_firmware_features |= FW_FEATURE_OPALv2; + powerpc_firmware_features |= FW_FEATURE_OPALv3; + printk("OPAL V3 detected !\n"); + } else if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { powerpc_firmware_features |= FW_FEATURE_OPALv2; printk("OPAL V2 detected !\n"); } else { printk("OPAL V1 detected !\n"); } + return 1; +} + +static int __init opal_register_exception_handlers(void) +{ + u64 glue; + + if (!(powerpc_firmware_features & FW_FEATURE_OPAL)) + return -ENODEV; + /* Hookup some exception handlers. We use the fwnmi area at 0x7000 * to provide the glue space to OPAL */ @@ -74,9 +90,11 @@ int __init early_init_dt_scan_opal(unsigned long node, glue += 128; opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); - return 1; + return 0; } +early_initcall(opal_register_exception_handlers); + int opal_get_chars(uint32_t vtermno, char *buf, int count) { s64 len, rc; @@ -133,6 +151,13 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { len = total_len; rc = opal_console_write(vtermno, &len, data); + + /* Closed or other error drop */ + if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && + rc != OPAL_BUSY_EVENT) { + written = total_len; + break; + } if (rc == OPAL_SUCCESS) { total_len -= len; data += len; @@ -305,6 +330,8 @@ static int __init opal_init(void) irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); pr_debug("opal: Found %d interrupts reserved for OPAL\n", irqs ? (irqlen / 4) : 0); + opal_irq_count = irqlen / 4; + opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int), GFP_KERNEL); for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { unsigned int hwirq = be32_to_cpup(irqs); unsigned int irq = irq_create_mapping(NULL, hwirq); @@ -316,7 +343,19 @@ static int __init opal_init(void) if (rc) pr_warning("opal: Error %d requesting irq %d" " (0x%x)\n", rc, irq, hwirq); + opal_irqs[i] = irq; } return 0; } subsys_initcall(opal_init); + +void opal_shutdown(void) +{ + unsigned int i; + + for (i = 0; i < opal_irq_count; i++) { + if (opal_irqs[i]) + free_irq(opal_irqs[i], 0); + opal_irqs[i] = 0; + } +} diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 8c6c9cf91c13..3937aaae5bc4 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -915,11 +915,14 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, index++; } } else if (res->flags & IORESOURCE_MEM) { + /* WARNING: Assumes M32 is mem region 0 in PHB. We need to + * harden that algorithm when we start supporting M64 + */ region.start = res->start - - hose->pci_mem_offset - + hose->mem_offset[0] - phb->ioda.m32_pci_base; region.end = res->end - - hose->pci_mem_offset - + hose->mem_offset[0] - phb->ioda.m32_pci_base; index = region.start / phb->ioda.m32_segsize; @@ -1045,6 +1048,12 @@ static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus, return phb->ioda.pe_rmap[(bus->number << 8) | devfn]; } +static void pnv_pci_ioda_shutdown(struct pnv_phb *phb) +{ + opal_pci_reset(phb->opal_id, OPAL_PCI_IODA_TABLE_RESET, + OPAL_ASSERT_RESET); +} + void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) { struct pci_controller *hose; @@ -1089,7 +1098,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) /* Detect specific models for error handling */ if (of_device_is_compatible(np, "ibm,p7ioc-pciex")) phb->model = PNV_PHB_MODEL_P7IOC; - else if (of_device_is_compatible(np, "ibm,p8-pciex")) + else if (of_device_is_compatible(np, "ibm,power8-pciex")) phb->model = PNV_PHB_MODEL_PHB3; else phb->model = PNV_PHB_MODEL_UNKNOWN; @@ -1115,8 +1124,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) phb->ioda.m32_size += 0x10000; phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe; - phb->ioda.m32_pci_base = hose->mem_resources[0].start - - hose->pci_mem_offset; + phb->ioda.m32_pci_base = hose->mem_resources[0].start - hose->mem_offset[0]; phb->ioda.io_size = hose->pci_io_size; phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe; phb->ioda.io_pci_base = 0; /* XXX calculate this ? */ @@ -1176,6 +1184,9 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) /* Setup TCEs */ phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; + /* Setup shutdown function for kexec */ + phb->shutdown = pnv_pci_ioda_shutdown; + /* Setup MSI support */ pnv_pci_init_ioda_msis(phb); diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 55dfca844ddf..163bd7422f1c 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -450,6 +450,18 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev) pnv_pci_dma_fallback_setup(hose, pdev); } +void pnv_pci_shutdown(void) +{ + struct pci_controller *hose; + + list_for_each_entry(hose, &hose_list, list_node) { + struct pnv_phb *phb = hose->private_data; + + if (phb && phb->shutdown) + phb->shutdown(phb); + } +} + /* Fixup wrong class code in p7ioc and p8 root complex */ static void pnv_p7ioc_rc_quirk(struct pci_dev *dev) { diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 48dc4bb856a1..25d76c4df50b 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h @@ -86,6 +86,7 @@ struct pnv_phb { void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev); void (*fixup_phb)(struct pci_controller *hose); u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); + void (*shutdown)(struct pnv_phb *phb); union { struct { @@ -158,4 +159,5 @@ extern void pnv_pci_init_ioda_hub(struct device_node *np); extern void pnv_pci_init_ioda2_phb(struct device_node *np); extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, u64 *startp, u64 *endp); + #endif /* __POWERNV_PCI_H */ diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h index 8a9df7f9667e..a1c6f83fc391 100644 --- a/arch/powerpc/platforms/powernv/powernv.h +++ b/arch/powerpc/platforms/powernv/powernv.h @@ -9,8 +9,10 @@ static inline void pnv_smp_init(void) { } #ifdef CONFIG_PCI extern void pnv_pci_init(void); +extern void pnv_pci_shutdown(void); #else static inline void pnv_pci_init(void) { } +static inline void pnv_pci_shutdown(void) { } #endif #endif /* _POWERNV_H */ diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index db1ad1c8f68f..d4459bfc92f7 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -78,7 +78,9 @@ static void pnv_show_cpuinfo(struct seq_file *m) if (root) model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: PowerNV %s\n", model); - if (firmware_has_feature(FW_FEATURE_OPALv2)) + if (firmware_has_feature(FW_FEATURE_OPALv3)) + seq_printf(m, "firmware\t: OPAL v3\n"); + else if (firmware_has_feature(FW_FEATURE_OPALv2)) seq_printf(m, "firmware\t: OPAL v2\n"); else if (firmware_has_feature(FW_FEATURE_OPAL)) seq_printf(m, "firmware\t: OPAL v1\n"); @@ -126,6 +128,17 @@ static void pnv_progress(char *s, unsigned short hex) { } +static void pnv_shutdown(void) +{ + /* Let the PCI code clear up IODA tables */ + pnv_pci_shutdown(); + + /* And unregister all OPAL interrupts so they don't fire + * up while we kexec + */ + opal_shutdown(); +} + #ifdef CONFIG_KEXEC static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) { @@ -187,6 +200,7 @@ define_machine(powernv) { .init_IRQ = pnv_init_IRQ, .show_cpuinfo = pnv_show_cpuinfo, .progress = pnv_progress, + .machine_shutdown = pnv_shutdown, .power_save = power7_idle, .calibrate_decr = generic_calibrate_decr, #ifdef CONFIG_KEXEC diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 0bdc735db16f..88c9459c3e07 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c @@ -71,16 +71,68 @@ int pnv_smp_kick_cpu(int nr) BUG_ON(nr < 0 || nr >= NR_CPUS); - /* On OPAL v2 the CPU are still spinning inside OPAL itself, - * get them back now + /* + * If we already started or OPALv2 is not supported, we just + * kick the CPU via the PACA */ - if (!paca[nr].cpu_start && firmware_has_feature(FW_FEATURE_OPALv2)) { - pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu); - rc = opal_start_cpu(pcpu, start_here); - if (rc != OPAL_SUCCESS) - pr_warn("OPAL Error %ld starting CPU %d\n", + if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2)) + goto kick; + + /* + * At this point, the CPU can either be spinning on the way in + * from kexec or be inside OPAL waiting to be started for the + * first time. OPAL v3 allows us to query OPAL to know if it + * has the CPUs, so we do that + */ + if (firmware_has_feature(FW_FEATURE_OPALv3)) { + uint8_t status; + + rc = opal_query_cpu_status(pcpu, &status); + if (rc != OPAL_SUCCESS) { + pr_warn("OPAL Error %ld querying CPU %d state\n", rc, nr); + return -ENODEV; + } + + /* + * Already started, just kick it, probably coming from + * kexec and spinning + */ + if (status == OPAL_THREAD_STARTED) + goto kick; + + /* + * Available/inactive, let's kick it + */ + if (status == OPAL_THREAD_INACTIVE) { + pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", + nr, pcpu); + rc = opal_start_cpu(pcpu, start_here); + if (rc != OPAL_SUCCESS) { + pr_warn("OPAL Error %ld starting CPU %d\n", + rc, nr); + return -ENODEV; + } + } else { + /* + * An unavailable CPU (or any other unknown status) + * shouldn't be started. It should also + * not be in the possible map but currently it can + * happen + */ + pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable" + " (status %d)...\n", nr, pcpu, status); + return -ENODEV; + } + } else { + /* + * On OPAL v2, we just kick it and hope for the best, + * we must not test the error from opal_start_cpu() or + * we would fail to get CPUs from kexec. + */ + opal_start_cpu(pcpu, start_here); } + kick: return smp_generic_kick_cpu(nr); } diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 9a0941bc4d31..023b288f895b 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -18,6 +18,7 @@ config PPC_PSERIES select PPC_PCI_CHOICE if EXPERT select ZLIB_DEFLATE select PPC_DOORBELL + select HAVE_CONTEXT_TRACKING default y config PPC_SPLPAR diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index e5b084723131..420524e6f8c9 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -24,6 +24,7 @@ static int query_token, change_token; #define RTAS_RESET_FN 2 #define RTAS_CHANGE_MSI_FN 3 #define RTAS_CHANGE_MSIX_FN 4 +#define RTAS_CHANGE_32MSI_FN 5 static struct pci_dn *get_pdn(struct pci_dev *pdev) { @@ -58,7 +59,8 @@ static int rtas_change_msi(struct pci_dn *pdn, u32 func, u32 num_irqs) seq_num = 1; do { - if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN) + if (func == RTAS_CHANGE_MSI_FN || func == RTAS_CHANGE_MSIX_FN || + func == RTAS_CHANGE_32MSI_FN) rc = rtas_call(change_token, 6, 4, rtas_ret, addr, BUID_HI(buid), BUID_LO(buid), func, num_irqs, seq_num); @@ -426,9 +428,12 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type) */ again: if (type == PCI_CAP_ID_MSI) { - rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); + if (pdn->force_32bit_msi) + rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec); + else + rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec); - if (rc < 0) { + if (rc < 0 && !pdn->force_32bit_msi) { pr_debug("rtas_msi: trying the old firmware call.\n"); rc = rtas_change_msi(pdn, RTAS_CHANGE_FN, nvec); } @@ -512,3 +517,13 @@ static int rtas_msi_init(void) return 0; } arch_initcall(rtas_msi_init); + +static void quirk_radeon(struct pci_dev *dev) +{ + struct pci_dn *pdn = get_pdn(dev); + + if (pdn) + pdn->force_32bit_msi = 1; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon); diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 0b580f413a9a..5f93856cdf47 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -108,3 +108,56 @@ static void fixup_winbond_82c105(struct pci_dev* dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_winbond_82c105); + +int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct device_node *dn, *pdn; + struct pci_bus *bus; + const uint32_t *pcie_link_speed_stats; + + bus = bridge->bus; + + dn = pcibios_get_phb_of_node(bus); + if (!dn) + return 0; + + for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) { + pcie_link_speed_stats = (const uint32_t *) of_get_property(pdn, + "ibm,pcie-link-speed-stats", NULL); + if (pcie_link_speed_stats) + break; + } + + of_node_put(pdn); + + if (!pcie_link_speed_stats) { + pr_err("no ibm,pcie-link-speed-stats property\n"); + return 0; + } + + switch (pcie_link_speed_stats[0]) { + case 0x01: + bus->max_bus_speed = PCIE_SPEED_2_5GT; + break; + case 0x02: + bus->max_bus_speed = PCIE_SPEED_5_0GT; + break; + default: + bus->max_bus_speed = PCI_SPEED_UNKNOWN; + break; + } + + switch (pcie_link_speed_stats[1]) { + case 0x01: + bus->cur_bus_speed = PCIE_SPEED_2_5GT; + break; + case 0x02: + bus->cur_bus_speed = PCIE_SPEED_5_0GT; + break; + default: + bus->cur_bus_speed = PCI_SPEED_UNKNOWN; + break; + } + + return 0; +} diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 8af71e4cc17f..c2a3a258001c 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -63,4 +63,8 @@ extern int dlpar_detach_node(struct device_node *); /* Snooze Delay, pseries_idle */ DECLARE_PER_CPU(long, smt_snooze_delay); +/* PCI root bridge prepare function override for pseries */ +struct pci_host_bridge; +int pseries_root_bridge_prepare(struct pci_host_bridge *bridge); + #endif /* _PSERIES_PSERIES_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ac932a9eb440..c11c8238797c 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -466,6 +466,8 @@ static void __init pSeries_setup_arch(void) else ppc_md.enable_pmcs = power4_enable_pmcs; + ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; + if (firmware_has_feature(FW_FEATURE_SET_MODE)) { long rc; if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) { diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index 47226e04126d..5f997e79d570 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/cpu.h> #include <linux/delay.h> #include <linux/suspend.h> #include <linux/stat.h> @@ -126,11 +127,15 @@ static ssize_t store_hibernate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + cpumask_var_t offline_mask; int rc; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) + return -ENOMEM; + stream_id = simple_strtoul(buf, NULL, 16); do { @@ -140,15 +145,32 @@ static ssize_t store_hibernate(struct device *dev, } while (rc == -EAGAIN); if (!rc) { + /* All present CPUs must be online */ + cpumask_andnot(offline_mask, cpu_present_mask, + cpu_online_mask); + rc = rtas_online_cpus_mask(offline_mask); + if (rc) { + pr_err("%s: Could not bring present CPUs online.\n", + __func__); + goto out; + } + stop_topology_update(); rc = pm_suspend(PM_SUSPEND_MEM); start_topology_update(); + + /* Take down CPUs not online prior to suspend */ + if (!rtas_offline_cpus_mask(offline_mask)) + pr_warn("%s: Could not restore CPUs to offline " + "state.\n", __func__); } stream_id = 0; if (!rc) rc = count; +out: + free_cpumask_var(offline_mask); return rc; } diff --git a/arch/powerpc/platforms/wsp/ics.c b/arch/powerpc/platforms/wsp/ics.c index 97fe82ee8633..2d3b1dd9571d 100644 --- a/arch/powerpc/platforms/wsp/ics.c +++ b/arch/powerpc/platforms/wsp/ics.c @@ -361,7 +361,7 @@ static int wsp_chip_set_affinity(struct irq_data *d, xive = xive_set_server(xive, get_irq_server(ics, hw_irq)); wsp_ics_set_xive(ics, hw_irq, xive); - return 0; + return IRQ_SET_MASK_OK; } static struct irq_chip wsp_irq_chip = { diff --git a/arch/powerpc/platforms/wsp/wsp_pci.c b/arch/powerpc/platforms/wsp/wsp_pci.c index 8e22f561d171..62cb527493e7 100644 --- a/arch/powerpc/platforms/wsp/wsp_pci.c +++ b/arch/powerpc/platforms/wsp/wsp_pci.c @@ -502,7 +502,7 @@ static void __init wsp_pcie_configure_hw(struct pci_controller *hose) (~(hose->mem_resources[0].end - hose->mem_resources[0].start)) & 0x3ffffff0000ul); out_be64(hose->cfg_data + PCIE_REG_M32A_START_ADDR, - (hose->mem_resources[0].start - hose->pci_mem_offset) | 1); + (hose->mem_resources[0].start - hose->mem_offset[0]) | 1); /* Clear all TVT entries * diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index b0a518e97599..99464a7bdb3b 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -64,6 +64,8 @@ endif obj-$(CONFIG_PPC_SCOM) += scom.o +obj-$(CONFIG_PPC_EARLY_DEBUG_MEMCONS) += udbg_memcons.o + subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror obj-$(CONFIG_PPC_XICS) += xics/ diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index 6e0e1005227f..9cd0e60716fe 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c @@ -81,7 +81,7 @@ int ehv_pic_set_affinity(struct irq_data *d, const struct cpumask *dest, ev_int_set_config(src, config, prio, cpuid); spin_unlock_irqrestore(&ehv_pic_lock, flags); - return 0; + return IRQ_SET_MASK_OK; } static unsigned int ehv_pic_type_to_vecpri(unsigned int type) diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index cffe7edac858..028ac1f71b51 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -178,7 +178,7 @@ static void setup_pci_atmu(struct pci_controller *hose) struct ccsr_pci __iomem *pci = hose->private_data; int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4; u64 mem, sz, paddr_hi = 0; - u64 paddr_lo = ULLONG_MAX; + u64 offset = 0, paddr_lo = ULLONG_MAX; u32 pcicsrbar = 0, pcicsrbar_sz; u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; @@ -208,8 +208,9 @@ static void setup_pci_atmu(struct pci_controller *hose) paddr_lo = min(paddr_lo, (u64)hose->mem_resources[i].start); paddr_hi = max(paddr_hi, (u64)hose->mem_resources[i].end); - n = setup_one_atmu(pci, j, &hose->mem_resources[i], - hose->pci_mem_offset); + /* We assume all memory resources have the same offset */ + offset = hose->mem_offset[i]; + n = setup_one_atmu(pci, j, &hose->mem_resources[i], offset); if (n < 0 || j >= 5) { pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i); @@ -239,8 +240,8 @@ static void setup_pci_atmu(struct pci_controller *hose) } /* convert to pci address space */ - paddr_hi -= hose->pci_mem_offset; - paddr_lo -= hose->pci_mem_offset; + paddr_hi -= offset; + paddr_lo -= offset; if (paddr_hi == paddr_lo) { pr_err("%s: No outbound window space\n", name); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index d30e6a676c89..0a13ecb270c7 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -836,7 +836,7 @@ int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, mpic_physmask(mask)); } - return 0; + return IRQ_SET_MASK_OK; } static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) @@ -1001,8 +1001,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, if (hw == mpic->spurious_vec) return -EINVAL; - if (mpic->protected && test_bit(hw, mpic->protected)) - return -EINVAL; + if (mpic->protected && test_bit(hw, mpic->protected)) { + pr_warning("mpic: Mapping of source 0x%x failed, " + "source protected by firmware !\n",\ + (unsigned int)hw); + return -EPERM; + } #ifdef CONFIG_SMP else if (hw >= mpic->ipi_vecs[0]) { @@ -1029,8 +1033,12 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, if (mpic_map_error_int(mpic, virq, hw)) return 0; - if (hw >= mpic->num_sources) + if (hw >= mpic->num_sources) { + pr_warning("mpic: Mapping of source 0x%x failed, " + "source out of range !\n",\ + (unsigned int)hw); return -EINVAL; + } mpic_msi_reserve_hwirq(mpic, hw); diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index 56e8b3c3c890..64603a10b863 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -257,6 +257,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, /* Setup outbound memory windows */ for (i = j = 0; i < 3; i++) { struct resource *res = &hose->mem_resources[i]; + resource_size_t offset = hose->mem_offset[i]; /* we only care about memory windows */ if (!(res->flags & IORESOURCE_MEM)) @@ -270,7 +271,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, /* Configure the resource */ if (ppc4xx_setup_one_pci_PMM(hose, reg, res->start, - res->start - hose->pci_mem_offset, + res->start - offset, resource_size(res), res->flags, j) == 0) { @@ -279,7 +280,7 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose, /* If the resource PCI address is 0 then we have our * ISA memory hole */ - if (res->start == hose->pci_mem_offset) + if (res->start == offset) found_isa_hole = 1; } } @@ -457,6 +458,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, /* Setup outbound memory windows */ for (i = j = 0; i < 3; i++) { struct resource *res = &hose->mem_resources[i]; + resource_size_t offset = hose->mem_offset[i]; /* we only care about memory windows */ if (!(res->flags & IORESOURCE_MEM)) @@ -470,7 +472,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, /* Configure the resource */ if (ppc4xx_setup_one_pcix_POM(hose, reg, res->start, - res->start - hose->pci_mem_offset, + res->start - offset, resource_size(res), res->flags, j) == 0) { @@ -479,7 +481,7 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose, /* If the resource PCI address is 0 then we have our * ISA memory hole */ - if (res->start == hose->pci_mem_offset) + if (res->start == offset) found_isa_hole = 1; } } @@ -1792,6 +1794,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, /* Setup outbound memory windows */ for (i = j = 0; i < 3; i++) { struct resource *res = &hose->mem_resources[i]; + resource_size_t offset = hose->mem_offset[i]; /* we only care about memory windows */ if (!(res->flags & IORESOURCE_MEM)) @@ -1805,7 +1808,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, /* Configure the resource */ if (ppc4xx_setup_one_pciex_POM(port, hose, mbase, res->start, - res->start - hose->pci_mem_offset, + res->start - offset, resource_size(res), res->flags, j) == 0) { @@ -1814,7 +1817,7 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, /* If the resource PCI address is 0 then we have our * ISA memory hole */ - if (res->start == hose->pci_mem_offset) + if (res->start == offset) found_isa_hole = 1; } } diff --git a/arch/powerpc/sysdev/udbg_memcons.c b/arch/powerpc/sysdev/udbg_memcons.c new file mode 100644 index 000000000000..ce5a7b489e4b --- /dev/null +++ b/arch/powerpc/sysdev/udbg_memcons.c @@ -0,0 +1,105 @@ +/* + * A udbg backend which logs messages and reads input from in memory + * buffers. + * + * The console output can be read from memcons_output which is a + * circular buffer whose next write position is stored in memcons.output_pos. + * + * Input may be passed by writing into the memcons_input buffer when it is + * empty. The input buffer is empty when both input_pos == input_start and + * *input_start == '\0'. + * + * Copyright (C) 2003-2005 Anton Blanchard and Milton Miller, IBM Corp + * Copyright (C) 2013 Alistair Popple, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/barrier.h> +#include <asm/page.h> +#include <asm/processor.h> +#include <asm/udbg.h> + +struct memcons { + char *output_start; + char *output_pos; + char *output_end; + char *input_start; + char *input_pos; + char *input_end; +}; + +static char memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE]; +static char memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE]; + +struct memcons memcons = { + .output_start = memcons_output, + .output_pos = memcons_output, + .output_end = &memcons_output[CONFIG_PPC_MEMCONS_OUTPUT_SIZE], + .input_start = memcons_input, + .input_pos = memcons_input, + .input_end = &memcons_input[CONFIG_PPC_MEMCONS_INPUT_SIZE], +}; + +void memcons_putc(char c) +{ + char *new_output_pos; + + *memcons.output_pos = c; + wmb(); + new_output_pos = memcons.output_pos + 1; + if (new_output_pos >= memcons.output_end) + new_output_pos = memcons.output_start; + + memcons.output_pos = new_output_pos; +} + +int memcons_getc_poll(void) +{ + char c; + char *new_input_pos; + + if (*memcons.input_pos) { + c = *memcons.input_pos; + + new_input_pos = memcons.input_pos + 1; + if (new_input_pos >= memcons.input_end) + new_input_pos = memcons.input_start; + else if (*new_input_pos == '\0') + new_input_pos = memcons.input_start; + + *memcons.input_pos = '\0'; + wmb(); + memcons.input_pos = new_input_pos; + return c; + } + + return -1; +} + +int memcons_getc(void) +{ + int c; + + while (1) { + c = memcons_getc_poll(); + if (c == -1) + cpu_relax(); + else + break; + } + + return c; +} + +void udbg_init_memcons(void) +{ + udbg_putc = memcons_putc; + udbg_getc = memcons_getc; + udbg_getc_poll = memcons_getc_poll; +} diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c index f7e8609df0d5..39d72212655e 100644 --- a/arch/powerpc/sysdev/xics/ics-opal.c +++ b/arch/powerpc/sysdev/xics/ics-opal.c @@ -148,7 +148,7 @@ static int ics_opal_set_affinity(struct irq_data *d, __func__, d->irq, hw_irq, server, rc); return -1; } - return 0; + return IRQ_SET_MASK_OK; } static struct irq_chip ics_opal_irq_chip = { diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 5f7d7ba2874c..7a539f4f5e30 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -21,6 +21,7 @@ #include <linux/module.h> #include <linux/seq_file.h> #include <linux/mount.h> +#include <linux/aio.h> #include <asm/ebcdic.h> #include "hypfs.h" diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 2d72d9e96c15..9cb1b975b353 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -793,10 +793,6 @@ ENTRY(sys32_stime_wrapper) llgtr %r2,%r2 # long * jg compat_sys_stime # branch to system call -ENTRY(sys32_sysctl_wrapper) - llgtr %r2,%r2 # struct compat_sysctl_args * - jg compat_sys_sysctl - ENTRY(sys32_fstat64_wrapper) llgfr %r2,%r2 # unsigned long llgtr %r3,%r3 # struct stat64 * @@ -1349,15 +1345,6 @@ ENTRY(sys_fanotify_init_wrapper) llgfr %r3,%r3 # unsigned int jg sys_fanotify_init # branch to system call -ENTRY(sys_fanotify_mark_wrapper) - lgfr %r2,%r2 # int - llgfr %r3,%r3 # unsigned int - sllg %r4,%r4,32 # get high word of 64bit mask - lr %r4,%r5 # get low word of 64bit mask - llgfr %r5,%r6 # unsigned int - llgt %r6,164(%r15) # char * - jg sys_fanotify_mark # branch to system call - ENTRY(sys_prlimit64_wrapper) lgfr %r2,%r2 # pid_t llgfr %r3,%r3 # unsigned int diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 9f214e992eed..913410bd74a3 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -157,7 +157,7 @@ SYSCALL(sys_readv,sys_readv,compat_sys_readv_wrapper) /* 145 */ SYSCALL(sys_writev,sys_writev,compat_sys_writev_wrapper) SYSCALL(sys_getsid,sys_getsid,sys32_getsid_wrapper) SYSCALL(sys_fdatasync,sys_fdatasync,sys32_fdatasync_wrapper) -SYSCALL(sys_sysctl,sys_sysctl,sys32_sysctl_wrapper) +SYSCALL(sys_sysctl,sys_sysctl,compat_sys_sysctl) SYSCALL(sys_mlock,sys_mlock,sys32_mlock_wrapper) /* 150 */ SYSCALL(sys_munlock,sys_munlock,sys32_munlock_wrapper) SYSCALL(sys_mlockall,sys_mlockall,sys32_mlockall_wrapper) @@ -341,7 +341,7 @@ SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev) SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */ SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper) SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper) -SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper) +SYSCALL(sys_fanotify_mark,sys_fanotify_mark,compat_sys_fanotify_mark) SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper) SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */ SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 78d8ace57272..8c868cf2cf93 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -93,9 +93,6 @@ config GENERIC_CSUM config GENERIC_HWEIGHT def_bool y -config GENERIC_GPIO - def_bool n - config GENERIC_CALIBRATE_DELAY bool diff --git a/arch/sh/boards/mach-sdk7786/Makefile b/arch/sh/boards/mach-sdk7786/Makefile index 8ae56e9560ac..45d32e3590b9 100644 --- a/arch/sh/boards/mach-sdk7786/Makefile +++ b/arch/sh/boards/mach-sdk7786/Makefile @@ -1,4 +1,4 @@ obj-y := fpga.o irq.o nmi.o setup.o -obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_GPIOLIB) += gpio.o obj-$(CONFIG_HAVE_SRAM_POOL) += sram.o diff --git a/arch/sh/boards/mach-x3proto/Makefile b/arch/sh/boards/mach-x3proto/Makefile index 708c21c919ff..0cbe3d02dea3 100644 --- a/arch/sh/boards/mach-x3proto/Makefile +++ b/arch/sh/boards/mach-x3proto/Makefile @@ -1,3 +1,3 @@ obj-y += setup.o ilsel.o -obj-$(CONFIG_GENERIC_GPIO) += gpio.o +obj-$(CONFIG_GPIOLIB) += gpio.o diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile index 7fdc102d0dd6..990195d98456 100644 --- a/arch/sh/kernel/cpu/sh2a/Makefile +++ b/arch/sh/kernel/cpu/sh2a/Makefile @@ -21,4 +21,4 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7203) := pinmux-sh7203.o pinmux-$(CONFIG_CPU_SUBTYPE_SH7264) := pinmux-sh7264.o pinmux-$(CONFIG_CPU_SUBTYPE_SH7269) := pinmux-sh7269.o -obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) +obj-$(CONFIG_GPIOLIB) += $(pinmux-y) diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c index 1825b0bd523d..4c17fb6970b1 100644 --- a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c +++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c @@ -9,7 +9,9 @@ * for more details. */ +#include <linux/bug.h> #include <linux/init.h> +#include <linux/ioport.h> #include <linux/kernel.h> #include <cpu/pfc.h> diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 6f13f33a35ff..d3634ae7b71a 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -30,4 +30,4 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7712) := clock-sh7712.o pinmux-$(CONFIG_CPU_SUBTYPE_SH7720) := pinmux-sh7720.o obj-y += $(clock-y) -obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) +obj-$(CONFIG_GPIOLIB) += $(pinmux-y) diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 8fc6ec2be2fa..0705df775208 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -47,6 +47,6 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SHX3) := pinmux-shx3.o obj-y += $(clock-y) obj-$(CONFIG_SMP) += $(smp-y) -obj-$(CONFIG_GENERIC_GPIO) += $(pinmux-y) +obj-$(CONFIG_GPIOLIB) += $(pinmux-y) obj-$(CONFIG_PERF_EVENTS) += perf_event.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += ubc.o diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index a639c0d07b8b..9ac9f1666339 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -137,11 +137,6 @@ config GENERIC_ISA_DMA bool default y if SPARC32 -config GENERIC_GPIO - bool - help - Generic GPIO API support - config ARCH_SUPPORTS_DEBUG_PAGEALLOC def_bool y if SPARC64 diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 9b40c9c12a0c..6cfc1b09ec25 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -253,24 +253,15 @@ void __init leon_smp_done(void) /* Free unneeded trap tables */ if (!cpu_present(1)) { - ClearPageReserved(virt_to_page(&trapbase_cpu1)); - init_page_count(virt_to_page(&trapbase_cpu1)); - free_page((unsigned long)&trapbase_cpu1); - totalram_pages++; + free_reserved_page(virt_to_page(&trapbase_cpu1)); num_physpages++; } if (!cpu_present(2)) { - ClearPageReserved(virt_to_page(&trapbase_cpu2)); - init_page_count(virt_to_page(&trapbase_cpu2)); - free_page((unsigned long)&trapbase_cpu2); - totalram_pages++; + free_reserved_page(virt_to_page(&trapbase_cpu2)); num_physpages++; } if (!cpu_present(3)) { - ClearPageReserved(virt_to_page(&trapbase_cpu3)); - init_page_count(virt_to_page(&trapbase_cpu3)); - free_page((unsigned long)&trapbase_cpu3); - totalram_pages++; + free_reserved_page(virt_to_page(&trapbase_cpu3)); num_physpages++; } /* Ok, they are spinning and ready to go. */ diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S index 2e680b5245c9..f7c72b6efc27 100644 --- a/arch/sparc/kernel/sys32.S +++ b/arch/sparc/kernel/sys32.S @@ -239,15 +239,6 @@ do_sys_accept4: /* sys_accept4(int, struct sockaddr *, int *, int) */ nop nop - .globl sys32_fanotify_mark -sys32_fanotify_mark: - sethi %hi(sys_fanotify_mark), %g1 - sllx %o2, 32, %o2 - or %o2, %o3, %o2 - mov %o4, %o3 - jmpl %g1 + %lo(sys_fanotify_mark), %g0 - mov %o5, %o4 - .section __ex_table,"a" .align 4 .word 1b, __retl_efault, 2b, __retl_efault diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 8fd932080215..6d81597064b6 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -84,7 +84,7 @@ sys_call_table32: .word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1 /*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init -/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime +/*330*/ .word compat_sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev /*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index 4490c397bb5b..af472cf7c69a 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -366,45 +366,14 @@ void __init mem_init(void) void free_initmem (void) { - unsigned long addr; - unsigned long freed; - - addr = (unsigned long)(&__init_begin); - freed = (unsigned long)(&__init_end) - addr; - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - struct page *p; - - memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); - p = virt_to_page(addr); - - ClearPageReserved(p); - init_page_count(p); - __free_page(p); - totalram_pages++; - num_physpages++; - } - printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n", - freed >> 10); + num_physpages += free_initmem_default(POISON_FREE_INITMEM); } #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - if (start < end) - printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", - (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - struct page *p; - - memset((void *)start, POISON_FREE_INITMEM, PAGE_SIZE); - p = virt_to_page(start); - - ClearPageReserved(p); - init_page_count(p); - __free_page(p); - totalram_pages++; - num_physpages++; - } + num_physpages += free_reserved_area(start, end, POISON_FREE_INITMEM, + "initrd"); } #endif diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index cf72a8a5b3aa..a7171997adfd 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -2059,8 +2059,7 @@ void __init mem_init(void) /* We subtract one to account for the mem_map_zero page * allocated below. */ - totalram_pages -= 1; - num_physpages = totalram_pages; + num_physpages = totalram_pages - 1; /* * Set up the zero page, mark it reserved, so that page count @@ -2071,7 +2070,7 @@ void __init mem_init(void) prom_printf("paging_init: Cannot alloc zero page.\n"); prom_halt(); } - SetPageReserved(mem_map_zero); + mark_page_reserved(mem_map_zero); codepages = (((unsigned long) _etext) - ((unsigned long) _start)); codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; @@ -2111,37 +2110,22 @@ void free_initmem(void) initend = (unsigned long)(__init_end) & PAGE_MASK; for (; addr < initend; addr += PAGE_SIZE) { unsigned long page; - struct page *p; page = (addr + ((unsigned long) __va(kern_base)) - ((unsigned long) KERNBASE)); memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); - if (do_free) { - p = virt_to_page(page); - - ClearPageReserved(p); - init_page_count(p); - __free_page(p); - totalram_pages++; - } + if (do_free) + free_reserved_page(virt_to_page(page)); } } #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - if (start < end) - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - struct page *p = virt_to_page(start); - - ClearPageReserved(p); - init_page_count(p); - __free_page(p); - totalram_pages++; - } + num_physpages += free_reserved_area(start, end, POISON_FREE_INITMEM, + "initrd"); } #endif diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 5b6a40dd5556..3aa37669ff8c 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -355,11 +355,17 @@ config HARDWALL config KERNEL_PL int "Processor protection level for kernel" range 1 2 - default "1" + default 2 if TILEGX + default 1 if !TILEGX ---help--- - This setting determines the processor protection level the - kernel will be built to run at. Generally you should use - the default value here. + Since MDE 4.2, the Tilera hypervisor runs the kernel + at PL2 by default. If running under an older hypervisor, + or as a KVM guest, you must run at PL1. (The current + hypervisor may also be recompiled with "make HV_PL=2" to + allow it to run a kernel at PL1, but clients running at PL1 + are not expected to be supported indefinitely.) + + If you're not sure, don't change the default. source "arch/tile/gxio/Kconfig" diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h index ccd847e2347f..837dca5328c2 100644 --- a/arch/tile/include/hv/hypervisor.h +++ b/arch/tile/include/hv/hypervisor.h @@ -107,7 +107,22 @@ #define HV_DISPATCH_ENTRY_SIZE 32 /** Version of the hypervisor interface defined by this file */ -#define _HV_VERSION 11 +#define _HV_VERSION 13 + +/** Last version of the hypervisor interface with old hv_init() ABI. + * + * The change from version 12 to version 13 corresponds to launching + * the client by default at PL2 instead of PL1 (corresponding to the + * hv itself running at PL3 instead of PL2). To make this explicit, + * the hv_init() API was also extended so the client can report its + * desired PL, resulting in a more helpful failure diagnostic. If you + * call hv_init() with _HV_VERSION_OLD_HV_INIT and omit the client_pl + * argument, the hypervisor will assume client_pl = 1. + * + * Note that this is a deprecated solution and we do not expect to + * support clients of the Tilera hypervisor running at PL1 indefinitely. + */ +#define _HV_VERSION_OLD_HV_INIT 12 /* Index into hypervisor interface dispatch code blocks. * @@ -377,7 +392,11 @@ typedef int HV_Errno; #ifndef __ASSEMBLER__ /** Pass HV_VERSION to hv_init to request this version of the interface. */ -typedef enum { HV_VERSION = _HV_VERSION } HV_VersionNumber; +typedef enum { + HV_VERSION = _HV_VERSION, + HV_VERSION_OLD_HV_INIT = _HV_VERSION_OLD_HV_INIT, + +} HV_VersionNumber; /** Initializes the hypervisor. * @@ -385,9 +404,11 @@ typedef enum { HV_VERSION = _HV_VERSION } HV_VersionNumber; * that this program expects, typically HV_VERSION. * @param chip_num Architecture number of the chip the client was built for. * @param chip_rev_num Revision number of the chip the client was built for. + * @param client_pl Privilege level the client is built for + * (not required if interface_version_number == HV_VERSION_OLD_HV_INIT). */ void hv_init(HV_VersionNumber interface_version_number, - int chip_num, int chip_rev_num); + int chip_num, int chip_rev_num, int client_pl); /** Queries we can make for hv_sysconf(). diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S index f71bfeeaf1a9..ac115307e5e4 100644 --- a/arch/tile/kernel/head_32.S +++ b/arch/tile/kernel/head_32.S @@ -38,7 +38,7 @@ ENTRY(_start) movei r2, TILE_CHIP_REV } { - moveli r0, _HV_VERSION + moveli r0, _HV_VERSION_OLD_HV_INIT jal hv_init } /* Get a reasonable default ASID in r0 */ diff --git a/arch/tile/kernel/head_64.S b/arch/tile/kernel/head_64.S index f9a2734f7b82..6093964fa5c7 100644 --- a/arch/tile/kernel/head_64.S +++ b/arch/tile/kernel/head_64.S @@ -34,13 +34,19 @@ ENTRY(_start) /* Notify the hypervisor of what version of the API we want */ { +#if KERNEL_PL == 1 && _HV_VERSION == 13 + /* Support older hypervisors by asking for API version 12. */ + movei r0, _HV_VERSION_OLD_HV_INIT +#else + movei r0, _HV_VERSION +#endif movei r1, TILE_CHIP - movei r2, TILE_CHIP_REV } { - moveli r0, _HV_VERSION - jal hv_init + movei r2, TILE_CHIP_REV + movei r3, KERNEL_PL } + jal hv_init /* Get a reasonable default ASID in r0 */ { move r0, zero diff --git a/arch/tile/lib/spinlock_32.c b/arch/tile/lib/spinlock_32.c index b16ac49a968e..b34f79aada48 100644 --- a/arch/tile/lib/spinlock_32.c +++ b/arch/tile/lib/spinlock_32.c @@ -101,7 +101,7 @@ EXPORT_SYMBOL(arch_spin_unlock_wait); * preserve the semantic that the same read lock can be acquired in an * interrupt context. */ -inline int arch_read_trylock(arch_rwlock_t *rwlock) +int arch_read_trylock(arch_rwlock_t *rwlock) { u32 val; __insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1); diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 41bf72073ccc..879990cb66c6 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -87,7 +87,7 @@ static DEFINE_MUTEX(ubd_lock); static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */ static int ubd_open(struct block_device *bdev, fmode_t mode); -static int ubd_release(struct gendisk *disk, fmode_t mode); +static void ubd_release(struct gendisk *disk, fmode_t mode); static int ubd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -1138,7 +1138,7 @@ out: return err; } -static int ubd_release(struct gendisk *disk, fmode_t mode) +static void ubd_release(struct gendisk *disk, fmode_t mode) { struct ubd *ubd_dev = disk->private_data; @@ -1146,7 +1146,6 @@ static int ubd_release(struct gendisk *disk, fmode_t mode) if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); mutex_unlock(&ubd_mutex); - return 0; } static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index 2943e3acdf0c..41bcc0013442 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig @@ -23,9 +23,6 @@ config UNICORE32 designs licensed by PKUnity Ltd. Please see web page at <http://www.pkunity.com/>. -config GENERIC_GPIO - def_bool y - config GENERIC_CSUM def_bool y @@ -156,7 +153,7 @@ source "mm/Kconfig" config LEDS def_bool y - depends on GENERIC_GPIO + depends on GPIOLIB config ALIGNMENT_TRAP def_bool y @@ -219,7 +216,6 @@ if ARCH_PUV3 config PUV3_GPIO bool depends on !ARCH_FPGA - select GENERIC_GPIO select GPIO_SYSFS default y diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c index cfe79c9529b3..f9e862539314 100644 --- a/arch/unicore32/kernel/sys.c +++ b/arch/unicore32/kernel/sys.c @@ -28,19 +28,11 @@ #include <asm/syscalls.h> #include <asm/cacheflush.h> -/* Note: used by the compat code even in 64-bit Linux. */ -SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, - unsigned long, prot, unsigned long, flags, - unsigned long, fd, unsigned long, off_4k) -{ - return sys_mmap_pgoff(addr, len, prot, flags, fd, - off_4k); -} - /* Provide the actual syscall number to call mapping. */ #undef __SYSCALL #define __SYSCALL(nr, call) [nr] = (call), +#define sys_mmap2 sys_mmap_pgoff /* Note that we don't include <linux/unistd.h> but <asm/unistd.h> */ void *sys_call_table[__NR_syscalls] = { [0 ... __NR_syscalls-1] = sys_ni_syscall, diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5db2117ae288..685692c94f05 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -108,7 +108,6 @@ config X86 select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC) select GENERIC_TIME_VSYSCALL if X86_64 select KTIME_SCALAR if X86_32 - select ALWAYS_USE_PERSISTENT_CLOCK select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER select HAVE_CONTEXT_TRACKING if X86_64 @@ -174,9 +173,6 @@ config GENERIC_BUG_RELATIVE_POINTERS config GENERIC_HWEIGHT def_bool y -config GENERIC_GPIO - bool - config ARCH_MAY_HAVE_PC_FDC def_bool y depends on ISA_DMA_API diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 4e4907c67d92..8e0ceecdc957 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -243,12 +243,3 @@ asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_lo, return sys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo, ((u64)len_hi << 32) | len_lo); } - -asmlinkage long sys32_fanotify_mark(int fanotify_fd, unsigned int flags, - u32 mask_lo, u32 mask_hi, - int fd, const char __user *pathname) -{ - return sys_fanotify_mark(fanotify_fd, flags, - ((u64)mask_hi << 32) | mask_lo, - fd, pathname); -} diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h index 2dbe4a721ce5..cad82c9c2fde 100644 --- a/arch/x86/include/asm/rwsem.h +++ b/arch/x86/include/asm/rwsem.h @@ -105,8 +105,8 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) asm volatile("# beginning down_write\n\t" LOCK_PREFIX " xadd %1,(%2)\n\t" /* adds 0xffff0001, returns the old value */ - " test %1,%1\n\t" - /* was the count 0 before? */ + " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" + /* was the active mask 0 before? */ " jz 1f\n" " call call_rwsem_down_write_failed\n" "1:\n" @@ -126,11 +126,25 @@ static inline void __down_write(struct rw_semaphore *sem) */ static inline int __down_write_trylock(struct rw_semaphore *sem) { - long ret = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, - RWSEM_ACTIVE_WRITE_BIAS); - if (ret == RWSEM_UNLOCKED_VALUE) - return 1; - return 0; + long result, tmp; + asm volatile("# beginning __down_write_trylock\n\t" + " mov %0,%1\n\t" + "1:\n\t" + " test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" + /* was the active mask 0 before? */ + " jnz 2f\n\t" + " mov %1,%2\n\t" + " add %3,%2\n\t" + LOCK_PREFIX " cmpxchg %2,%0\n\t" + " jnz 1b\n\t" + "2:\n\t" + " sete %b1\n\t" + " movzbl %b1, %k1\n\t" + "# ending __down_write_trylock\n\t" + : "+m" (sem->count), "=&a" (result), "=&r" (tmp) + : "er" (RWSEM_ACTIVE_WRITE_BIAS) + : "memory", "cc"); + return result; } /* diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index 0ef202e232d6..82c34ee25a65 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h @@ -50,9 +50,6 @@ asmlinkage long sys32_fallocate(int, int, unsigned, asmlinkage long sys32_sigreturn(void); asmlinkage long sys32_rt_sigreturn(void); -asmlinkage long sys32_fanotify_mark(int, unsigned int, u32, u32, int, - const char __user *); - #endif /* CONFIG_COMPAT */ #endif /* _ASM_X86_SYS_IA32_H */ diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index 5f87b35fd2ef..2917a6452c49 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h @@ -37,8 +37,8 @@ asmlinkage long sys_get_thread_area(struct user_desc __user *); unsigned long sys_sigreturn(void); /* kernel/vm86_32.c */ -int sys_vm86old(struct vm86_struct __user *); -int sys_vm86(unsigned long, unsigned long); +asmlinkage long sys_vm86old(struct vm86_struct __user *); +asmlinkage long sys_vm86(unsigned long, unsigned long); #else /* CONFIG_X86_32 */ diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index b3a4866661c5..2af848dfa754 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -120,6 +120,9 @@ #define MSR_CORE_C6_RESIDENCY 0x000003fd #define MSR_CORE_C7_RESIDENCY 0x000003fe #define MSR_PKG_C2_RESIDENCY 0x0000060d +#define MSR_PKG_C8_RESIDENCY 0x00000630 +#define MSR_PKG_C9_RESIDENCY 0x00000631 +#define MSR_PKG_C10_RESIDENCY 0x00000632 /* Run Time Average Power Limiting (RAPL) Interface */ diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index dab95a85f7f8..55b67614ed94 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -34,7 +34,7 @@ extern pgd_t early_level4_pgt[PTRS_PER_PGD]; extern pmd_t early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD]; static unsigned int __initdata next_early_pgt = 2; -pmdval_t __initdata early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX); +pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX); /* Wipe all early page tables except for the kernel symbol map */ static void __init reset_early_page_tables(void) diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c index d893e8ed8ac9..2e9e12871c2b 100644 --- a/arch/x86/kernel/microcode_intel_early.c +++ b/arch/x86/kernel/microcode_intel_early.c @@ -487,6 +487,7 @@ static inline void show_saved_mc(void) #endif #if defined(CONFIG_MICROCODE_INTEL_EARLY) && defined(CONFIG_HOTPLUG_CPU) +static DEFINE_MUTEX(x86_cpu_microcode_mutex); /* * Save this mc into mc_saved_data. So it will be loaded early when a CPU is * hot added or resumes. @@ -507,7 +508,7 @@ int save_mc_for_early(u8 *mc) * Hold hotplug lock so mc_saved_data is not accessed by a CPU in * hotplug. */ - cpu_hotplug_driver_lock(); + mutex_lock(&x86_cpu_microcode_mutex); mc_saved_count_init = mc_saved_data.mc_saved_count; mc_saved_count = mc_saved_data.mc_saved_count; @@ -544,7 +545,7 @@ int save_mc_for_early(u8 *mc) } out: - cpu_hotplug_driver_unlock(); + mutex_unlock(&x86_cpu_microcode_mutex); return ret; } diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 607af0d4d5ef..4e7a37ff03ab 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -312,6 +312,8 @@ void arch_cpu_idle(void) { if (cpuidle_idle_call()) x86_idle(); + else + local_irq_enable(); } /* @@ -368,9 +370,6 @@ void amd_e400_remove_cpu(int cpu) */ static void amd_e400_idle(void) { - if (need_resched()) - return; - if (!amd_e400_c1e_detected) { u32 lo, hi; diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 1cf5766dde16..e8edcf52e069 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -33,6 +33,7 @@ #include <linux/capability.h> #include <linux/errno.h> #include <linux/interrupt.h> +#include <linux/syscalls.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/signal.h> @@ -48,7 +49,6 @@ #include <asm/io.h> #include <asm/tlbflush.h> #include <asm/irq.h> -#include <asm/syscalls.h> /* * Known problems: @@ -202,36 +202,32 @@ out: static int do_vm86_irq_handling(int subfunction, int irqnumber); static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); -int sys_vm86old(struct vm86_struct __user *v86) +SYSCALL_DEFINE1(vm86old, struct vm86_struct __user *, v86) { struct kernel_vm86_struct info; /* declare this _on top_, * this avoids wasting of stack space. * This remains on the stack until we * return to 32 bit user space. */ - struct task_struct *tsk; - int tmp, ret = -EPERM; + struct task_struct *tsk = current; + int tmp; - tsk = current; if (tsk->thread.saved_sp0) - goto out; + return -EPERM; tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, offsetof(struct kernel_vm86_struct, vm86plus) - sizeof(info.regs)); - ret = -EFAULT; if (tmp) - goto out; + return -EFAULT; memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus); info.regs32 = current_pt_regs(); tsk->thread.vm86_info = v86; do_sys_vm86(&info, tsk); - ret = 0; /* we never return here */ -out: - return ret; + return 0; /* we never return here */ } -int sys_vm86(unsigned long cmd, unsigned long arg) +SYSCALL_DEFINE2(vm86, unsigned long, cmd, unsigned long, arg) { struct kernel_vm86_struct info; /* declare this _on top_, * this avoids wasting of stack space. @@ -239,7 +235,7 @@ int sys_vm86(unsigned long cmd, unsigned long arg) * return to 32 bit user space. */ struct task_struct *tsk; - int tmp, ret; + int tmp; struct vm86plus_struct __user *v86; tsk = current; @@ -248,8 +244,7 @@ int sys_vm86(unsigned long cmd, unsigned long arg) case VM86_FREE_IRQ: case VM86_GET_IRQ_BITS: case VM86_GET_AND_RESET_IRQ: - ret = do_vm86_irq_handling(cmd, (int)arg); - goto out; + return do_vm86_irq_handling(cmd, (int)arg); case VM86_PLUS_INSTALL_CHECK: /* * NOTE: on old vm86 stuff this will return the error @@ -257,28 +252,23 @@ int sys_vm86(unsigned long cmd, unsigned long arg) * interpreted as (invalid) address to vm86_struct. * So the installation check works. */ - ret = 0; - goto out; + return 0; } /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */ - ret = -EPERM; if (tsk->thread.saved_sp0) - goto out; + return -EPERM; v86 = (struct vm86plus_struct __user *)arg; tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, offsetof(struct kernel_vm86_struct, regs32) - sizeof(info.regs)); - ret = -EFAULT; if (tmp) - goto out; + return -EFAULT; info.regs32 = current_pt_regs(); info.vm86plus.is_vm86pus = 1; tsk->thread.vm86_info = (struct vm86_struct __user *)v86; do_sys_vm86(&info, tsk); - ret = 0; /* we never return here */ -out: - return ret; + return 0; /* we never return here */ } diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8e517bba6a7c..8db0010ed150 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -60,6 +60,7 @@ #define OpGS 25ull /* GS */ #define OpMem8 26ull /* 8-bit zero extended memory operand */ #define OpImm64 27ull /* Sign extended 16/32/64-bit immediate */ +#define OpXLat 28ull /* memory at BX/EBX/RBX + zero-extended AL */ #define OpBits 5 /* Width of operand field */ #define OpMask ((1ull << OpBits) - 1) @@ -99,6 +100,7 @@ #define SrcImmUByte (OpImmUByte << SrcShift) #define SrcImmU (OpImmU << SrcShift) #define SrcSI (OpSI << SrcShift) +#define SrcXLat (OpXLat << SrcShift) #define SrcImmFAddr (OpImmFAddr << SrcShift) #define SrcMemFAddr (OpMemFAddr << SrcShift) #define SrcAcc (OpAcc << SrcShift) @@ -533,6 +535,9 @@ FOP_SETCC(setle) FOP_SETCC(setnle) FOP_END; +FOP_START(salc) "pushf; sbb %al, %al; popf \n\t" FOP_RET +FOP_END; + #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \ do { \ unsigned long _tmp; \ @@ -2996,6 +3001,28 @@ static int em_das(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } +static int em_aam(struct x86_emulate_ctxt *ctxt) +{ + u8 al, ah; + + if (ctxt->src.val == 0) + return emulate_de(ctxt); + + al = ctxt->dst.val & 0xff; + ah = al / ctxt->src.val; + al %= ctxt->src.val; + + ctxt->dst.val = (ctxt->dst.val & 0xffff0000) | al | (ah << 8); + + /* Set PF, ZF, SF */ + ctxt->src.type = OP_IMM; + ctxt->src.val = 0; + ctxt->src.bytes = 1; + fastop(ctxt, em_or); + + return X86EMUL_CONTINUE; +} + static int em_aad(struct x86_emulate_ctxt *ctxt) { u8 al = ctxt->dst.val & 0xff; @@ -3936,7 +3963,10 @@ static const struct opcode opcode_table[256] = { /* 0xD0 - 0xD7 */ G(Src2One | ByteOp, group2), G(Src2One, group2), G(Src2CL | ByteOp, group2), G(Src2CL, group2), - N, I(DstAcc | SrcImmByte | No64, em_aad), N, N, + I(DstAcc | SrcImmUByte | No64, em_aam), + I(DstAcc | SrcImmUByte | No64, em_aad), + F(DstAcc | ByteOp | No64, em_salc), + I(DstAcc | SrcXLat | ByteOp, em_mov), /* 0xD8 - 0xDF */ N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N, /* 0xE0 - 0xE7 */ @@ -4198,6 +4228,16 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, op->val = 0; op->count = 1; break; + case OpXLat: + op->type = OP_MEM; + op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes; + op->addr.mem.ea = + register_address(ctxt, + reg_read(ctxt, VCPU_REGS_RBX) + + (reg_read(ctxt, VCPU_REGS_RAX) & 0xff)); + op->addr.mem.seg = seg_override(ctxt); + op->val = 0; + break; case OpImmFAddr: op->type = OP_IMM; op->addr.mem.ea = ctxt->_eip; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 25a791ed21c8..260a91939555 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5434,6 +5434,12 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) return 0; } + if (vcpu->arch.halt_request) { + vcpu->arch.halt_request = 0; + ret = kvm_emulate_halt(vcpu); + goto out; + } + if (signal_pending(current)) goto out; if (need_resched()) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 05a8b1a2300d..094b5d96ab14 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -555,6 +555,25 @@ void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw) } EXPORT_SYMBOL_GPL(kvm_lmsw); +static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu) +{ + if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) && + !vcpu->guest_xcr0_loaded) { + /* kvm_set_xcr() also depends on this */ + xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0); + vcpu->guest_xcr0_loaded = 1; + } +} + +static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu) +{ + if (vcpu->guest_xcr0_loaded) { + if (vcpu->arch.xcr0 != host_xcr0) + xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0); + vcpu->guest_xcr0_loaded = 0; + } +} + int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) { u64 xcr0; @@ -571,8 +590,8 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) return 1; if (xcr0 & ~host_xcr0) return 1; + kvm_put_guest_xcr0(vcpu); vcpu->arch.xcr0 = xcr0; - vcpu->guest_xcr0_loaded = 0; return 0; } @@ -5614,25 +5633,6 @@ static void inject_pending_event(struct kvm_vcpu *vcpu) } } -static void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu) -{ - if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) && - !vcpu->guest_xcr0_loaded) { - /* kvm_set_xcr() also depends on this */ - xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0); - vcpu->guest_xcr0_loaded = 1; - } -} - -static void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu) -{ - if (vcpu->guest_xcr0_loaded) { - if (vcpu->arch.xcr0 != host_xcr0) - xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0); - vcpu->guest_xcr0_loaded = 0; - } -} - static void process_nmi(struct kvm_vcpu *vcpu) { unsigned limit = 2; diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index fdc5dca14fb3..eaac1743def7 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -359,7 +359,17 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, } /* - * would have hole in the middle or ends, and only ram parts will be mapped. + * We need to iterate through the E820 memory map and create direct mappings + * for only E820_RAM and E820_KERN_RESERVED regions. We cannot simply + * create direct mappings for all pfns from [0 to max_low_pfn) and + * [4GB to max_pfn) because of possible memory holes in high addresses + * that cannot be marked as UC by fixed/variable range MTRRs. + * Depending on the alignment of E820 ranges, this may possibly result + * in using smaller size (i.e. 4K instead of 2M or 1G) page tables. + * + * init_mem_mapping() calls init_range_memory_mapping() with big range. + * That range would have hole in the middle or ends, and only ram parts + * will be mapped in init_range_memory_mapping(). */ static unsigned long __init init_range_memory_mapping( unsigned long r_start, @@ -419,6 +429,13 @@ void __init init_mem_mapping(void) max_pfn_mapped = 0; /* will get exact value next */ min_pfn_mapped = real_end >> PAGE_SHIFT; last_start = start = real_end; + + /* + * We start from the top (end of memory) and go to the bottom. + * The memblock_find_in_range() gets us a block of RAM from the + * end of RAM in [min_pfn_mapped, max_pfn_mapped) used as new pages + * for page table. + */ while (last_start > ISA_END_ADDRESS) { if (last_start > step_size) { start = round_down(last_start - 1, step_size); diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 6eb18c42a28a..0e0fabf17342 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -141,6 +141,11 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn, */ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) { + if (bus == 0 && (devfn == PCI_DEVFN(2, 0) + || devfn == PCI_DEVFN(0, 0) + || devfn == PCI_DEVFN(3, 0))) + return 1; + /* This is a workaround for A0 LNC bug where PCI status register does * not have new CAP bit set. can not be written by SW either. * @@ -150,10 +155,7 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) */ if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE) return 0; - if (bus == 0 && (devfn == PCI_DEVFN(2, 0) - || devfn == PCI_DEVFN(0, 0) - || devfn == PCI_DEVFN(3, 0))) - return 1; + return 0; /* langwell on others */ } diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 4a9be6ddf054..48e8461057ba 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -295,11 +295,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) int pos; u32 table_offset, bir; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - + pos = dev->msix_cap; pci_read_config_dword(dev, pos + PCI_MSIX_TABLE, &table_offset); - bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); + bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); map_irq.table_base = pci_resource_start(dev, bir); map_irq.entry_nr = msidesc->msi_attrib.entry_nr; diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index d0d59bfbccce..aabfb8380a1c 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl @@ -345,7 +345,7 @@ 336 i386 perf_event_open sys_perf_event_open 337 i386 recvmmsg sys_recvmmsg compat_sys_recvmmsg 338 i386 fanotify_init sys_fanotify_init -339 i386 fanotify_mark sys_fanotify_mark sys32_fanotify_mark +339 i386 fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark 340 i386 prlimit64 sys_prlimit64 341 i386 name_to_handle_at sys_name_to_handle_at 342 i386 open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 53d4f680c9b5..a492be2635ac 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -85,7 +85,29 @@ EXPORT_SYMBOL_GPL(hypercall_page); +/* + * Pointer to the xen_vcpu_info structure or + * &HYPERVISOR_shared_info->vcpu_info[cpu]. See xen_hvm_init_shared_info + * and xen_vcpu_setup for details. By default it points to share_info->vcpu_info + * but if the hypervisor supports VCPUOP_register_vcpu_info then it can point + * to xen_vcpu_info. The pointer is used in __xen_evtchn_do_upcall to + * acknowledge pending events. + * Also more subtly it is used by the patched version of irq enable/disable + * e.g. xen_irq_enable_direct and xen_iret in PV mode. + * + * The desire to be able to do those mask/unmask operations as a single + * instruction by using the per-cpu offset held in %gs is the real reason + * vcpu info is in a per-cpu pointer and the original reason for this + * hypercall. + * + */ DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); + +/* + * Per CPU pages used if hypervisor supports VCPUOP_register_vcpu_info + * hypercall. This can be used both in PV and PVHVM mode. The structure + * overrides the default per_cpu(xen_vcpu, cpu) value. + */ DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); enum xen_domain_type xen_domain_type = XEN_NATIVE; @@ -157,6 +179,21 @@ static void xen_vcpu_setup(int cpu) BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); + /* + * This path is called twice on PVHVM - first during bootup via + * smp_init -> xen_hvm_cpu_notify, and then if the VCPU is being + * hotplugged: cpu_up -> xen_hvm_cpu_notify. + * As we can only do the VCPUOP_register_vcpu_info once lets + * not over-write its result. + * + * For PV it is called during restore (xen_vcpu_restore) and bootup + * (xen_setup_vcpu_info_placement). The hotplug mechanism does not + * use this function. + */ + if (xen_hvm_domain()) { + if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu)) + return; + } if (cpu < MAX_VIRT_CPUS) per_cpu(xen_vcpu,cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; @@ -172,7 +209,12 @@ static void xen_vcpu_setup(int cpu) /* Check to see if the hypervisor will put the vcpu_info structure where we want it, which allows direct access via - a percpu-variable. */ + a percpu-variable. + N.B. This hypercall can _only_ be called once per CPU. Subsequent + calls will error out with -EINVAL. This is due to the fact that + hypervisor has no unregister variant and this hypercall does not + allow to over-write info.mfn and info.offset. + */ err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); if (err) { @@ -387,6 +429,9 @@ static void __init xen_init_cpuid_mask(void) cpuid_leaf1_edx_mask &= ~((1 << X86_FEATURE_APIC) | /* disable local APIC */ (1 << X86_FEATURE_ACPI)); /* disable ACPI */ + + cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_X2APIC % 32)); + ax = 1; cx = 0; xen_cpuid(&ax, &bx, &cx, &dx); @@ -1603,6 +1648,9 @@ void __ref xen_hvm_init_shared_info(void) * online but xen_hvm_init_shared_info is run at resume time too and * in that case multiple vcpus might be online. */ for_each_online_cpu(cpu) { + /* Leave it to be NULL. */ + if (cpu >= MAX_VIRT_CPUS) + continue; per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; } } diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 8b54603ce816..3002ec1bb71a 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -364,7 +364,7 @@ void __cpuinit xen_init_lock_cpu(int cpu) int irq; const char *name; - WARN(per_cpu(lock_kicker_irq, cpu) > 0, "spinlock on CPU%d exists on IRQ%d!\n", + WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n", cpu, per_cpu(lock_kicker_irq, cpu)); /* diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index b09de49dbec5..0a1b95f81a32 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -1,11 +1,9 @@ -config FRAME_POINTER - def_bool n - config ZONE_DMA def_bool y config XTENSA def_bool y + select ARCH_WANT_FRAME_POINTERS select HAVE_IDE select GENERIC_ATOMIC64 select HAVE_GENERIC_HARDIRQS @@ -33,9 +31,6 @@ config RWSEM_XCHGADD_ALGORITHM config GENERIC_HWEIGHT def_bool y -config GENERIC_GPIO - bool - config ARCH_HAS_ILOG2_U32 def_bool n @@ -52,6 +47,15 @@ config HZ source "init/Kconfig" source "kernel/Kconfig.freezer" +config LOCKDEP_SUPPORT + def_bool y + +config STACKTRACE_SUPPORT + def_bool y + +config TRACE_IRQFLAGS_SUPPORT + def_bool y + config MMU def_bool n @@ -103,6 +107,35 @@ config MATH_EMULATION help Can we use information of configuration file? +config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX + bool "Initialize Xtensa MMU inside the Linux kernel code" + default y + help + Earlier version initialized the MMU in the exception vector + before jumping to _startup in head.S and had an advantage that + it was possible to place a software breakpoint at 'reset' and + then enter your normal kernel breakpoints once the MMU was mapped + to the kernel mappings (0XC0000000). + + This unfortunately doesn't work for U-Boot and likley also wont + work for using KEXEC to have a hot kernel ready for doing a + KDUMP. + + So now the MMU is initialized in head.S but it's necessary to + use hardware breakpoints (gdb 'hbreak' cmd) to break at _startup. + xt-gdb can't place a Software Breakpoint in the 0XD region prior + to mapping the MMU and after mapping even if the area of low memory + was mapped gdb wouldn't remove the breakpoint on hitting it as the + PC wouldn't match. Since Hardware Breakpoints are recommended for + Linux configurations it seems reasonable to just assume they exist + and leave this older mechanism for unfortunate souls that choose + not to follow Tensilica's recommendation. + + Selecting this will cause U-Boot to set the KERNEL Load and Entry + address at 0x00003000 instead of the mapped std of 0xD0003000. + + If in doubt, say Y. + endmenu config XTENSA_CALIBRATE_CCOUNT @@ -252,21 +285,6 @@ endmenu menu "Executable file formats" -# only elf supported -config KCORE_ELF - def_bool y - depends on PROC_FS - help - If you enabled support for /proc file system then the file - /proc/kcore will contain the kernel core image in ELF format. This - can be used in gdb: - - $ cd /usr/src/linux ; gdb vmlinux /proc/kcore - - This is especially useful if you have compiled the kernel with the - "-g" option to preserve debugging information. It is mainly used - for examining kernel data structures on the live kernel. - source "fs/Kconfig.binfmt" endmenu diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile index 1fe01b78c124..89db089f5a12 100644 --- a/arch/xtensa/boot/boot-elf/Makefile +++ b/arch/xtensa/boot/boot-elf/Makefile @@ -12,6 +12,7 @@ endif export OBJCOPY_ARGS export CPPFLAGS_boot.lds += -P -C +export KBUILD_AFLAGS += -mtext-section-literals boot-y := bootstrap.o diff --git a/arch/xtensa/boot/boot-elf/boot.lds.S b/arch/xtensa/boot/boot-elf/boot.lds.S index 7b646e0a6486..932b58ef33d4 100644 --- a/arch/xtensa/boot/boot-elf/boot.lds.S +++ b/arch/xtensa/boot/boot-elf/boot.lds.S @@ -1,41 +1,29 @@ -#include <variant/core.h> +/* + * linux/arch/xtensa/boot/boot-elf/boot.lds.S + * + * Copyright (C) 2008 - 2013 by Tensilica Inc. + * + * Chris Zankel <chris@zankel.net> + * Marc Gauthier <marc@tensilica.com + * Pete Delaney <piet@tensilica.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <asm/vectors.h> OUTPUT_ARCH(xtensa) ENTRY(_ResetVector) SECTIONS { - .start 0xD0000000 : { *(.start) } - - .text 0xD0000000: - { - __reloc_start = . ; - _text_start = . ; - *(.literal .text.literal .text) - _text_end = . ; - } - - .rodata ALIGN(0x04): - { - *(.rodata) - *(.rodata1) - } - - .data ALIGN(0x04): + .ResetVector.text XCHAL_RESET_VECTOR_VADDR : { - *(.data) - *(.data1) - *(.sdata) - *(.sdata2) - *(.got.plt) - *(.got) - *(.dynamic) + *(.ResetVector.text) } - __reloc_end = . ; - - . = ALIGN(0x10); - __image_load = . ; - .image 0xd0001000: + .image KERNELOFFSET: AT (LOAD_MEMORY_ADDRESS) { _image_start = .; *(image) @@ -43,7 +31,6 @@ SECTIONS _image_end = . ; } - .bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3): { __bss_start = .; @@ -53,14 +40,15 @@ SECTIONS *(.bss) __bss_end = .; } - _end = .; - _param_start = .; - .ResetVector.text XCHAL_RESET_VECTOR_VADDR : + /* + * This is a remapped copy of the Reset Vector Code. + * It keeps gdb in sync with the PC after switching + * to the temporary mapping used while setting up + * the V2 MMU mappings for Linux. + */ + .ResetVector.remapped_text 0x46000000 (INFO): { - *(.ResetVector.text) + *(.ResetVector.remapped_text) } - - - PROVIDE (end = .); } diff --git a/arch/xtensa/boot/boot-elf/bootstrap.S b/arch/xtensa/boot/boot-elf/bootstrap.S index 464298bc348b..1388a499753b 100644 --- a/arch/xtensa/boot/boot-elf/bootstrap.S +++ b/arch/xtensa/boot/boot-elf/bootstrap.S @@ -1,18 +1,77 @@ +/* + * arch/xtensa/boot/boot-elf/bootstrap.S + * + * Low-level exception handling + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004 - 2013 by Tensilica Inc. + * + * Chris Zankel <chris@zankel.net> + * Marc Gauthier <marc@tensilica.com> + * Piet Delaney <piet@tensilica.com> + */ #include <asm/bootparam.h> +#include <asm/processor.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/cacheasm.h> +#include <asm/initialize_mmu.h> +#include <linux/linkage.h> - -/* ResetVector - */ - .section .ResetVector.text, "ax" + .section .ResetVector.text, "ax" .global _ResetVector + .global reset + _ResetVector: - _j reset + _j _SetupMMU + + .begin no-absolute-literals + .literal_position + .align 4 RomInitAddr: - .word 0xd0001000 +#if defined(CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX) && \ + XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY + .word 0x00003000 +#else + .word 0xd0003000 +#endif RomBootParam: .word _bootparam +_bootparam: + .short BP_TAG_FIRST + .short 4 + .long BP_VERSION + .short BP_TAG_LAST + .short 0 + .long 0 + + .align 4 +_SetupMMU: + movi a0, 0 + wsr a0, windowbase + rsync + movi a0, 1 + wsr a0, windowstart + rsync + movi a0, 0x1F + wsr a0, ps + rsync + + Offset = _SetupMMU - _ResetVector + +#ifndef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX + initialize_mmu +#endif + + .end no-absolute-literals + + rsil a0, XCHAL_DEBUGLEVEL-1 + rsync reset: l32r a0, RomInitAddr l32r a2, RomBootParam @@ -21,13 +80,25 @@ reset: jx a0 .align 4 - .section .bootstrap.data, "aw" - .globl _bootparam -_bootparam: - .short BP_TAG_FIRST - .short 4 - .long BP_VERSION - .short BP_TAG_LAST - .short 0 - .long 0 + .section .ResetVector.remapped_text, "x" + .global _RemappedResetVector + + /* Do org before literals */ + .org 0 + +_RemappedResetVector: + .begin no-absolute-literals + .literal_position + + _j _RemappedSetupMMU + + /* Position Remapped code at the same location as the original code */ + . = _RemappedResetVector + Offset + +_RemappedSetupMMU: +#ifndef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX + initialize_mmu +#endif + + .end no-absolute-literals diff --git a/arch/xtensa/boot/boot-redboot/boot.ld b/arch/xtensa/boot/boot-redboot/boot.ld index 5bbcaf9e830d..b0b9e95b58bd 100644 --- a/arch/xtensa/boot/boot-redboot/boot.ld +++ b/arch/xtensa/boot/boot-redboot/boot.ld @@ -33,7 +33,7 @@ SECTIONS . = ALIGN(0x10); __image_load = . ; - .image 0xd0001000: AT(__image_load) + .image 0xd0003000: AT(__image_load) { _image_start = .; *(image) diff --git a/arch/xtensa/boot/boot-uboot/Makefile b/arch/xtensa/boot/boot-uboot/Makefile index bfbf8af582f1..545759819ef9 100644 --- a/arch/xtensa/boot/boot-uboot/Makefile +++ b/arch/xtensa/boot/boot-uboot/Makefile @@ -4,7 +4,11 @@ # for more details. # -UIMAGE_LOADADDR = 0xd0001000 +ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX +UIMAGE_LOADADDR = 0x00003000 +else +UIMAGE_LOADADDR = 0xd0003000 +endif UIMAGE_COMPRESSION = gzip $(obj)/../uImage: vmlinux.bin.gz FORCE diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig index ddab37b24741..77c52f80187a 100644 --- a/arch/xtensa/configs/iss_defconfig +++ b/arch/xtensa/configs/iss_defconfig @@ -10,7 +10,6 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_NO_IOPORT=y diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig index eaf1b8fc6556..4799c6a526b5 100644 --- a/arch/xtensa/configs/s6105_defconfig +++ b/arch/xtensa/configs/s6105_defconfig @@ -10,7 +10,6 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_NO_IOPORT=y diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 095f0a2244f7..1b982641ec35 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -15,6 +15,7 @@ generic-y += irq_regs.h generic-y += kdebug.h generic-y += kmap_types.h generic-y += kvm_para.h +generic-y += linkage.h generic-y += local.h generic-y += local64.h generic-y += percpu.h diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h index 40a8c178f10d..36dc7a684397 100644 --- a/arch/xtensa/include/asm/ftrace.h +++ b/arch/xtensa/include/asm/ftrace.h @@ -1 +1,33 @@ -/* empty */ +/* + * arch/xtensa/include/asm/ftrace.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Tensilica Inc. + */ +#ifndef _XTENSA_FTRACE_H +#define _XTENSA_FTRACE_H + +#include <asm/processor.h> + +#define HAVE_ARCH_CALLER_ADDR +#define CALLER_ADDR0 ({ unsigned long a0, a1; \ + __asm__ __volatile__ ( \ + "mov %0, a0\n" \ + "mov %1, a1\n" \ + : "=r"(a0), "=r"(a1) : : ); \ + MAKE_PC_FROM_RA(a0, a1); }) +#ifdef CONFIG_FRAME_POINTER +extern unsigned long return_address(unsigned level); +#define CALLER_ADDR1 return_address(1) +#define CALLER_ADDR2 return_address(2) +#define CALLER_ADDR3 return_address(3) +#else +#define CALLER_ADDR1 (0) +#define CALLER_ADDR2 (0) +#define CALLER_ADDR3 (0) +#endif + +#endif /* _XTENSA_FTRACE_H */ diff --git a/arch/xtensa/include/asm/initialize_mmu.h b/arch/xtensa/include/asm/initialize_mmu.h index e1f8ba4061ed..722553f17db3 100644 --- a/arch/xtensa/include/asm/initialize_mmu.h +++ b/arch/xtensa/include/asm/initialize_mmu.h @@ -23,6 +23,9 @@ #ifndef _XTENSA_INITIALIZE_MMU_H #define _XTENSA_INITIALIZE_MMU_H +#include <asm/pgtable.h> +#include <asm/vectors.h> + #ifdef __ASSEMBLY__ #define XTENSA_HWVERSION_RC_2009_0 230000 @@ -48,6 +51,110 @@ * (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) */ +#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY +/* + * Have MMU v3 + */ + +#if !XCHAL_HAVE_VECBASE +# error "MMU v3 requires reloc vectors" +#endif + + movi a1, 0 + _call0 1f + _j 2f + + .align 4 +1: movi a2, 0x10000000 + movi a3, 0x18000000 + add a2, a2, a0 +9: bgeu a2, a3, 9b /* PC is out of the expected range */ + + /* Step 1: invalidate mapping at 0x40000000..0x5FFFFFFF. */ + + movi a2, 0x40000006 + idtlb a2 + iitlb a2 + isync + + /* Step 2: map 0x40000000..0x47FFFFFF to paddr containing this code + * and jump to the new mapping. + */ +#define CA_BYPASS (_PAGE_CA_BYPASS | _PAGE_HW_WRITE | _PAGE_HW_EXEC) +#define CA_WRITEBACK (_PAGE_CA_WB | _PAGE_HW_WRITE | _PAGE_HW_EXEC) + + srli a3, a0, 27 + slli a3, a3, 27 + addi a3, a3, CA_BYPASS + addi a7, a2, -1 + wdtlb a3, a7 + witlb a3, a7 + isync + + slli a4, a0, 5 + srli a4, a4, 5 + addi a5, a2, -6 + add a4, a4, a5 + jx a4 + + /* Step 3: unmap everything other than current area. + * Start at 0x60000000, wrap around, and end with 0x20000000 + */ +2: movi a4, 0x20000000 + add a5, a2, a4 +3: idtlb a5 + iitlb a5 + add a5, a5, a4 + bne a5, a2, 3b + + /* Step 4: Setup MMU with the old V2 mappings. */ + movi a6, 0x01000000 + wsr a6, ITLBCFG + wsr a6, DTLBCFG + isync + + movi a5, 0xd0000005 + movi a4, CA_WRITEBACK + wdtlb a4, a5 + witlb a4, a5 + + movi a5, 0xd8000005 + movi a4, CA_BYPASS + wdtlb a4, a5 + witlb a4, a5 + + movi a5, 0xe0000006 + movi a4, 0xf0000000 + CA_WRITEBACK + wdtlb a4, a5 + witlb a4, a5 + + movi a5, 0xf0000006 + movi a4, 0xf0000000 + CA_BYPASS + wdtlb a4, a5 + witlb a4, a5 + + isync + + /* Jump to self, using MMU v2 mappings. */ + movi a4, 1f + jx a4 + +1: + movi a2, VECBASE_RESET_VADDR + wsr a2, vecbase + + /* Step 5: remove temporary mapping. */ + idtlb a7 + iitlb a7 + isync + + movi a0, 0 + wsr a0, ptevaddr + rsync + +#endif /* defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && + XCHAL_HAVE_SPANNING_WAY */ + .endm #endif /*__ASSEMBLY__*/ diff --git a/arch/xtensa/include/asm/irqflags.h b/arch/xtensa/include/asm/irqflags.h index f865b1c1eae4..ea36674c6ec5 100644 --- a/arch/xtensa/include/asm/irqflags.h +++ b/arch/xtensa/include/asm/irqflags.h @@ -47,7 +47,10 @@ static inline void arch_local_irq_restore(unsigned long flags) static inline bool arch_irqs_disabled_flags(unsigned long flags) { - return (flags & 0xf) != 0; +#if XCHAL_EXCM_LEVEL < LOCKLEVEL || (1 << PS_EXCM_BIT) < LOCKLEVEL +#error "XCHAL_EXCM_LEVEL and 1<<PS_EXCM_BIT must be no less than LOCKLEVEL" +#endif + return (flags & (PS_INTLEVEL_MASK | (1 << PS_EXCM_BIT))) >= LOCKLEVEL; } static inline bool arch_irqs_disabled(void) diff --git a/arch/xtensa/include/asm/linkage.h b/arch/xtensa/include/asm/linkage.h deleted file mode 100644 index bf2128a99d79..000000000000 --- a/arch/xtensa/include/asm/linkage.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/linkage.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_LINKAGE_H -#define _XTENSA_LINKAGE_H - -/* Nothing to do here ... */ - -#endif /* _XTENSA_LINKAGE_H */ diff --git a/arch/xtensa/include/asm/stacktrace.h b/arch/xtensa/include/asm/stacktrace.h new file mode 100644 index 000000000000..6a05fcb0a20d --- /dev/null +++ b/arch/xtensa/include/asm/stacktrace.h @@ -0,0 +1,36 @@ +/* + * arch/xtensa/include/asm/stacktrace.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2013 Tensilica Inc. + */ +#ifndef _XTENSA_STACKTRACE_H +#define _XTENSA_STACKTRACE_H + +#include <linux/sched.h> + +struct stackframe { + unsigned long pc; + unsigned long sp; +}; + +static __always_inline unsigned long *stack_pointer(struct task_struct *task) +{ + unsigned long *sp; + + if (!task || task == current) + __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp)); + else + sp = (unsigned long *)task->thread.sp; + + return sp; +} + +void walk_stackframe(unsigned long *sp, + int (*fn)(struct stackframe *frame, void *data), + void *data); + +#endif /* _XTENSA_STACKTRACE_H */ diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h index 9e85ce8bd8dd..3d35e5d0367e 100644 --- a/arch/xtensa/include/asm/timex.h +++ b/arch/xtensa/include/asm/timex.h @@ -19,13 +19,16 @@ #define _INTLEVEL(x) XCHAL_INT ## x ## _LEVEL #define INTLEVEL(x) _INTLEVEL(x) -#if INTLEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL +#if XCHAL_NUM_TIMERS > 0 && \ + INTLEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL # define LINUX_TIMER 0 # define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT -#elif INTLEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL +#elif XCHAL_NUM_TIMERS > 1 && \ + INTLEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL # define LINUX_TIMER 1 # define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT -#elif INTLEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL +#elif XCHAL_NUM_TIMERS > 2 && \ + INTLEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL # define LINUX_TIMER 2 # define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT #else diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h index b5464ef3cf66..917488a0ab00 100644 --- a/arch/xtensa/include/asm/traps.h +++ b/arch/xtensa/include/asm/traps.h @@ -22,10 +22,9 @@ extern void do_unhandled(struct pt_regs *regs, unsigned long exccause); static inline void spill_registers(void) { - unsigned int a0, ps; __asm__ __volatile__ ( - "movi a14, " __stringify(PS_EXCM_BIT | LOCKLEVEL) "\n\t" + "movi a14, "__stringify((1 << PS_EXCM_BIT) | LOCKLEVEL)"\n\t" "mov a12, a0\n\t" "rsr a13, sar\n\t" "xsr a14, ps\n\t" @@ -35,7 +34,7 @@ static inline void spill_registers(void) "mov a0, a12\n\t" "wsr a13, sar\n\t" "wsr a14, ps\n\t" - : : "a" (&a0), "a" (&ps) + : : #if defined(CONFIG_FRAME_POINTER) : "a2", "a3", "a4", "a11", "a12", "a13", "a14", "a15", #else diff --git a/arch/xtensa/include/asm/vectors.h b/arch/xtensa/include/asm/vectors.h new file mode 100644 index 000000000000..c52b656d0310 --- /dev/null +++ b/arch/xtensa/include/asm/vectors.h @@ -0,0 +1,125 @@ +/* + * arch/xtensa/include/asm/xchal_vaddr_remap.h + * + * Xtensa macros for MMU V3 Support. Deals with re-mapping the Virtual + * Memory Addresses from "Virtual == Physical" to their prevvious V2 MMU + * mappings (KSEG at 0xD0000000 and KIO at 0XF0000000). + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2008 - 2012 Tensilica Inc. + * + * Pete Delaney <piet@tensilica.com> + * Marc Gauthier <marc@tensilica.com + */ + +#ifndef _XTENSA_VECTORS_H +#define _XTENSA_VECTORS_H + +#include <variant/core.h> + +#if defined(CONFIG_MMU) + +/* Will Become VECBASE */ +#define VIRTUAL_MEMORY_ADDRESS 0xD0000000 + +/* Image Virtual Start Address */ +#define KERNELOFFSET 0xD0003000 + +#if defined(XCHAL_HAVE_PTP_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY + /* MMU v3 - XCHAL_HAVE_PTP_MMU == 1 */ + #define PHYSICAL_MEMORY_ADDRESS 0x00000000 + #define LOAD_MEMORY_ADDRESS 0x00003000 +#else + /* MMU V2 - XCHAL_HAVE_PTP_MMU == 0 */ + #define PHYSICAL_MEMORY_ADDRESS 0xD0000000 + #define LOAD_MEMORY_ADDRESS 0xD0003000 +#endif + +#else /* !defined(CONFIG_MMU) */ + /* MMU Not being used - Virtual == Physical */ + + /* VECBASE */ + #define VIRTUAL_MEMORY_ADDRESS 0x00002000 + + /* Location of the start of the kernel text, _start */ + #define KERNELOFFSET 0x00003000 + #define PHYSICAL_MEMORY_ADDRESS 0x00000000 + + /* Loaded just above possibly live vectors */ + #define LOAD_MEMORY_ADDRESS 0x00003000 + +#endif /* CONFIG_MMU */ + +#define XC_VADDR(offset) (VIRTUAL_MEMORY_ADDRESS + offset) +#define XC_PADDR(offset) (PHYSICAL_MEMORY_ADDRESS + offset) + +/* Used to set VECBASE register */ +#define VECBASE_RESET_VADDR VIRTUAL_MEMORY_ADDRESS + +#define RESET_VECTOR_VECOFS (XCHAL_RESET_VECTOR_VADDR - \ + VECBASE_RESET_VADDR) +#define RESET_VECTOR_VADDR XC_VADDR(RESET_VECTOR_VECOFS) + +#define RESET_VECTOR1_VECOFS (XCHAL_RESET_VECTOR1_VADDR - \ + VECBASE_RESET_VADDR) +#define RESET_VECTOR1_VADDR XC_VADDR(RESET_VECTOR1_VECOFS) + +#if XCHAL_HAVE_VECBASE + +#define USER_VECTOR_VADDR XC_VADDR(XCHAL_USER_VECOFS) +#define KERNEL_VECTOR_VADDR XC_VADDR(XCHAL_KERNEL_VECOFS) +#define DOUBLEEXC_VECTOR_VADDR XC_VADDR(XCHAL_DOUBLEEXC_VECOFS) +#define WINDOW_VECTORS_VADDR XC_VADDR(XCHAL_WINDOW_OF4_VECOFS) +#define INTLEVEL2_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL2_VECOFS) +#define INTLEVEL3_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL3_VECOFS) +#define INTLEVEL4_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL4_VECOFS) +#define INTLEVEL5_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL5_VECOFS) +#define INTLEVEL6_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL6_VECOFS) + +#define DEBUG_VECTOR_VADDR XC_VADDR(XCHAL_DEBUG_VECOFS) + +#undef XCHAL_NMI_VECTOR_VADDR +#define XCHAL_NMI_VECTOR_VADDR XC_VADDR(XCHAL_NMI_VECOFS) + +#undef XCHAL_INTLEVEL7_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_VADDR XC_VADDR(XCHAL_INTLEVEL7_VECOFS) + +/* + * These XCHAL_* #defines from varian/core.h + * are not valid to use with V3 MMU. Non-XCHAL + * constants are defined above and should be used. + */ +#undef XCHAL_VECBASE_RESET_VADDR +#undef XCHAL_RESET_VECTOR0_VADDR +#undef XCHAL_USER_VECTOR_VADDR +#undef XCHAL_KERNEL_VECTOR_VADDR +#undef XCHAL_DOUBLEEXC_VECTOR_VADDR +#undef XCHAL_WINDOW_VECTORS_VADDR +#undef XCHAL_INTLEVEL2_VECTOR_VADDR +#undef XCHAL_INTLEVEL3_VECTOR_VADDR +#undef XCHAL_INTLEVEL4_VECTOR_VADDR +#undef XCHAL_INTLEVEL5_VECTOR_VADDR +#undef XCHAL_INTLEVEL6_VECTOR_VADDR +#undef XCHAL_DEBUG_VECTOR_VADDR +#undef XCHAL_NMI_VECTOR_VADDR +#undef XCHAL_INTLEVEL7_VECTOR_VADDR + +#else + +#define USER_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR +#define KERNEL_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR +#define DOUBLEEXC_VECTOR_VADDR XCHAL_DOUBLEEXC_VECTOR_VADDR +#define WINDOW_VECTORS_VADDR XCHAL_WINDOW_VECTORS_VADDR +#define INTLEVEL2_VECTOR_VADDR XCHAL_INTLEVEL2_VECTOR_VADDR +#define INTLEVEL3_VECTOR_VADDR XCHAL_INTLEVEL3_VECTOR_VADDR +#define INTLEVEL4_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR +#define INTLEVEL5_VECTOR_VADDR XCHAL_INTLEVEL5_VECTOR_VADDR +#define INTLEVEL6_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define DEBUG_VECTOR_VADDR XCHAL_DEBUG_VECTOR_VADDR + +#endif + +#endif /* _XTENSA_VECTORS_H */ diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile index c3a59d992ac0..1e7fc87a94bb 100644 --- a/arch/xtensa/kernel/Makefile +++ b/arch/xtensa/kernel/Makefile @@ -4,14 +4,16 @@ extra-y := head.o vmlinux.lds -obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o \ - setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \ - pci-dma.o +obj-y := align.o coprocessor.o entry.o irq.o pci-dma.o platform.o process.o \ + ptrace.o setup.o signal.o stacktrace.o syscall.o time.o traps.o \ + vectors.o obj-$(CONFIG_KGDB) += xtensa-stub.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o +AFLAGS_head.o += -mtext-section-literals + # In the Xtensa architecture, assembly generates literals which must always # precede the L32R instruction with a relative offset less than 256 kB. # Therefore, the .text and .literal section must be combined in parenthesis diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 63845f950792..5082507d5631 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -354,16 +354,16 @@ common_exception: * so we can allow exceptions and interrupts (*) again. * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X) * - * (*) We only allow interrupts of higher priority than current IRQ + * (*) We only allow interrupts if they were previously enabled and + * we're not handling an IRQ */ rsr a3, ps - addi a0, a0, -4 - movi a2, 1 + addi a0, a0, -EXCCAUSE_LEVEL1_INTERRUPT + movi a2, LOCKLEVEL extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH # a3 = PS.INTLEVEL - movnez a2, a3, a3 # a2 = 1: level-1, > 1: high priority - moveqz a3, a2, a0 # a3 = IRQ level iff interrupt + moveqz a3, a2, a0 # a3 = LOCKLEVEL iff interrupt movi a2, 1 << PS_WOE_BIT or a3, a3, a2 rsr a0, exccause @@ -389,6 +389,22 @@ common_exception: save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT +#ifdef CONFIG_TRACE_IRQFLAGS + l32i a4, a1, PT_DEPC + /* Double exception means we came here with an exception + * while PS.EXCM was set, i.e. interrupts disabled. + */ + bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f + l32i a4, a1, PT_EXCCAUSE + bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f + /* We came here with an interrupt means interrupts were enabled + * and we've just disabled them. + */ + movi a4, trace_hardirqs_off + callx4 a4 +1: +#endif + /* Go to second-level dispatcher. Set up parameters to pass to the * exception handler and call the exception handler. */ @@ -407,11 +423,29 @@ common_exception: .global common_exception_return common_exception_return: +#ifdef CONFIG_TRACE_IRQFLAGS + l32i a4, a1, PT_DEPC + /* Double exception means we came here with an exception + * while PS.EXCM was set, i.e. interrupts disabled. + */ + bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f + l32i a4, a1, PT_EXCCAUSE + bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f + /* We came here with an interrupt means interrupts were enabled + * and we'll reenable them on return. + */ + movi a4, trace_hardirqs_on + callx4 a4 +1: +#endif + /* Jump if we are returning from kernel exceptions. */ 1: l32i a3, a1, PT_PS _bbci.l a3, PS_UM_BIT, 4f + rsil a2, 0 + /* Specific to a user exception exit: * We need to check some flags for signal handling and rescheduling, * and have to restore WB and WS, extra states, and all registers @@ -652,51 +686,19 @@ common_exception_exit: l32i a0, a1, PT_DEPC l32i a3, a1, PT_AREG3 - _bltui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f - - wsr a0, depc l32i a2, a1, PT_AREG2 - l32i a0, a1, PT_AREG0 - l32i a1, a1, PT_AREG1 - rfde + _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f -1: /* Restore a0...a3 and return */ - rsr a0, ps - extui a2, a0, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH - movi a0, 2f - slli a2, a2, 4 - add a0, a2, a0 - l32i a2, a1, PT_AREG2 - jx a0 - - .macro irq_exit_level level - .align 16 - .if XCHAL_EXCM_LEVEL >= \level - l32i a0, a1, PT_PC - wsr a0, epc\level l32i a0, a1, PT_AREG0 l32i a1, a1, PT_AREG1 - rfi \level - .endif - .endm + rfe - .align 16 -2: +1: wsr a0, depc l32i a0, a1, PT_AREG0 l32i a1, a1, PT_AREG1 - rfe - - .align 16 - /* no rfi for level-1 irq, handled by rfe above*/ - nop - - irq_exit_level 2 - irq_exit_level 3 - irq_exit_level 4 - irq_exit_level 5 - irq_exit_level 6 + rfde ENDPROC(kernel_exception) diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index df88f98737f4..ef12c0e6fa25 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S @@ -48,17 +48,36 @@ */ __HEAD + .begin no-absolute-literals + ENTRY(_start) - _j 2f + /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ + wsr a2, excsave1 + _j _SetupMMU + + .align 4 + .literal_position +.Lstartup: + .word _startup + .align 4 -1: .word _startup -2: l32r a0, 1b + .global _SetupMMU +_SetupMMU: + Offset = _SetupMMU - _start + +#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX + initialize_mmu +#endif + .end no-absolute-literals + + l32r a0, .Lstartup jx a0 ENDPROC(_start) - .section .init.text, "ax" + __INIT + .literal_position ENTRY(_startup) @@ -67,10 +86,6 @@ ENTRY(_startup) movi a0, LOCKLEVEL wsr a0, ps - /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ - - wsr a2, excsave1 - /* Start with a fresh windowbase and windowstart. */ movi a1, 1 @@ -86,7 +101,9 @@ ENTRY(_startup) /* Clear debugging registers. */ #if XCHAL_HAVE_DEBUG +#if XCHAL_NUM_IBREAK > 0 wsr a0, ibreakenable +#endif wsr a0, icount movi a1, 15 wsr a0, icountlevel @@ -156,8 +173,6 @@ ENTRY(_startup) isync - initialize_mmu - /* Unpack data sections * * The linker script used to build the Linux kernel image @@ -205,6 +220,10 @@ ENTRY(_startup) ___flush_dcache_all a2 a3 #endif + memw + isync + ___invalidate_icache_all a2 a3 + isync /* Setup stack and enable window exceptions (keep irqs disabled) */ diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index 44bf21c3769a..2bd6c351f37c 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -36,6 +36,7 @@ _F(void, power_off, (void), { while(1); }); _F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); }); _F(void, heartbeat, (void), { }); _F(int, pcibios_fixup, (void), { return 0; }); +_F(void, pcibios_init, (void), { }); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT _F(void, calibrate_ccount, (void), diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c new file mode 100644 index 000000000000..7d2c317bd98b --- /dev/null +++ b/arch/xtensa/kernel/stacktrace.c @@ -0,0 +1,120 @@ +/* + * arch/xtensa/kernel/stacktrace.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2013 Tensilica Inc. + */ +#include <linux/export.h> +#include <linux/sched.h> +#include <linux/stacktrace.h> + +#include <asm/stacktrace.h> +#include <asm/traps.h> + +void walk_stackframe(unsigned long *sp, + int (*fn)(struct stackframe *frame, void *data), + void *data) +{ + unsigned long a0, a1; + unsigned long sp_end; + + a1 = (unsigned long)sp; + sp_end = ALIGN(a1, THREAD_SIZE); + + spill_registers(); + + while (a1 < sp_end) { + struct stackframe frame; + + sp = (unsigned long *)a1; + + a0 = *(sp - 4); + a1 = *(sp - 3); + + if (a1 <= (unsigned long)sp) + break; + + frame.pc = MAKE_PC_FROM_RA(a0, a1); + frame.sp = a1; + + if (fn(&frame, data)) + return; + } +} + +#ifdef CONFIG_STACKTRACE + +struct stack_trace_data { + struct stack_trace *trace; + unsigned skip; +}; + +static int stack_trace_cb(struct stackframe *frame, void *data) +{ + struct stack_trace_data *trace_data = data; + struct stack_trace *trace = trace_data->trace; + + if (trace_data->skip) { + --trace_data->skip; + return 0; + } + if (!kernel_text_address(frame->pc)) + return 0; + + trace->entries[trace->nr_entries++] = frame->pc; + return trace->nr_entries >= trace->max_entries; +} + +void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace) +{ + struct stack_trace_data trace_data = { + .trace = trace, + .skip = trace->skip, + }; + walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data); +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); + +void save_stack_trace(struct stack_trace *trace) +{ + save_stack_trace_tsk(current, trace); +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +#endif + +#ifdef CONFIG_FRAME_POINTER + +struct return_addr_data { + unsigned long addr; + unsigned skip; +}; + +static int return_address_cb(struct stackframe *frame, void *data) +{ + struct return_addr_data *r = data; + + if (r->skip) { + --r->skip; + return 0; + } + if (!kernel_text_address(frame->pc)) + return 0; + r->addr = frame->pc; + return 1; +} + +unsigned long return_address(unsigned level) +{ + struct return_addr_data r = { + .skip = level + 1, + }; + walk_stackframe(stack_pointer(NULL), return_address_cb, &r); + return r.addr; +} +EXPORT_SYMBOL(return_address); + +#endif diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 458186dab5dc..3e8a05c874cd 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -11,7 +11,7 @@ * * Essentially rewritten for the Xtensa architecture port. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2013 Tensilica Inc. * * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> * Chris Zankel <chris@zankel.net> @@ -32,6 +32,7 @@ #include <linux/delay.h> #include <linux/hardirq.h> +#include <asm/stacktrace.h> #include <asm/ptrace.h> #include <asm/timex.h> #include <asm/uaccess.h> @@ -195,7 +196,6 @@ void do_multihit(struct pt_regs *regs, unsigned long exccause) /* * IRQ handler. - * PS.INTLEVEL is the current IRQ priority level. */ extern void do_IRQ(int, struct pt_regs *); @@ -212,18 +212,21 @@ void do_interrupt(struct pt_regs *regs) XCHAL_INTLEVEL6_MASK, XCHAL_INTLEVEL7_MASK, }; - unsigned level = get_sr(ps) & PS_INTLEVEL_MASK; - - if (WARN_ON_ONCE(level >= ARRAY_SIZE(int_level_mask))) - return; for (;;) { unsigned intread = get_sr(interrupt); unsigned intenable = get_sr(intenable); - unsigned int_at_level = intread & intenable & - int_level_mask[level]; + unsigned int_at_level = intread & intenable; + unsigned level; + + for (level = LOCKLEVEL; level > 0; --level) { + if (int_at_level & int_level_mask[level]) { + int_at_level &= int_level_mask[level]; + break; + } + } - if (!int_at_level) + if (level == 0) return; /* @@ -404,53 +407,25 @@ void show_regs(struct pt_regs * regs) regs->syscall); } -static __always_inline unsigned long *stack_pointer(struct task_struct *task) +static int show_trace_cb(struct stackframe *frame, void *data) { - unsigned long *sp; - - if (!task || task == current) - __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp)); - else - sp = (unsigned long *)task->thread.sp; - - return sp; + if (kernel_text_address(frame->pc)) { + printk(" [<%08lx>] ", frame->pc); + print_symbol("%s\n", frame->pc); + } + return 0; } void show_trace(struct task_struct *task, unsigned long *sp) { - unsigned long a0, a1, pc; - unsigned long sp_start, sp_end; - - if (sp) - a1 = (unsigned long)sp; - else - a1 = (unsigned long)stack_pointer(task); - - sp_start = a1 & ~(THREAD_SIZE-1); - sp_end = sp_start + THREAD_SIZE; + if (!sp) + sp = stack_pointer(task); printk("Call Trace:"); #ifdef CONFIG_KALLSYMS printk("\n"); #endif - spill_registers(); - - while (a1 > sp_start && a1 < sp_end) { - sp = (unsigned long*)a1; - - a0 = *(sp - 4); - a1 = *(sp - 3); - - if (a1 <= (unsigned long) sp) - break; - - pc = MAKE_PC_FROM_RA(a0, a1); - - if (kernel_text_address(pc)) { - printk(" [<%08lx>] ", pc); - print_symbol("%s\n", pc); - } - } + walk_stackframe(sp, show_trace_cb, NULL); printk("\n"); } diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index 82109b42e240..f9e175382aa9 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S @@ -50,6 +50,7 @@ #include <asm/processor.h> #include <asm/page.h> #include <asm/thread_info.h> +#include <asm/vectors.h> #define WINDOW_VECTORS_SIZE 0x180 @@ -220,7 +221,7 @@ ENTRY(_DoubleExceptionVector) xsr a0, depc # get DEPC, save a0 - movi a3, XCHAL_WINDOW_VECTORS_VADDR + movi a3, WINDOW_VECTORS_VADDR _bltu a0, a3, .Lfixup addi a3, a3, WINDOW_VECTORS_SIZE _bgeu a0, a3, .Lfixup @@ -385,9 +386,12 @@ ENDPROC(_DebugInterruptVector) .if XCHAL_EXCM_LEVEL >= \level .section .Level\level\()InterruptVector.text, "ax" ENTRY(_Level\level\()InterruptVector) - wsr a0, epc1 + wsr a0, excsave2 rsr a0, epc\level - xsr a0, epc1 + wsr a0, epc1 + movi a0, EXCCAUSE_LEVEL1_INTERRUPT + wsr a0, exccause + rsr a0, eps\level # branch to user or kernel vector j _SimulateUserKernelVectorException .endif @@ -439,10 +443,8 @@ ENDPROC(_WindowOverflow4) */ .align 4 _SimulateUserKernelVectorException: - wsr a0, excsave2 - movi a0, 4 # LEVEL1_INTERRUPT cause - wsr a0, exccause - rsr a0, ps + addi a0, a0, (1 << PS_EXCM_BIT) + wsr a0, ps bbsi.l a0, PS_UM_BIT, 1f # branch if user mode rsr a0, excsave2 # restore a0 j _KernelExceptionVector # simulate kernel vector exception diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index 14695240536d..21acd11b5df2 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -18,6 +18,7 @@ #include <asm/page.h> #include <asm/thread_info.h> +#include <asm/vectors.h> #include <variant/core.h> #include <platform/hardware.h> OUTPUT_ARCH(xtensa) @@ -30,7 +31,7 @@ jiffies = jiffies_64; #endif #ifndef KERNELOFFSET -#define KERNELOFFSET 0xd0001000 +#define KERNELOFFSET 0xd0003000 #endif /* Note: In the following macros, it would be nice to specify only the @@ -185,16 +186,16 @@ SECTIONS SECTION_VECTOR (_WindowVectors_text, .WindowVectors.text, - XCHAL_WINDOW_VECTORS_VADDR, 4, + WINDOW_VECTORS_VADDR, 4, .dummy) SECTION_VECTOR (_DebugInterruptVector_literal, .DebugInterruptVector.literal, - XCHAL_DEBUG_VECTOR_VADDR - 4, + DEBUG_VECTOR_VADDR - 4, SIZEOF(.WindowVectors.text), .WindowVectors.text) SECTION_VECTOR (_DebugInterruptVector_text, .DebugInterruptVector.text, - XCHAL_DEBUG_VECTOR_VADDR, + DEBUG_VECTOR_VADDR, 4, .DebugInterruptVector.literal) #undef LAST @@ -202,7 +203,7 @@ SECTIONS #if XCHAL_EXCM_LEVEL >= 2 SECTION_VECTOR (_Level2InterruptVector_text, .Level2InterruptVector.text, - XCHAL_INTLEVEL2_VECTOR_VADDR, + INTLEVEL2_VECTOR_VADDR, SIZEOF(LAST), LAST) # undef LAST # define LAST .Level2InterruptVector.text @@ -210,7 +211,7 @@ SECTIONS #if XCHAL_EXCM_LEVEL >= 3 SECTION_VECTOR (_Level3InterruptVector_text, .Level3InterruptVector.text, - XCHAL_INTLEVEL3_VECTOR_VADDR, + INTLEVEL3_VECTOR_VADDR, SIZEOF(LAST), LAST) # undef LAST # define LAST .Level3InterruptVector.text @@ -218,7 +219,7 @@ SECTIONS #if XCHAL_EXCM_LEVEL >= 4 SECTION_VECTOR (_Level4InterruptVector_text, .Level4InterruptVector.text, - XCHAL_INTLEVEL4_VECTOR_VADDR, + INTLEVEL4_VECTOR_VADDR, SIZEOF(LAST), LAST) # undef LAST # define LAST .Level4InterruptVector.text @@ -226,7 +227,7 @@ SECTIONS #if XCHAL_EXCM_LEVEL >= 5 SECTION_VECTOR (_Level5InterruptVector_text, .Level5InterruptVector.text, - XCHAL_INTLEVEL5_VECTOR_VADDR, + INTLEVEL5_VECTOR_VADDR, SIZEOF(LAST), LAST) # undef LAST # define LAST .Level5InterruptVector.text @@ -234,39 +235,39 @@ SECTIONS #if XCHAL_EXCM_LEVEL >= 6 SECTION_VECTOR (_Level6InterruptVector_text, .Level6InterruptVector.text, - XCHAL_INTLEVEL6_VECTOR_VADDR, + INTLEVEL6_VECTOR_VADDR, SIZEOF(LAST), LAST) # undef LAST # define LAST .Level6InterruptVector.text #endif SECTION_VECTOR (_KernelExceptionVector_literal, .KernelExceptionVector.literal, - XCHAL_KERNEL_VECTOR_VADDR - 4, + KERNEL_VECTOR_VADDR - 4, SIZEOF(LAST), LAST) #undef LAST SECTION_VECTOR (_KernelExceptionVector_text, .KernelExceptionVector.text, - XCHAL_KERNEL_VECTOR_VADDR, + KERNEL_VECTOR_VADDR, 4, .KernelExceptionVector.literal) SECTION_VECTOR (_UserExceptionVector_literal, .UserExceptionVector.literal, - XCHAL_USER_VECTOR_VADDR - 4, + USER_VECTOR_VADDR - 4, SIZEOF(.KernelExceptionVector.text), .KernelExceptionVector.text) SECTION_VECTOR (_UserExceptionVector_text, .UserExceptionVector.text, - XCHAL_USER_VECTOR_VADDR, + USER_VECTOR_VADDR, 4, .UserExceptionVector.literal) SECTION_VECTOR (_DoubleExceptionVector_literal, .DoubleExceptionVector.literal, - XCHAL_DOUBLEEXC_VECTOR_VADDR - 16, + DOUBLEEXC_VECTOR_VADDR - 16, SIZEOF(.UserExceptionVector.text), .UserExceptionVector.text) SECTION_VECTOR (_DoubleExceptionVector_text, .DoubleExceptionVector.text, - XCHAL_DOUBLEEXC_VECTOR_VADDR, + DOUBLEEXC_VECTOR_VADDR, 32, .DoubleExceptionVector.literal) @@ -284,11 +285,26 @@ SECTIONS . = ALIGN(0x10); .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) } - .ResetVector.text XCHAL_RESET_VECTOR_VADDR : + .ResetVector.text RESET_VECTOR_VADDR : { *(.ResetVector.text) } + + /* + * This is a remapped copy of the Secondary Reset Vector Code. + * It keeps gdb in sync with the PC after switching + * to the temporary mapping used while setting up + * the V2 MMU mappings for Linux. + * + * Only debug information about this section is put in the kernel image. + */ + .SecondaryResetVector.remapped_text 0x46000000 (INFO): + { + *(.SecondaryResetVector.remapped_text) + } + + .xt.lit : { *(.xt.lit) } .xt.prop : { *(.xt.prop) } diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index afe058b24e6e..42c53c87c204 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -119,3 +119,8 @@ EXPORT_SYMBOL(outsl); EXPORT_SYMBOL(insb); EXPORT_SYMBOL(insw); EXPORT_SYMBOL(insl); + +extern long common_exception_return; +extern long _spill_registers; +EXPORT_SYMBOL(common_exception_return); +EXPORT_SYMBOL(_spill_registers); diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index 0f77f9d3bb8b..a1077570e383 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c @@ -24,15 +24,19 @@ void __init paging_init(void) */ void __init init_mmu(void) { - /* Writing zeros to the <t>TLBCFG special registers ensure - * that valid values exist in the register. For existing - * PGSZID<w> fields, zero selects the first element of the - * page-size array. For nonexistent PGSZID<w> fields, zero is - * the best value to write. Also, when changing PGSZID<w> +#if !(XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) + /* + * Writing zeros to the instruction and data TLBCFG special + * registers ensure that valid values exist in the register. + * + * For existing PGSZID<w> fields, zero selects the first element + * of the page-size array. For nonexistent PGSZID<w> fields, + * zero is the best value to write. Also, when changing PGSZID<w> * fields, the corresponding TLB must be flushed. */ set_itlbcfg_register(0); set_dtlbcfg_register(0); +#endif flush_tlb_all(); /* Set rasid register to a known value. */ diff --git a/arch/xtensa/oprofile/backtrace.c b/arch/xtensa/oprofile/backtrace.c index 66f32ee2c982..5f03a593d84f 100644 --- a/arch/xtensa/oprofile/backtrace.c +++ b/arch/xtensa/oprofile/backtrace.c @@ -132,9 +132,7 @@ static void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth) pc = MAKE_PC_FROM_RA(a0, pc); /* Add the PC to the trace. */ - if (kernel_text_address(pc)) - oprofile_add_trace(pc); - + oprofile_add_trace(pc); if (pc == (unsigned long) &common_exception_return) { regs = (struct pt_regs *)a1; if (user_mode(regs)) { diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index da9866f7fecf..70cb408bc20d 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -56,13 +56,13 @@ static void rs_poll(unsigned long); static int rs_open(struct tty_struct *tty, struct file * filp) { tty->port = &serial_port; - spin_lock(&timer_lock); + spin_lock_bh(&timer_lock); if (tty->count == 1) { setup_timer(&serial_timer, rs_poll, (unsigned long)&serial_port); mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE); } - spin_unlock(&timer_lock); + spin_unlock_bh(&timer_lock); return 0; } @@ -99,14 +99,13 @@ static int rs_write(struct tty_struct * tty, static void rs_poll(unsigned long priv) { struct tty_port *port = (struct tty_port *)priv; - struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; int i = 0; unsigned char c; spin_lock(&timer_lock); - while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){ - __simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0); + while (simc_poll(0)) { + simc_read(0, &c, 1); tty_insert_flip_char(port, c, TTY_NORMAL); i++; } @@ -244,8 +243,7 @@ static void iss_console_write(struct console *co, const char *s, unsigned count) int len = strlen(s); if (s != 0 && *s != 0) - __simc (SYS_write, 1, (unsigned long)s, - count < len ? count : len,0,0); + simc_write(1, s, count < len ? count : len); } static struct tty_driver* iss_console_device(struct console *c, int *index) diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h index b5a4edf02d76..12b15ad1e586 100644 --- a/arch/xtensa/platforms/iss/include/platform/simcall.h +++ b/arch/xtensa/platforms/iss/include/platform/simcall.h @@ -59,56 +59,58 @@ static int errno; -static inline int __simc(int a, int b, int c, int d, int e, int f) +static inline int __simc(int a, int b, int c, int d) { int ret; register int a1 asm("a2") = a; register int b1 asm("a3") = b; register int c1 asm("a4") = c; register int d1 asm("a5") = d; - register int e1 asm("a6") = e; - register int f1 asm("a7") = f; __asm__ __volatile__ ( "simcall\n" "mov %0, a2\n" "mov %1, a3\n" : "=a" (ret), "=a" (errno), "+r"(a1), "+r"(b1) - : "r"(c1), "r"(d1), "r"(e1), "r"(f1) + : "r"(c1), "r"(d1) : "memory"); return ret; } static inline int simc_open(const char *file, int flags, int mode) { - return __simc(SYS_open, (int) file, flags, mode, 0, 0); + return __simc(SYS_open, (int) file, flags, mode); } static inline int simc_close(int fd) { - return __simc(SYS_close, fd, 0, 0, 0, 0); + return __simc(SYS_close, fd, 0, 0); } static inline int simc_ioctl(int fd, int request, void *arg) { - return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0); + return __simc(SYS_ioctl, fd, request, (int) arg); } static inline int simc_read(int fd, void *buf, size_t count) { - return __simc(SYS_read, fd, (int) buf, count, 0, 0); + return __simc(SYS_read, fd, (int) buf, count); } static inline int simc_write(int fd, const void *buf, size_t count) { - return __simc(SYS_write, fd, (int) buf, count, 0, 0); + return __simc(SYS_write, fd, (int) buf, count); } static inline int simc_poll(int fd) { struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; - return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv, - 0, 0); + return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv); +} + +static inline int simc_lseek(int fd, uint32_t off, int whence) +{ + return __simc(SYS_lseek, fd, off, whence); } #endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */ diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index e1700102f35e..da7d18240866 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -38,12 +38,6 @@ void __init platform_init(bp_tag_t* bootparam) } -#ifdef CONFIG_PCI -void platform_pcibios_init(void) -{ -} -#endif - void platform_halt(void) { pr_info(" ** Called platform_halt() **\n"); @@ -64,7 +58,9 @@ void platform_restart(void) "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" "wsr a2, icount\n\t" +#if XCHAL_NUM_IBREAK > 0 "wsr a2, ibreakenable\n\t" +#endif "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" "wsr a2, ps\n\t" diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c index 88608cc11b8c..c0edb35424ce 100644 --- a/arch/xtensa/platforms/iss/simdisk.c +++ b/arch/xtensa/platforms/iss/simdisk.c @@ -85,7 +85,7 @@ static void simdisk_transfer(struct simdisk *dev, unsigned long sector, while (nbytes > 0) { unsigned long io; - __simc(SYS_lseek, dev->fd, offset, SEEK_SET, 0, 0); + simc_lseek(dev->fd, offset, SEEK_SET); if (write) io = simc_write(dev->fd, buffer, nbytes); else @@ -139,13 +139,12 @@ static int simdisk_open(struct block_device *bdev, fmode_t mode) return 0; } -static int simdisk_release(struct gendisk *disk, fmode_t mode) +static void simdisk_release(struct gendisk *disk, fmode_t mode) { struct simdisk *dev = disk->private_data; spin_lock(&dev->lock); --dev->users; spin_unlock(&dev->lock); - return 0; } static const struct block_device_operations simdisk_ops = { @@ -177,7 +176,7 @@ static int simdisk_attach(struct simdisk *dev, const char *filename) err = -ENODEV; goto out; } - dev->size = __simc(SYS_lseek, dev->fd, 0, SEEK_END, 0, 0); + dev->size = simc_lseek(dev->fd, 0, SEEK_END); set_capacity(dev->gd, dev->size >> SECTOR_SHIFT); dev->filename = filename; pr_info("SIMDISK: %s=%s\n", dev->gd->disk_name, dev->filename); @@ -218,7 +217,7 @@ static ssize_t proc_read_simdisk(struct file *file, char __user *buf, size_t size, loff_t *ppos) { struct simdisk *dev = PDE_DATA(file_inode(file)); - char *s = dev->filename; + const char *s = dev->filename; if (s) { ssize_t n = simple_read_from_buffer(buf, size, ppos, s, strlen(s)); @@ -239,7 +238,7 @@ static ssize_t proc_write_simdisk(struct file *file, const char __user *buf, if (tmp == NULL) return -ENOMEM; - if (copy_from_user(tmp, buffer, count)) { + if (copy_from_user(tmp, buf, count)) { err = -EFAULT; goto out_free; } diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index c7d90f17886e..f9bc87966290 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c @@ -69,7 +69,9 @@ void platform_restart(void) "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" "wsr a2, icount\n\t" +#if XCHAL_NUM_IBREAK > 0 "wsr a2, ibreakenable\n\t" +#endif "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" "wsr a2, ps\n\t" diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 9d888a2a5755..96ef8eeb064e 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -60,7 +60,9 @@ void platform_restart(void) "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" "wsr a2, icount\n\t" +#if XCHAL_NUM_IBREAK > 0 "wsr a2, ibreakenable\n\t" +#endif "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" "wsr a2, ps\n\t" |