Merge branch '4.3-fixes' into mips-for-linux-next
authorRalf Baechle <ralf@linux-mips.org>
Thu, 12 Nov 2015 10:36:03 +0000 (11:36 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 12 Nov 2015 10:36:03 +0000 (11:36 +0100)
148 files changed:
Documentation/devicetree/bindings/mips/img/xilfpga.txt [new file with mode: 0644]
arch/mips/Kbuild
arch/mips/Kbuild.platforms
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/Makefile
arch/mips/bcm47xx/setup.c
arch/mips/bcm47xx/sprom.c
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/bcm63xx/cpu.c
arch/mips/bcm63xx/dev-pcmcia.c
arch/mips/bcm63xx/irq.c
arch/mips/bcm63xx/setup.c
arch/mips/bcm63xx/timer.c
arch/mips/bmips/setup.c
arch/mips/boot/dts/Makefile
arch/mips/boot/dts/brcm/bcm7346.dtsi
arch/mips/boot/dts/brcm/bcm7358.dtsi
arch/mips/boot/dts/brcm/bcm7360.dtsi
arch/mips/boot/dts/brcm/bcm7362.dtsi
arch/mips/boot/dts/brcm/bcm7425.dtsi
arch/mips/boot/dts/brcm/bcm97346dbsmb.dts
arch/mips/boot/dts/brcm/bcm97358svmb.dts
arch/mips/boot/dts/brcm/bcm97360svmb.dts
arch/mips/boot/dts/brcm/bcm97362svmb.dts
arch/mips/boot/dts/mti/malta.dts
arch/mips/boot/dts/xilfpga/Makefile [new file with mode: 0644]
arch/mips/boot/dts/xilfpga/microAptiv.dtsi [new file with mode: 0644]
arch/mips/boot/dts/xilfpga/nexys4ddr.dts [new file with mode: 0644]
arch/mips/cavium-octeon/setup.c
arch/mips/configs/bigsur_defconfig
arch/mips/configs/bmips_be_defconfig
arch/mips/configs/bmips_stb_defconfig
arch/mips/configs/capcella_defconfig
arch/mips/configs/e55_defconfig
arch/mips/configs/fuloong2e_defconfig
arch/mips/configs/lasat_defconfig
arch/mips/configs/lemote2f_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/malta_kvm_defconfig
arch/mips/configs/malta_kvm_guest_defconfig
arch/mips/configs/malta_qemu_32r6_defconfig
arch/mips/configs/maltaaprp_defconfig
arch/mips/configs/maltasmvp_eva_defconfig
arch/mips/configs/maltaup_defconfig
arch/mips/configs/maltaup_xpa_defconfig
arch/mips/configs/mpc30x_defconfig
arch/mips/configs/xilfpga_defconfig [new file with mode: 0644]
arch/mips/include/asm/abi.h
arch/mips/include/asm/bcache.h
arch/mips/include/asm/clocksource.h [new file with mode: 0644]
arch/mips/include/asm/compat.h
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/debug.h [new file with mode: 0644]
arch/mips/include/asm/elf.h
arch/mips/include/asm/fw/fw.h
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
arch/mips/include/asm/mach-malta/malta-dtshim.h [new file with mode: 0644]
arch/mips/include/asm/mach-ralink/mt7620.h
arch/mips/include/asm/mach-ralink/ralink_regs.h
arch/mips/include/asm/mach-ralink/rt305x.h
arch/mips/include/asm/mach-xilfpga/irq.h [new file with mode: 0644]
arch/mips/include/asm/mips-cm.h
arch/mips/include/asm/mips-cpc.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/page.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/vdso.h
arch/mips/include/uapi/asm/Kbuild
arch/mips/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/mips/jz4740/board-qi_lb60.c
arch/mips/kernel/Makefile
arch/mips/kernel/cps-vec-ns16550.S [new file with mode: 0644]
arch/mips/kernel/cps-vec.S
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/csrc-r4k.c
arch/mips/kernel/idle.c
arch/mips/kernel/mips-cm.c
arch/mips/kernel/mips-cpc.c
arch/mips/kernel/mips-r2-to-r6-emul.c
arch/mips/kernel/segment.c
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smp-cps.c
arch/mips/kernel/smp-gic.c
arch/mips/kernel/spinlock_test.c
arch/mips/kernel/stacktrace.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vdso.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/kvm/locore.S
arch/mips/lantiq/clk.h
arch/mips/lantiq/irq.c
arch/mips/lantiq/prom.c
arch/mips/lantiq/xway/clk.c
arch/mips/lantiq/xway/prom.c
arch/mips/lantiq/xway/reset.c
arch/mips/lantiq/xway/sysctrl.c
arch/mips/lib/Makefile
arch/mips/lib/bswapdi.c [new file with mode: 0644]
arch/mips/lib/bswapsi.c [new file with mode: 0644]
arch/mips/loongson64/Kconfig
arch/mips/loongson64/common/Makefile
arch/mips/loongson64/lemote-2f/Makefile
arch/mips/math-emu/me-debugfs.c
arch/mips/mm/Makefile
arch/mips/mm/sc-debugfs.c [new file with mode: 0644]
arch/mips/mm/sc-mips.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/Makefile
arch/mips/mti-malta/malta-dtshim.c [new file with mode: 0644]
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-memory.c
arch/mips/mti-malta/malta-setup.c
arch/mips/netlogic/xlp/dt.c
arch/mips/pci/pci-rt3883.c
arch/mips/pistachio/init.c
arch/mips/ralink/cevt-rt3352.c
arch/mips/ralink/early_printk.c
arch/mips/ralink/mt7620.c
arch/mips/ralink/of.c
arch/mips/ralink/prom.c
arch/mips/ralink/reset.c
arch/mips/ralink/rt288x.c
arch/mips/ralink/rt305x.c
arch/mips/ralink/rt3883.c
arch/mips/vdso/.gitignore [new file with mode: 0644]
arch/mips/vdso/Makefile [new file with mode: 0644]
arch/mips/vdso/elf.S [new file with mode: 0644]
arch/mips/vdso/genvdso.c [new file with mode: 0644]
arch/mips/vdso/genvdso.h [new file with mode: 0644]
arch/mips/vdso/gettimeofday.c [new file with mode: 0644]
arch/mips/vdso/sigreturn.S [new file with mode: 0644]
arch/mips/vdso/vdso.h [new file with mode: 0644]
arch/mips/vdso/vdso.lds.S [new file with mode: 0644]
arch/mips/xilfpga/Kconfig [new file with mode: 0644]
arch/mips/xilfpga/Makefile [new file with mode: 0644]
arch/mips/xilfpga/Platform [new file with mode: 0644]
arch/mips/xilfpga/init.c [new file with mode: 0644]
arch/mips/xilfpga/intc.c [new file with mode: 0644]
arch/mips/xilfpga/time.c [new file with mode: 0644]
drivers/clocksource/mips-gic-timer.c
drivers/irqchip/irq-mips-gic.c
include/linux/irqchip/mips-gic.h

diff --git a/Documentation/devicetree/bindings/mips/img/xilfpga.txt b/Documentation/devicetree/bindings/mips/img/xilfpga.txt
new file mode 100644 (file)
index 0000000..57e7ee9
--- /dev/null
@@ -0,0 +1,83 @@
+Imagination University Program MIPSfpga
+=======================================
+
+Under the Imagination University Program, a microAptiv UP core has been
+released for academic usage.
+
+As we are dealing with a MIPS core instantiated on an FPGA, specifications
+are fluid and can be varied in RTL.
+
+This binding document is provided as baseline guidance for the example
+project provided by IMG.
+
+The example project runs on the Nexys4DDR board by Digilent powered by
+the ARTIX-7 FPGA by Xilinx.
+
+Relevant details about the example project and the Nexys4DDR board:
+
+- microAptiv UP core m14Kc
+- 50MHz clock speed
+- 128Mbyte DDR RAM     at 0x0000_0000
+- 8Kbyte RAM           at 0x1000_0000
+- axi_intc             at 0x1020_0000
+- axi_uart16550                at 0x1040_0000
+- axi_gpio             at 0x1060_0000
+- axi_i2c              at 0x10A0_0000
+- custom_gpio          at 0x10C0_0000
+- axi_ethernetlite     at 0x10E0_0000
+- 8Kbyte BootRAM       at 0x1FC0_0000
+
+Required properties:
+--------------------
+ - compatible: Must include "digilent,nexys4ddr","img,xilfpga".
+
+CPU nodes:
+----------
+A "cpus" node is required.  Required properties:
+ - #address-cells: Must be 1.
+ - #size-cells: Must be 0.
+A CPU sub-node is also required for at least CPU 0. Required properties:
+ - device_type: Must be "cpu".
+ - compatible: Must be "mips,m14Kc".
+ - reg: Must be <0>.
+ - clocks: phandle to ext clock for fixed-clock received by MIPS core.
+
+Example:
+
+       compatible = "img,xilfpga","digilent,nexys4ddr";
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,m14Kc";
+                       reg = <0>;
+                       clocks  = <&ext>;
+               };
+       };
+
+       ext: ext {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <50000000>;
+       };
+
+Boot protocol:
+--------------
+
+The BootRAM is a writeable "RAM" in FPGA at 0x1FC0_0000.
+This is for easy reprogrammibility via JTAG.
+
+The BootRAM initializes the cache and the axi_uart peripheral.
+
+DDR initialization is already handled by a HW IP block.
+
+When the example project bitstream is loaded, the cpu_reset button
+needs to be pressed.
+
+The bootram initializes the cache and axi_uart.
+Then outputs MIPSFPGA\n\r on the serial port on the Nexys4DDR board.
+
+At this point, the board is ready to load the Linux kernel
+vmlinux file via JTAG.
index dd295335891a03dc2cfbb657883135749f38083e..5c3f688a5232f2690007a8e92a12ba76ae11b4a5 100644 (file)
@@ -17,6 +17,7 @@ obj- := $(platform-)
 obj-y += kernel/
 obj-y += mm/
 obj-y += net/
+obj-y += vdso/
 
 ifdef CONFIG_KVM
 obj-y += kvm/
index a424e46b50afaa85f5e081f5f9ee8e31887816bb..a96c81d1d22e6afce0973161639024e93346fd0b 100644 (file)
@@ -33,6 +33,7 @@ platforms += sibyte
 platforms += sni
 platforms += txx9
 platforms += vr41xx
+platforms += xilfpga
 
 # include the platform specific files
 include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
index e3aa5b0b4ef17771fbd2afa1557f29ee6a7a2b3d..71683a8533723866872de04f7194d07a28f33045 100644 (file)
@@ -5,6 +5,7 @@ config MIPS
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
        select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
+       select ARCH_USE_BUILTIN_BSWAP
        select HAVE_CONTEXT_TRACKING
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_IDE
@@ -60,6 +61,8 @@ config MIPS
        select SYSCTL_EXCEPTION_TRACE
        select HAVE_VIRT_CPU_ACCOUNTING_GEN
        select HAVE_IRQ_TIME_ACCOUNTING
+       select GENERIC_TIME_VSYSCALL
+       select ARCH_CLOCKSOURCE_DATA
 
 menu "Machine selection"
 
@@ -401,6 +404,28 @@ config MACH_PISTACHIO
        help
          This enables support for the IMG Pistachio SoC platform.
 
+config MACH_XILFPGA
+       bool "MIPSfpga Xilinx based boards"
+       select ARCH_REQUIRE_GPIOLIB
+       select BOOT_ELF32
+       select BOOT_RAW
+       select BUILTIN_DTB
+       select CEVT_R4K
+       select COMMON_CLK
+       select CSRC_R4K
+       select IRQ_MIPS_CPU
+       select LIBFDT
+       select MIPS_CPU_SCACHE
+       select SYS_HAS_EARLY_PRINTK
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_ZBOOT_UART16550
+       select USE_OF
+       select USE_GENERIC_EARLY_PRINTK_8250
+       help
+         This enables support for the IMG University Program MIPSfpga platform.
+
 config MIPS_MALTA
        bool "MIPS Malta board"
        select ARCH_MAY_HAVE_PC_FDC
@@ -424,6 +449,7 @@ config MIPS_MALTA
        select MIPS_L1_CACHE_SHIFT_6
        select PCI_GT64XXX_PCI0
        select MIPS_MSC
+       select SMP_UP if SMP
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_HAS_CPU_MIPS32_R2
@@ -449,6 +475,8 @@ config MIPS_MALTA
        select SYS_SUPPORTS_ZBOOT
        select USE_OF
        select ZONE_DMA32 if 64BIT
+       select BUILTIN_DTB
+       select LIBFDT
        help
          This enables support for the MIPS Technologies Malta evaluation
          board.
@@ -964,6 +992,7 @@ source "arch/mips/loongson32/Kconfig"
 source "arch/mips/loongson64/Kconfig"
 source "arch/mips/netlogic/Kconfig"
 source "arch/mips/paravirt/Kconfig"
+source "arch/mips/xilfpga/Kconfig"
 
 endmenu
 
@@ -1036,6 +1065,9 @@ config CSRC_R4K
 config CSRC_SB1250
        bool
 
+config MIPS_CLOCK_VSYSCALL
+       def_bool CSRC_R4K || CLKSRC_MIPS_GIC
+
 config GPIO_TXX9
        select ARCH_REQUIRE_GPIOLIB
        bool
@@ -2529,6 +2561,9 @@ choice
        help
         Allows the configuration of the timer frequency.
 
+       config HZ_24
+               bool "24 HZ" if SYS_SUPPORTS_24HZ || SYS_SUPPORTS_ARBIT_HZ
+
        config HZ_48
                bool "48 HZ" if SYS_SUPPORTS_48HZ || SYS_SUPPORTS_ARBIT_HZ
 
@@ -2552,6 +2587,9 @@ choice
 
 endchoice
 
+config SYS_SUPPORTS_24HZ
+       bool
+
 config SYS_SUPPORTS_48HZ
        bool
 
@@ -2575,13 +2613,18 @@ config SYS_SUPPORTS_1024HZ
 
 config SYS_SUPPORTS_ARBIT_HZ
        bool
-       default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \
-                    !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \
-                    !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \
+       default y if !SYS_SUPPORTS_24HZ && \
+                    !SYS_SUPPORTS_48HZ && \
+                    !SYS_SUPPORTS_100HZ && \
+                    !SYS_SUPPORTS_128HZ && \
+                    !SYS_SUPPORTS_250HZ && \
+                    !SYS_SUPPORTS_256HZ && \
+                    !SYS_SUPPORTS_1000HZ && \
                     !SYS_SUPPORTS_1024HZ
 
 config HZ
        int
+       default 24 if HZ_24
        default 48 if HZ_48
        default 100 if HZ_100
        default 128 if HZ_128
@@ -2685,7 +2728,7 @@ config BUILTIN_DTB
        bool
 
 choice
-       prompt "Kernel appended dtb support" if OF
+       prompt "Kernel appended dtb support" if USE_OF
        default MIPS_NO_APPENDED_DTB
 
        config MIPS_NO_APPENDED_DTB
@@ -2693,6 +2736,20 @@ choice
                help
                  Do not enable appended dtb support.
 
+       config MIPS_ELF_APPENDED_DTB
+               bool "vmlinux"
+               help
+                 With this option, the boot code will look for a device tree binary
+                 DTB) included in the vmlinux ELF section .appended_dtb. By default
+                 it is empty and the DTB can be appended using binutils command
+                 objcopy:
+
+                   objcopy --update-section .appended_dtb=<filename>.dtb vmlinux
+
+                 This is meant as a backward compatiblity convenience for those
+                 systems with a bootloader that can't be upgraded to accommodate
+                 the documented boot protocol using a device tree.
+
        config MIPS_RAW_APPENDED_DTB
                bool "vmlinux.bin"
                help
@@ -2729,6 +2786,25 @@ choice
                  if you don't intend to always append a DTB.
 endchoice
 
+choice
+       prompt "Kernel command line type" if !CMDLINE_OVERRIDE
+       default MIPS_CMDLINE_FROM_DTB if USE_OF && !ATH79 && !MACH_INGENIC && \
+                                        !MIPS_MALTA && !MIPS_SEAD3 && \
+                                        !CAVIUM_OCTEON_SOC
+       default MIPS_CMDLINE_FROM_BOOTLOADER
+
+       config MIPS_CMDLINE_FROM_DTB
+               depends on USE_OF
+               bool "Dtb kernel arguments if available"
+
+       config MIPS_CMDLINE_DTB_EXTEND
+               depends on USE_OF
+               bool "Extend dtb kernel arguments with bootloader arguments"
+
+       config MIPS_CMDLINE_FROM_BOOTLOADER
+               bool "Bootloader kernel arguments if available"
+endchoice
+
 endmenu
 
 config LOCKDEP_SUPPORT
@@ -2739,6 +2815,10 @@ config STACKTRACE_SUPPORT
        bool
        default y
 
+config HAVE_LATENCYTOP_SUPPORT
+       bool
+       default y
+
 config PGTABLE_LEVELS
        int
        default 3 if 64BIT && !PAGE_SIZE_64KB
index e250524021aca8ec7e1b79bfd0b4f088d96f109d..f0e314ceb8baa84d36ea6664772f71df46ad003f 100644 (file)
@@ -113,4 +113,76 @@ config SPINLOCK_TEST
        help
          Add several files to the debugfs to test spinlock speed.
 
+if CPU_MIPSR6
+
+choice
+       prompt "Compact branch policy"
+       default MIPS_COMPACT_BRANCHES_OPTIMAL
+
+config MIPS_COMPACT_BRANCHES_NEVER
+       bool "Never (force delay slot branches)"
+       help
+         Pass the -mcompact-branches=never flag to the compiler in order to
+         force it to always emit branches with delay slots, and make no use
+         of the compact branch instructions introduced by MIPSr6. This is
+         useful if you suspect there may be an issue with compact branches in
+         either the compiler or the CPU.
+
+config MIPS_COMPACT_BRANCHES_OPTIMAL
+       bool "Optimal (use where beneficial)"
+       help
+         Pass the -mcompact-branches=optimal flag to the compiler in order for
+         it to make use of compact branch instructions where it deems them
+         beneficial, and use branches with delay slots elsewhere. This is the
+         default compiler behaviour, and should be used unless you have a
+         reason to choose otherwise.
+
+config MIPS_COMPACT_BRANCHES_ALWAYS
+       bool "Always (force compact branches)"
+       help
+         Pass the -mcompact-branches=always flag to the compiler in order to
+         force it to always emit compact branches, making no use of branch
+         instructions with delay slots. This can result in more compact code
+         which may be beneficial in some scenarios.
+
+endchoice
+
+endif # CPU_MIPSR6
+
+config SCACHE_DEBUGFS
+       bool "L2 cache debugfs entries"
+       depends on DEBUG_FS
+       help
+         Enable this to allow parts of the L2 cache configuration, such as
+         whether or not prefetching is enabled, to be exposed to userland
+         via debugfs.
+
+         If unsure, say N.
+
+menuconfig MIPS_CPS_NS16550
+       bool "CPS SMP NS16550 UART output"
+       depends on MIPS_CPS
+       help
+         Output debug information via an ns16550 compatible UART if exceptions
+         occur early in the boot process of a secondary core.
+
+if MIPS_CPS_NS16550
+
+config MIPS_CPS_NS16550_BASE
+       hex "UART Base Address"
+       default 0x1b0003f8 if MIPS_MALTA
+       help
+         The base address of the ns16550 compatible UART on which to output
+         debug information from the early stages of core startup.
+
+config MIPS_CPS_NS16550_SHIFT
+       int "UART Register Shift"
+       default 0 if MIPS_MALTA
+       help
+         The number of bits to shift ns16550 register indices by in order to
+         form their addresses. That is, log base 2 of the span between
+         adjacent ns16550 registers in the system.
+
+endif # MIPS_CPS_NS16550
+
 endmenu
index 252e347958f383354a597323078512846f592d52..3f70ba54ae21e909973ad9913eb71151fcc50492 100644 (file)
@@ -204,6 +204,10 @@ toolchain-msa                              := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(
 cflags-$(toolchain-msa)                        += -DTOOLCHAIN_SUPPORTS_MSA
 endif
 
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER)   += -mcompact-branches=never
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_ALWAYS)  += -mcompact-branches=always
+
 #
 # Firmware support
 #
index 17503a05938e6c3848e950acd366361fd768ab0d..6d38948f0f1ed4a95f29d883cd7fb4abe65ed327 100644 (file)
@@ -105,11 +105,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
                                  struct ssb_init_invariants *iv)
 {
        char buf[20];
+       int len, err;
 
        /* Fill boardinfo structure */
        memset(&iv->boardinfo, 0 , sizeof(struct ssb_boardinfo));
 
-       bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
+       len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
+       if (len > 0) {
+               err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
+               if (err)
+                       pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
+                               buf);
+       }
+       if (!iv->boardinfo.vendor)
+               iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+
+       len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
+       if (len > 0) {
+               err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
+               if (err)
+                       pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
+                               buf);
+       }
 
        memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
        bcm47xx_fill_sprom(&iv->sprom, NULL, false);
index 2d5c7a7f24bb943669d7c43fb66bee1482ff6412..a7e569c7968ea7e8bc1a1ce3e629fc54cc2710ee 100644 (file)
@@ -60,9 +60,9 @@ static int get_nvram_var(const char *prefix, const char *postfix,
 }
 
 #define NVRAM_READ_VAL(type)                                           \
-static void nvram_read_ ## type (const char *prefix,                   \
-                                const char *postfix, const char *name, \
-                                type *val, type allset, bool fallback) \
+static void nvram_read_ ## type(const char *prefix,                    \
+                               const char *postfix, const char *name,  \
+                               type *val, type allset, bool fallback)  \
 {                                                                      \
        char buf[100];                                                  \
        int err;                                                        \
@@ -422,7 +422,10 @@ static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
        int i;
 
        for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
-               struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+               struct ssb_sprom_core_pwr_info *pwr_info;
+
+               pwr_info = &sprom->core_pwr_info[i];
+
                snprintf(postfix, sizeof(postfix), "%i", i);
                nvram_read_u8(prefix, postfix, "maxp2ga",
                              &pwr_info->maxpwr_2g, 0, fallback);
@@ -470,7 +473,10 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
        int i;
 
        for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
-               struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+               struct ssb_sprom_core_pwr_info *pwr_info;
+
+               pwr_info = &sprom->core_pwr_info[i];
+
                snprintf(postfix, sizeof(postfix), "%i", i);
                nvram_read_u16(prefix, postfix, "pa2gw3a",
                               &pwr_info->pa_2g[3], 0, fallback);
@@ -535,10 +541,11 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
        nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
 
        /* The address prefix 00:90:4C is used by Broadcom in their initial
-          configuration. When a mac address with the prefix 00:90:4C is used
-          all devices from the same series are sharing the same mac address.
-          To prevent mac address collisions we replace them with a mac address
-          based on the base address. */
+        * configuration. When a mac address with the prefix 00:90:4C is used
+        * all devices from the same series are sharing the same mac address.
+        * To prevent mac address collisions we replace them with a mac address
+        * based on the base address.
+        */
        if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
                u8 mac[6];
 
@@ -592,32 +599,23 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
        bcm47xx_sprom_fill_auto(sprom, prefix, fallback);
 }
 
-#ifdef CONFIG_BCM47XX_SSB
-void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
-                               const char *prefix)
-{
-       nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
-                      true);
-       if (!boardinfo->vendor)
-               boardinfo->vendor = SSB_BOARDVENDOR_BCM;
-
-       nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
-}
-#endif
-
 #if defined(CONFIG_BCM47XX_SSB)
 static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
 {
        char prefix[10];
 
-       if (bus->bustype == SSB_BUSTYPE_PCI) {
+       switch (bus->bustype) {
+       case SSB_BUSTYPE_SSB:
+               bcm47xx_fill_sprom(out, NULL, false);
+               return 0;
+       case SSB_BUSTYPE_PCI:
                memset(out, 0, sizeof(struct ssb_sprom));
                snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
                         bus->host_pci->bus->number + 1,
                         PCI_SLOT(bus->host_pci->devfn));
                bcm47xx_fill_sprom(out, prefix, false);
                return 0;
-       } else {
+       default:
                pr_warn("Unable to fill SPROM for given bustype.\n");
                return -EINVAL;
        }
index 33727e7f0c79f756a004dc4d5fd964b31b3d6058..b2097c0d2ed78b554ab321c6620767d3ccd29f71 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -31,7 +33,6 @@
 
 #include <uapi/linux/bcm933xx_hcs.h>
 
-#define PFX    "board_bcm963xx: "
 
 #define HCS_OFFSET_128K                        0x20000
 
@@ -740,7 +741,7 @@ int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
                memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
                return 0;
        } else {
-               printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+               pr_err("unable to fill SPROM for given bustype\n");
                return -EINVAL;
        }
 }
@@ -784,7 +785,7 @@ void __init board_prom_init(void)
                         cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
        else
                strcpy(cfe_version, "unknown");
-       printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
+       pr_info("CFE version: %s\n", cfe_version);
 
        bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
 
@@ -808,8 +809,7 @@ void __init board_prom_init(void)
                char name[17];
                memcpy(name, board_name, 16);
                name[16] = 0;
-               printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
-                      name);
+               pr_err("unknown bcm963xx board: %s\n", name);
                return;
        }
 
@@ -854,7 +854,7 @@ void __init board_setup(void)
 {
        if (!board.name[0])
                panic("unable to detect bcm963xx board");
-       printk(KERN_INFO PFX "board name: %s\n", board.name);
+       pr_info("board name: %s\n", board.name);
 
        /* make sure we're running on expected cpu */
        if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
@@ -910,7 +910,7 @@ int __init board_register_devices(void)
                memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
                if (ssb_arch_register_fallback_sprom(
                                &bcm63xx_get_fallback_sprom) < 0)
-                       pr_err(PFX "failed to register fallback SPROM\n");
+                       pr_err("failed to register fallback SPROM\n");
        }
 #endif
 
index 307ec8b8e41c1eb12129844c9744ed9dd9441fb7..1c7c3fbfa1f330afae049d30e48b731cd6b46499 100644 (file)
@@ -376,10 +376,10 @@ void __init bcm63xx_cpu_init(void)
        bcm63xx_cpu_freq = detect_cpu_clock();
        bcm63xx_memory_size = detect_memory_size();
 
-       printk(KERN_INFO "Detected Broadcom 0x%04x CPU revision %02x\n",
-              bcm63xx_cpu_id, bcm63xx_cpu_rev);
-       printk(KERN_INFO "CPU frequency is %u MHz\n",
-              bcm63xx_cpu_freq / 1000000);
-       printk(KERN_INFO "%uMB of RAM installed\n",
-              bcm63xx_memory_size >> 20);
+       pr_info("Detected Broadcom 0x%04x CPU revision %02x\n",
+               bcm63xx_cpu_id, bcm63xx_cpu_rev);
+       pr_info("CPU frequency is %u MHz\n",
+               bcm63xx_cpu_freq / 1000000);
+       pr_info("%uMB of RAM installed\n",
+               bcm63xx_memory_size >> 20);
 }
index a551bab5ecb94b2aafce31787cea8e6bb31dbd10..9496cd23695149d992e254e7ad2830d9d9860719 100644 (file)
@@ -139,6 +139,6 @@ int __init bcm63xx_pcmcia_register(void)
        return platform_device_register(&bcm63xx_pcmcia_device);
 
 out_err:
-       printk(KERN_ERR "unable to set pcmcia chip select\n");
+       pr_err("unable to set pcmcia chip select\n");
        return ret;
 }
index 1a47ec2a09062b59bf76b1b4de9270435698b88e..c96139097ae270c9fbf6252d086611159bd6503d 100644 (file)
@@ -311,7 +311,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
                break;
 
        default:
-               printk(KERN_ERR "bogus flow type combination given !\n");
+               pr_err("bogus flow type combination given !\n");
                return -EINVAL;
        }
 
index 240fb4ffa55c8625ef26354e29cff25c58f63b68..2be9caaa208530757af7ab41eaa6104c9a0616da 100644 (file)
@@ -24,7 +24,7 @@
 
 void bcm63xx_machine_halt(void)
 {
-       printk(KERN_INFO "System halted\n");
+       pr_info("System halted\n");
        while (1)
                ;
 }
@@ -34,7 +34,7 @@ static void bcm6348_a1_reboot(void)
        u32 reg;
 
        /* soft reset all blocks */
-       printk(KERN_INFO "soft-resetting all blocks ...\n");
+       pr_info("soft-resetting all blocks ...\n");
        reg = bcm_perf_readl(PERF_SOFTRESET_REG);
        reg &= ~SOFTRESET_6348_ALL;
        bcm_perf_writel(reg, PERF_SOFTRESET_REG);
@@ -46,7 +46,7 @@ static void bcm6348_a1_reboot(void)
        mdelay(10);
 
        /* Jump to the power on address. */
-       printk(KERN_INFO "jumping to reset vector.\n");
+       pr_info("jumping to reset vector.\n");
        /* set high vectors (base at 0xbfc00000 */
        set_c0_status(ST0_BEV | ST0_ERL);
        /* run uncached in kseg0 */
@@ -110,7 +110,7 @@ void bcm63xx_machine_reboot(void)
        if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
                bcm6348_a1_reboot();
 
-       printk(KERN_INFO "triggering watchdog soft-reset...\n");
+       pr_info("triggering watchdog soft-reset...\n");
        if (BCMCPU_IS_6328()) {
                bcm_wdt_writel(1, WDT_SOFTRESET_REG);
        } else {
index 5f11359815688d5350a56cce5704971e4e533b1a..2110359c00e5cb79cf1b04b21c73c83e81f79ea8 100644 (file)
@@ -195,7 +195,7 @@ int bcm63xx_timer_init(void)
        irq = bcm63xx_get_irq_number(IRQ_TIMER);
        ret = request_irq(irq, timer_interrupt, 0, "bcm63xx_timer", NULL);
        if (ret) {
-               printk(KERN_ERR "bcm63xx_timer: failed to register irq\n");
+               pr_err("%s: failed to register irq\n", __func__);
                return ret;
        }
 
index 526ec2789bb9ef0ba208079d307f9580c408c7ec..5b16d2955fbb864afae0103753bd8d0d115eba0e 100644 (file)
@@ -157,7 +157,6 @@ void __init plat_mem_setup(void)
                panic("no dtb found");
 
        __dt_setup_arch(dtb);
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 
        for (q = bmips_quirk_list; q->quirk_fn; q++) {
                if (of_flat_dt_is_compatible(of_get_flat_dt_root(),
index 778a34028c1b1fb6b67754053e24ea09828eee31..0571ef7697b02e9c51eea5e7c47dd92f3536a418 100644 (file)
@@ -6,6 +6,7 @@ dts-dirs        += mti
 dts-dirs       += netlogic
 dts-dirs       += qca
 dts-dirs       += ralink
+dts-dirs       += xilfpga
 
 obj-y          := $(addsuffix /, $(dts-dirs))
 
index d817bb46b934fd1cb81388dd0d492f55c74171ed..d4bf52cfcf170ee8ac84daa874495e0a6420e542 100644 (file)
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406780 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0xf000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <59>;
+                       interrupts = <59>, <57>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <60>, <58>, <62>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@406380 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406380 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
+               bsce: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bsce";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
                        interrupts = <76>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <40>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       brcm,broken-ncq;
+                       brcm,broken-phy;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@1800000 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
index 277a90adc1a78cb07834dd7c870ac374cc1557da..8e2501694d03fbd93827aeda79ef22f7cfd5d094 100644 (file)
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406600 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <56>;
+                       interrupts = <56>, <54>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <57>, <55>, <59>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
index 9e1e571ba346ad7a240faf5a18a54b3f108e3cc7..7e5f76040fb898b19a4bbc301c8a20f3b9368aa4 100644 (file)
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406600 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <56>;
+                       interrupts = <56>, <54>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <57>, <55>, <59>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
index 6e65db86fc618471df11f543b2569872d36f85b4..c739ea77acb0dfe17363ec52cf390cace407e54c 100644 (file)
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406600 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <56>;
+                       interrupts = <56>, <54>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <57>, <55>, <59>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscd: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
                        interrupts = <66>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <86>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       brcm,broken-ncq;
+                       brcm,broken-phy;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@1800000 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
index 5b660b617eaddb799d04ad6f2e86f15fd767e17e..e24d41ab4e30f9163605180d78605fc02a477db6 100644 (file)
                        interrupts = <73>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <40>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       brcm,broken-ncq;
+                       brcm,broken-phy;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@1800000 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
index 3fe0445b9d37bae86ed53564b09747bd321653dd..d3d28816a0270716d9634b553bcc30962584ef1a 100644 (file)
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
+&bsce {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
 &ohci3 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+};
index a8dc01e3031317f577db8e5c5bfc8f08363b045a..02ce6b429dc47b104633491cee178499e677f1f4 100644 (file)
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
index eee8b0e32681541266b70caa5d4b07ff789d35aa..d48462e091f176e6be77eeb301f769b40ef1afbc 100644 (file)
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
index 739c2ef5663b5cec059ee167cbb92451bc010db7..3cfcaebe7f79db34e8c340ba71a1238f327b78c3 100644 (file)
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
 &ohci0 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+};
index c678115f5b7f7c5b194d321b060b15df58cada4c..b18c46637d21b4ae7b85636d98a3353332022bbc 100644 (file)
@@ -1,5 +1,9 @@
 /dts-v1/;
 
+/memreserve/ 0x00000000 0x00001000;    /* YAMON exception vectors */
+/memreserve/ 0x00001000 0x000ef000;    /* YAMON */
+/memreserve/ 0x000f0000 0x00010000;    /* PIIX4 ISA memory */
+
 / {
        #address-cells = <1>;
        #size-cells = <1>;
diff --git a/arch/mips/boot/dts/xilfpga/Makefile b/arch/mips/boot/dts/xilfpga/Makefile
new file mode 100644 (file)
index 0000000..913a752
--- /dev/null
@@ -0,0 +1,9 @@
+dtb-$(CONFIG_XILFPGA_NEXYS4DDR)        += nexys4ddr.dtb
+
+obj-y                          += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+
+# Force kbuild to make empty built-in.o if necessary
+obj-                           += dummy.o
+
+always                         := $(dtb-y)
+clean-files    := *.dtb *.dtb.S
diff --git a/arch/mips/boot/dts/xilfpga/microAptiv.dtsi b/arch/mips/boot/dts/xilfpga/microAptiv.dtsi
new file mode 100644 (file)
index 0000000..81d518e
--- /dev/null
@@ -0,0 +1,21 @@
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "img,xilfpga";
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,m14Kc";
+                       clocks  = <&ext>;
+                       reg = <0>;
+               };
+       };
+
+       ext: ext {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+       };
+};
diff --git a/arch/mips/boot/dts/xilfpga/nexys4ddr.dts b/arch/mips/boot/dts/xilfpga/nexys4ddr.dts
new file mode 100644 (file)
index 0000000..686ebd1
--- /dev/null
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+#include "microAptiv.dtsi"
+
+/ {
+       compatible = "digilent,nexys4ddr";
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x08000000>;
+       };
+
+       cpuintc: interrupt-controller@0 {
+               #address-cells = <0>;
+               #interrupt-cells = <1>;
+               interrupt-controller;
+               compatible = "mti,cpu-interrupt-controller";
+       };
+
+       axi_gpio: gpio@10600000 {
+               #gpio-cells = <1>;
+               compatible = "xlnx,xps-gpio-1.00.a";
+               gpio-controller;
+               reg = <0x10600000 0x10000>;
+               xlnx,all-inputs = <0x0>;
+               xlnx,dout-default = <0x0>;
+               xlnx,gpio-width = <0x16>;
+               xlnx,interrupt-present = <0x0>;
+               xlnx,is-dual = <0x0>;
+               xlnx,tri-default = <0xffffffff>;
+       } ;
+
+       axi_uart16550: serial@10400000 {
+               compatible = "ns16550a";
+               reg = <0x10400000 0x10000>;
+
+               reg-shift = <2>;
+               reg-offset = <0x1000>;
+
+               clocks  = <&ext>;
+       };
+};
+
+&ext {
+       clock-frequency = <50000000>;
+};
index bd634259eab9d6b0f7d1b8e746d0b11c01f0950d..cd7101fb622705c26fa40bfd0f58ca4d23d05dcb 100644 (file)
@@ -1081,6 +1081,7 @@ void __init prom_free_prom_memory(void)
 
 int octeon_prune_device_tree(void);
 
+extern const char __appended_dtb;
 extern const char __dtb_octeon_3xxx_begin;
 extern const char __dtb_octeon_68xx_begin;
 void __init device_tree_init(void)
@@ -1088,11 +1089,19 @@ void __init device_tree_init(void)
        const void *fdt;
        bool do_prune;
 
+#ifdef CONFIG_MIPS_ELF_APPENDED_DTB
+       if (!fdt_check_header(&__appended_dtb)) {
+               fdt = &__appended_dtb;
+               do_prune = false;
+               pr_info("Using appended Device Tree.\n");
+       } else
+#endif
        if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) {
                fdt = phys_to_virt(octeon_bootinfo->fdt_addr);
                if (fdt_check_header(fdt))
                        panic("Corrupt Device Tree passed to kernel.");
                do_prune = false;
+               pr_info("Using passed Device Tree.\n");
        } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
                fdt = &__dtb_octeon_68xx_begin;
                do_prune = true;
@@ -1106,8 +1115,6 @@ void __init device_tree_init(void)
        if (do_prune) {
                octeon_prune_device_tree();
                pr_info("Using internal Device Tree.\n");
-       } else {
-               pr_info("Using passed Device Tree.\n");
        }
        unflatten_and_copy_device_tree();
 }
index 1cdff6b6327d2753b41f76e348ee0bde97cc84dc..b3e7a1b61220bdff725a28661e39ab75e0744f72 100644 (file)
@@ -122,20 +122,20 @@ CONFIG_EEPROM_MAX6875=y
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_IDETAPE=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_CHR_DEV_SCH=m
 CONFIG_ATA=y
 CONFIG_SATA_SIL24=y
+CONFIG_PATA_CMD64X=y
+CONFIG_PATA_IT8213=m
 CONFIG_PATA_SIL680=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
index f5585c8f35ad83539951a426b7b0871e4fcd8fb2..24dcb90b0f64b993dae12cd30a3e1aa5a6933f58 100644 (file)
@@ -8,7 +8,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y
 # CONFIG_SWAP is not set
 CONFIG_NO_HZ=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
+CONFIG_RD_GZIP=y
 CONFIG_EXPERT=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
@@ -33,6 +33,7 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PRINTK_TIME=y
 CONFIG_BRCMSTB_GISB_ARB=y
 CONFIG_MTD=y
 CONFIG_MTD_CFI=y
index 400a47ec1ef1e3a223da49d61c8abe0cdd2a04e3..4eb5d6e9cf8f1f256cbcf91b653746cb53ee0dde 100644 (file)
@@ -9,7 +9,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y
 # CONFIG_SWAP is not set
 CONFIG_NO_HZ=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
+CONFIG_RD_GZIP=y
 CONFIG_EXPERT=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
@@ -34,6 +34,7 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PRINTK_TIME=y
 CONFIG_BRCMSTB_GISB_ARB=y
 CONFIG_MTD=y
 CONFIG_MTD_CFI=y
index 5135dc0b950aadbd325a0826c5918f8cca5bd6c4..2924ba34a01bf8d4bad7297a002ef2e4161d17ee 100644 (file)
@@ -31,9 +31,9 @@ CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_FW_LOADER=m
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_PHYLIB=m
 CONFIG_MARVELL_PHY=m
index 0126e66d60cbbf92a0a59a68abbf06ada87fe599..e94d266c4b97995f23b0b3e9c64fc7cd80adc2cf 100644 (file)
@@ -14,9 +14,9 @@ CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
index a75c65da08b4b7d573c45e0e429acd6dd54300c9..87435897fd50c802725be994843e07e1bc8ac105 100644 (file)
@@ -34,7 +34,7 @@ CONFIG_MIPS32_N32=y
 CONFIG_PM=y
 # CONFIG_SUSPEND is not set
 CONFIG_HIBERNATION=y
-CONFIG_PM_STD_PARTITION="/dev/hda3"
+CONFIG_PM_STD_PARTITION="/dev/sda3"
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -114,20 +114,16 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_RAM=m
 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_TASK_IOCTL=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_VIA=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_MACVLAN=m
 CONFIG_VETH=m
index 0179c7fa014f1c093099198bebe5585057eb93f2..e620a2c3eba478a955ab75303f57f7824d3bf61f 100644 (file)
@@ -35,11 +35,11 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_CMD64X=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCI=y
index 54cc3853d259de430f222e2a4f50d907201bd302..004cf52d1b7d81911e5e911a0dcee274be23b869 100644 (file)
@@ -108,16 +108,11 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_TASK_IOCTL=y
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_AMD74XX=y
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_AMD=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index 61a4460d67d32b2c7d8d266f40c316c70aef5e7c..5afb4840aec75c3d41fb7a4fd08b8322d0437904 100644 (file)
@@ -241,14 +241,11 @@ 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_RAID_ATTRS=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
@@ -265,6 +262,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_ATA=y
 CONFIG_ATA_PIIX=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index d41742dd26c8131279bc6a898461a043a78335ec..98f13879bb8fda832e3e73355f96af7defdcbc23 100644 (file)
@@ -248,17 +248,12 @@ 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_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
@@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index a7806e83ea0f1502cf0f78ceb5b0f29a86a07ee4..3b5d5913f548cddaf65f457da86ae245dee9f06d 100644 (file)
@@ -248,17 +248,12 @@ 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_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
@@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index 4bce1f8ebe98294ad339bb6715bbf2e342088ffc..7f50dd67aa8d979e7e3515b2ff8537058c8ed0f0 100644 (file)
@@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 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_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index fb042ce86b4bc1da95d3b9297e6dfe88ed2f5dad..a9d433a17fcf60dd3e434d993958f633effd9df5 100644 (file)
@@ -81,15 +81,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 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_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index c83338a39917e17bd7cf1edd3f2b126f8339ab0a..2774ef06450596f7582db13c7749ce7a3b76f510 100644 (file)
@@ -85,15 +85,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 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_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index 62344648eb7a31a0e134db2d7eaf828dd8a012aa..9bbd2218f0bf518ff1c2aeceaec8695317556664 100644 (file)
@@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 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_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index c388bff091482c9b871d80e86a27386e0fae1e9f..73221573275166e1ae7d044b1bad8dfa1b1f6d65 100644 (file)
@@ -244,17 +244,12 @@ 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_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
@@ -269,6 +264,13 @@ CONFIG_SCSI_AACRAID=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index 7a346605c498ae02e5a48245d03b1e028aacce96..a2c045fab6c58b38069db48b4d49dd9755a1789f 100644 (file)
@@ -27,9 +27,9 @@ CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_NETWORK_SECMARK=y
 CONFIG_CONNECTOR=m
 CONFIG_ATA_OVER_ETH=m
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
diff --git a/arch/mips/configs/xilfpga_defconfig b/arch/mips/configs/xilfpga_defconfig
new file mode 100644 (file)
index 0000000..ed1dce3
--- /dev/null
@@ -0,0 +1,40 @@
+CONFIG_MACH_XILFPGA=y
+# CONFIG_COMPACTION is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_BLOCK is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_UEVENT_HELPER is not set
+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_ALLOW_DEV_COREDUMP 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_VT_HW_CONSOLE_BINDING=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MIPS_PLATFORM_DEVICES is not set
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
index 37f84078e78abbe3f6b85841461c8bccc62d6c9a..940760844e2fe98a8e3958e975b1cbd674786675 100644 (file)
 
 #include <asm/signal.h>
 #include <asm/siginfo.h>
+#include <asm/vdso.h>
 
 struct mips_abi {
        int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
                                  struct pt_regs *regs, sigset_t *set);
-       const unsigned long     signal_return_offset;
        int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
                                     struct pt_regs *regs, sigset_t *set);
-       const unsigned long     rt_signal_return_offset;
        const unsigned long     restart;
 
        unsigned        off_sc_fpregs;
        unsigned        off_sc_fpc_csr;
        unsigned        off_sc_used_math;
+
+       struct mips_vdso_image *vdso;
 };
 
 #endif /* _ASM_ABI_H */
index 8c34484cea827f516591dd9f3c775d36e81fac7b..a00857b135c348eb104e8dae4dfdda4ccbe8563d 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _ASM_BCACHE_H
 #define _ASM_BCACHE_H
 
+#include <linux/types.h>
 
 /* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent,
    chipset implemented caches. On machines with other CPUs the CPU does the
@@ -18,6 +19,9 @@ struct bcache_ops {
        void (*bc_disable)(void);
        void (*bc_wback_inv)(unsigned long page, unsigned long size);
        void (*bc_inv)(unsigned long page, unsigned long size);
+       void (*bc_prefetch_enable)(void);
+       void (*bc_prefetch_disable)(void);
+       bool (*bc_prefetch_is_enabled)(void);
 };
 
 extern void indy_sc_init(void);
@@ -46,6 +50,26 @@ static inline void bc_inv(unsigned long page, unsigned long size)
        bcops->bc_inv(page, size);
 }
 
+static inline void bc_prefetch_enable(void)
+{
+       if (bcops->bc_prefetch_enable)
+               bcops->bc_prefetch_enable();
+}
+
+static inline void bc_prefetch_disable(void)
+{
+       if (bcops->bc_prefetch_disable)
+               bcops->bc_prefetch_disable();
+}
+
+static inline bool bc_prefetch_is_enabled(void)
+{
+       if (bcops->bc_prefetch_is_enabled)
+               return bcops->bc_prefetch_is_enabled();
+
+       return false;
+}
+
 #else /* !defined(CONFIG_BOARD_SCACHE) */
 
 /* Not R4000 / R4400 / R4600 / R5000.  */
@@ -54,6 +78,9 @@ static inline void bc_inv(unsigned long page, unsigned long size)
 #define bc_disable() do { } while (0)
 #define bc_wback_inv(page, size) do { } while (0)
 #define bc_inv(page, size) do { } while (0)
+#define bc_prefetch_enable() do { } while (0)
+#define bc_prefetch_disable() do { } while (0)
+#define bc_prefetch_is_enabled() 0
 
 #endif /* !defined(CONFIG_BOARD_SCACHE) */
 
diff --git a/arch/mips/include/asm/clocksource.h b/arch/mips/include/asm/clocksource.h
new file mode 100644 (file)
index 0000000..3deb1d0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_CLOCKSOURCE_H
+#define __ASM_CLOCKSOURCE_H
+
+#include <linux/types.h>
+
+/* VDSO clocksources. */
+#define VDSO_CLOCK_NONE                0       /* No suitable clocksource. */
+#define VDSO_CLOCK_R4K         1       /* Use the coprocessor 0 count. */
+#define VDSO_CLOCK_GIC         2       /* Use the GIC. */
+
+/**
+ * struct arch_clocksource_data - Architecture-specific clocksource information.
+ * @vdso_clock_mode: Method the VDSO should use to access the clocksource.
+ */
+struct arch_clocksource_data {
+       u8 vdso_clock_mode;
+};
+
+#endif /* __ASM_CLOCKSOURCE_H */
index c4bd54a7f5ce1675de61705a5b8779846e012589..a9580097cba8fe0d7db36793c8f8cf831323579e 100644 (file)
@@ -130,6 +130,8 @@ typedef union compat_sigval {
        compat_uptr_t   sival_ptr;
 } compat_sigval_t;
 
+/* Can't use the generic version because si_code and si_errno are swapped */
+
 #define SI_PAD_SIZE32  (128/sizeof(int) - 3)
 
 typedef struct compat_siginfo {
@@ -138,57 +140,61 @@ typedef struct compat_siginfo {
        int si_errno;
 
        union {
-               int _pad[SI_PAD_SIZE32];
+               int _pad[128 / sizeof(int) - 3];
 
                /* kill() */
                struct {
                        compat_pid_t _pid;      /* sender's pid */
-                       __compat_uid_t _uid;    /* sender's uid */
+                       __compat_uid32_t _uid;  /* sender's uid */
                } _kill;
 
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;    /* timer id */
+                       int _overrun;           /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       __compat_uid32_t _uid;  /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
                /* SIGCHLD */
                struct {
                        compat_pid_t _pid;      /* which child */
-                       __compat_uid_t _uid;    /* sender's uid */
+                       __compat_uid32_t _uid;  /* sender's uid */
                        int _status;            /* exit code */
                        compat_clock_t _utime;
                        compat_clock_t _stime;
                } _sigchld;
 
-               /* IRIX SIGCHLD */
-               struct {
-                       compat_pid_t _pid;      /* which child */
-                       compat_clock_t _utime;
-                       int _status;            /* exit code */
-                       compat_clock_t _stime;
-               } _irix_sigchld;
-
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
                struct {
-                       s32 _addr; /* faulting insn/memory ref. */
+                       compat_uptr_t _addr;    /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+                       int _trapno;    /* TRAP # which caused the signal */
+#endif
+                       short _addr_lsb; /* LSB of the reported address */
+                       struct {
+                               compat_uptr_t _lower;
+                               compat_uptr_t _upper;
+                       } _addr_bnd;
                } _sigfault;
 
-               /* SIGPOLL, SIGXFSZ (To do ...)  */
+               /* SIGPOLL */
                struct {
-                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
                        int _fd;
                } _sigpoll;
 
-               /* POSIX.1b timers */
-               struct {
-                       timer_t _tid;           /* timer id */
-                       int _overrun;           /* overrun count */
-                       compat_sigval_t _sigval;/* same as below */
-                       int _sys_private;       /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
                struct {
-                       compat_pid_t _pid;      /* sender's pid */
-                       __compat_uid_t _uid;    /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
+                       compat_uptr_t _call_addr; /* calling insn */
+                       int _syscall;   /* triggering system call number */
+                       compat_uint_t _arch;    /* AUDIT_ARCH_* of syscall */
+               } _sigsys;
        } _sifields;
 } compat_siginfo_t;
 
index fe67f12ac2393b23705b4a094bbf8c3b7cc77166..d1e04c943f5f7c7d9ec232851e14d9b5c4215496 100644 (file)
 #endif
 
 #ifndef cpu_has_rixi
-# ifdef CONFIG_64BIT
-# define cpu_has_rixi          (cpu_data[0].options & MIPS_CPU_RIXI)
-# else /* CONFIG_32BIT */
-# define cpu_has_rixi          ((cpu_data[0].options & MIPS_CPU_RIXI) && !cpu_has_64bits)
-# endif
+#define cpu_has_rixi           (cpu_data[0].options & MIPS_CPU_RIXI)
 #endif
 
 #ifndef cpu_has_mmips
diff --git a/arch/mips/include/asm/debug.h b/arch/mips/include/asm/debug.h
new file mode 100644 (file)
index 0000000..254f00d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ *
+ * 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.
+ */
+
+#ifndef __MIPS_ASM_DEBUG_H__
+#define __MIPS_ASM_DEBUG_H__
+
+#include <linux/dcache.h>
+
+/*
+ * mips_debugfs_dir corresponds to the "mips" directory at the top level
+ * of the DebugFS hierarchy. MIPS-specific DebugFS entires should be
+ * placed beneath this directory.
+ */
+extern struct dentry *mips_debugfs_dir;
+
+#endif /* __MIPS_ASM_DEBUG_H__ */
index 53b26933b12cea365457f95172fbde6990043ff1..b01a6ff468e00aab5d185a9dd53023101b34f2b7 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _ASM_ELF_H
 #define _ASM_ELF_H
 
+#include <linux/auxvec.h>
 #include <linux/fs.h>
 #include <uapi/linux/elf.h>
 
@@ -419,6 +420,12 @@ extern const char *__elf_platform;
 #define ELF_ET_DYN_BASE                (TASK_SIZE / 3 * 2)
 #endif
 
+#define ARCH_DLINFO                                                    \
+do {                                                                   \
+       NEW_AUX_ENT(AT_SYSINFO_EHDR,                                    \
+                   (unsigned long)current->mm->context.vdso);          \
+} while (0)
+
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
index f3e6978aad704c4a15bad1971c55625f2e378f6e..d0ef8b4892bbe6af327a0b351df93f948c413b37 100644 (file)
 
 #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;
@@ -38,7 +23,6 @@ extern int *_fw_envp;
 
 extern void fw_init_cmdline(void);
 extern char *fw_getcmdline(void);
-extern fw_memblock_t *fw_getmdesc(int);
 extern void fw_meminit(void);
 extern char *fw_getenv(char *name);
 extern unsigned long fw_getenvl(char *name);
index 1461c10c1c4c4e9a9c5c3e0ec1384b433e4f312c..71e4096a2145667328f9535d6c3ea93617881154 100644 (file)
@@ -48,11 +48,6 @@ extern enum bcm47xx_bus_type bcm47xx_bus_type;
 void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
                        bool fallback);
 
-#ifdef CONFIG_BCM47XX_SSB
-void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
-                               const char *prefix);
-#endif
-
 void bcm47xx_set_system_type(u16 chip_id);
 
 #endif /* __ASM_BCM47XX_H */
index 133336b493b67c4822e79a2965e93300adbab853..dd6005b75e0c0bb594e657ede11df74b21776852 100644 (file)
 #define SOC_ID_VRX268_2                0x00C /* v1.2 */
 #define SOC_ID_GRX288_2                0x00D /* v1.2 */
 #define SOC_ID_GRX282_2                0x00E /* v1.2 */
+#define SOC_ID_VRX220          0x000
+
+#define SOC_ID_ARX362          0x004
+#define SOC_ID_ARX368          0x005
+#define SOC_ID_ARX382          0x007
+#define SOC_ID_ARX388          0x008
+#define SOC_ID_URX388          0x009
+#define SOC_ID_GRX383          0x010
+#define SOC_ID_GRX369          0x011
+#define SOC_ID_GRX387          0x00F
+#define SOC_ID_GRX389          0x012
 
  /* SoC Types */
 #define SOC_TYPE_DANUBE                0x01
@@ -43,6 +54,9 @@
 #define SOC_TYPE_VR9           0x04 /* v1.1 */
 #define SOC_TYPE_VR9_2         0x05 /* v1.2 */
 #define SOC_TYPE_AMAZON_SE     0x06
+#define SOC_TYPE_AR10          0x07
+#define SOC_TYPE_GRX390                0x08
+#define SOC_TYPE_VRX220                0x09
 
 /* BOOT_SEL - find what boot media we have */
 #define BS_EXT_ROM             0x0
diff --git a/arch/mips/include/asm/mach-malta/malta-dtshim.h b/arch/mips/include/asm/mach-malta/malta-dtshim.h
new file mode 100644 (file)
index 0000000..cfd7776
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_MALTA_DTSHIM_H__
+#define __MIPS_MALTA_DTSHIM_H__
+
+#include <linux/init.h>
+
+#ifdef CONFIG_MIPS_MALTA
+
+extern void __init *malta_dt_shim(void *fdt);
+
+#else /* !CONFIG_MIPS_MALTA */
+
+static inline void *malta_dt_shim(void *fdt)
+{
+       return fdt;
+}
+
+#endif /* !CONFIG_MIPS_MALTA */
+
+#endif /* __MIPS_MALTA_DTSHIM_H__ */
index 1976fb815fd10c5275b0e04a1c008812fc847e6c..455d406e8ddf1667e4c2212aacfe985c2eb08be8 100644 (file)
 #ifndef _MT7620_REGS_H_
 #define _MT7620_REGS_H_
 
-enum mt762x_soc_type {
-       MT762X_SOC_UNKNOWN = 0,
-       MT762X_SOC_MT7620A,
-       MT762X_SOC_MT7620N,
-       MT762X_SOC_MT7628AN,
-};
-
 #define MT7620_SYSC_BASE               0x10000000
 
 #define SYSC_REG_CHIP_NAME0            0x00
 #define SYSC_REG_CHIP_NAME1            0x04
+#define SYSC_REG_EFUSE_CFG             0x08
 #define SYSC_REG_CHIP_REV              0x0c
 #define SYSC_REG_SYSTEM_CONFIG0                0x10
 #define SYSC_REG_SYSTEM_CONFIG1                0x14
index bd93014490df39eebce2df057d5b3e84f2130aeb..4c9fba68c8b2490bfaf98b2f1ec8b2fc77f0ed5f 100644 (file)
 #ifndef _RALINK_REGS_H_
 #define _RALINK_REGS_H_
 
+enum ralink_soc_type {
+       RALINK_UNKNOWN = 0,
+       RT2880_SOC,
+       RT3883_SOC,
+       RT305X_SOC_RT3050,
+       RT305X_SOC_RT3052,
+       RT305X_SOC_RT3350,
+       RT305X_SOC_RT3352,
+       RT305X_SOC_RT5350,
+       MT762X_SOC_MT7620A,
+       MT762X_SOC_MT7620N,
+       MT762X_SOC_MT7621AT,
+       MT762X_SOC_MT7628AN,
+       MT762X_SOC_MT7688,
+};
+extern enum ralink_soc_type ralink_soc;
+
 extern __iomem void *rt_sysc_membase;
 extern __iomem void *rt_memc_membase;
 
index 96f731bac79a4a9941f0fb5cc5198621f4ee7f9f..2eea79331a14bf040b164ce294e2ce3a0bb99ba7 100644 (file)
 #ifndef _RT305X_REGS_H_
 #define _RT305X_REGS_H_
 
-enum rt305x_soc_type {
-       RT305X_SOC_UNKNOWN = 0,
-       RT305X_SOC_RT3050,
-       RT305X_SOC_RT3052,
-       RT305X_SOC_RT3350,
-       RT305X_SOC_RT3352,
-       RT305X_SOC_RT5350,
-};
-
-extern enum rt305x_soc_type rt305x_soc;
+extern enum ralink_soc_type ralink_soc;
 
 static inline int soc_is_rt3050(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3050;
+       return ralink_soc == RT305X_SOC_RT3050;
 }
 
 static inline int soc_is_rt3052(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3052;
+       return ralink_soc == RT305X_SOC_RT3052;
 }
 
 static inline int soc_is_rt305x(void)
@@ -41,17 +32,17 @@ static inline int soc_is_rt305x(void)
 
 static inline int soc_is_rt3350(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3350;
+       return ralink_soc == RT305X_SOC_RT3350;
 }
 
 static inline int soc_is_rt3352(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3352;
+       return ralink_soc == RT305X_SOC_RT3352;
 }
 
 static inline int soc_is_rt5350(void)
 {
-       return rt305x_soc == RT305X_SOC_RT5350;
+       return ralink_soc == RT305X_SOC_RT5350;
 }
 
 #define RT305X_SYSC_BASE               0x10000000
diff --git a/arch/mips/include/asm/mach-xilfpga/irq.h b/arch/mips/include/asm/mach-xilfpga/irq.h
new file mode 100644 (file)
index 0000000..0132a5b
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_MACH_XILFPGA_IRQ_H__
+#define __MIPS_ASM_MACH_XILFPGA_IRQ_H__
+
+#define NR_IRQS 32
+
+#include_next <irq.h>
+
+#endif /* __MIPS_ASM_MACH_XILFPGA_IRQ_H__ */
index 1f1927ab42690b284257faa8991f4cff31a3264d..6516e9da51334916b04b6f8689a0857faad5f0ca 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef __MIPS_ASM_MIPS_CM_H__
 #define __MIPS_ASM_MIPS_CM_H__
 
+#include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/io.h>
 #include <linux/types.h>
@@ -36,12 +37,12 @@ extern phys_addr_t __mips_cm_phys_base(void);
 /*
  * mips_cm_is64 - determine CM register width
  *
- * The CM register width is processor and CM specific. A 64-bit processor
- * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
- * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
- * can be done either using regular 64-bit load/store instructions, or 32-bit
- * load/store instruction on 32-bit register pairs. We opt for using 64-bit
- * accesses on 64-bit CMs and kernels and 32-bit in any other case.
+ * The CM register width is determined by the version of the CM, with CM3
+ * introducing 64 bit GCRs and all prior CM versions having 32 bit GCRs.
+ * However we may run a kernel built for MIPS32 on a system with 64 bit GCRs,
+ * or vice-versa. This variable indicates the width of the memory accesses
+ * that the kernel will perform to GCRs, which may differ from the actual
+ * width of the GCRs.
  *
  * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
  */
@@ -125,7 +126,17 @@ static inline u32 read32_gcr_##name(void)                  \
                                                                \
 static inline u64 read64_gcr_##name(void)                      \
 {                                                              \
-       return __raw_readq(addr_gcr_##name());                  \
+       void __iomem *addr = addr_gcr_##name();                 \
+       u64 ret;                                                \
+                                                               \
+       if (mips_cm_is64) {                                     \
+               ret = __raw_readq(addr);                        \
+       } else {                                                \
+               ret = __raw_readl(addr);                        \
+               ret |= (u64)__raw_readl(addr + 0x4) << 32;      \
+       }                                                       \
+                                                               \
+       return ret;                                             \
 }                                                              \
                                                                \
 static inline unsigned long read_gcr_##name(void)              \
@@ -195,6 +206,8 @@ BUILD_CM_R_(gic_status,             MIPS_CM_GCB_OFS + 0xd0)
 BUILD_CM_R_(cpc_status,                MIPS_CM_GCB_OFS + 0xf0)
 BUILD_CM_RW(l2_config,         MIPS_CM_GCB_OFS + 0x130)
 BUILD_CM_RW(sys_config2,       MIPS_CM_GCB_OFS + 0x150)
+BUILD_CM_RW(l2_pft_control,    MIPS_CM_GCB_OFS + 0x300)
+BUILD_CM_RW(l2_pft_control_b,  MIPS_CM_GCB_OFS + 0x308)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,  0x00)
@@ -245,11 +258,14 @@ BUILD_CM_Cx_R_(tcid_8_priority,   0x80)
                 ((minor) << CM_GCR_REV_MINOR_SHF))
 
 #define CM_REV_CM2                             CM_ENCODE_REV(6, 0)
+#define CM_REV_CM2_5                           CM_ENCODE_REV(7, 0)
 #define CM_REV_CM3                             CM_ENCODE_REV(8, 0)
 
 /* GCR_ERROR_CAUSE register fields */
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF         27
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK         (_ULCAST_(0x1f) << 27)
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF                58
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_MSK                GENMASK_ULL(63, 58)
 #define CM_GCR_ERROR_CAUSE_ERRINFO_SHF         0
 #define CM_GCR_ERROR_CAUSE_ERRINGO_MSK         (_ULCAST_(0x7ffffff) << 0)
 
@@ -321,6 +337,20 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
 #define CM_GCR_SYS_CONFIG2_MAXVPW_SHF          0
 #define CM_GCR_SYS_CONFIG2_MAXVPW_MSK          (_ULCAST_(0xf) << 0)
 
+/* GCR_L2_PFT_CONTROL register fields */
+#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_SHF     12
+#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK     (_ULCAST_(0xfffff) << 12)
+#define CM_GCR_L2_PFT_CONTROL_PFTEN_SHF                8
+#define CM_GCR_L2_PFT_CONTROL_PFTEN_MSK                (_ULCAST_(0x1) << 8)
+#define CM_GCR_L2_PFT_CONTROL_NPFT_SHF         0
+#define CM_GCR_L2_PFT_CONTROL_NPFT_MSK         (_ULCAST_(0xff) << 0)
+
+/* GCR_L2_PFT_CONTROL_B register fields */
+#define CM_GCR_L2_PFT_CONTROL_B_CEN_SHF                8
+#define CM_GCR_L2_PFT_CONTROL_B_CEN_MSK                (_ULCAST_(0x1) << 8)
+#define CM_GCR_L2_PFT_CONTROL_B_PORTID_SHF     0
+#define CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK     (_ULCAST_(0xff) << 0)
+
 /* GCR_Cx_COHERENCE register fields */
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF    0
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK    (_ULCAST_(0xff) << 0)
@@ -329,11 +359,15 @@ BUILD_CM_Cx_R_(tcid_8_priority,   0x80)
 #define CM_GCR_Cx_CONFIG_IOCUTYPE_SHF          10
 #define CM_GCR_Cx_CONFIG_IOCUTYPE_MSK          (_ULCAST_(0x3) << 10)
 #define CM_GCR_Cx_CONFIG_PVPE_SHF              0
-#define CM_GCR_Cx_CONFIG_PVPE_MSK              (_ULCAST_(0x1ff) << 0)
+#define CM_GCR_Cx_CONFIG_PVPE_MSK              (_ULCAST_(0x3ff) << 0)
 
 /* GCR_Cx_OTHER register fields */
 #define CM_GCR_Cx_OTHER_CORENUM_SHF            16
 #define CM_GCR_Cx_OTHER_CORENUM_MSK            (_ULCAST_(0xffff) << 16)
+#define CM3_GCR_Cx_OTHER_CORE_SHF              8
+#define CM3_GCR_Cx_OTHER_CORE_MSK              (_ULCAST_(0x3f) << 8)
+#define CM3_GCR_Cx_OTHER_VP_SHF                        0
+#define CM3_GCR_Cx_OTHER_VP_MSK                        (_ULCAST_(0x7) << 0)
 
 /* GCR_Cx_RESET_BASE register fields */
 #define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_SHF    12
@@ -444,4 +478,32 @@ static inline unsigned int mips_cm_vp_id(unsigned int cpu)
        return (core * mips_cm_max_vp_width()) + vp;
 }
 
+#ifdef CONFIG_MIPS_CM
+
+/**
+ * mips_cm_lock_other - lock access to another core
+ * @core: the other core to be accessed
+ * @vp: the VP within the other core to be accessed
+ *
+ * Call before operating upon a core via the 'other' register region in
+ * order to prevent the region being moved during access. Must be followed
+ * by a call to mips_cm_unlock_other.
+ */
+extern void mips_cm_lock_other(unsigned int core, unsigned int vp);
+
+/**
+ * mips_cm_unlock_other - unlock access to another core
+ *
+ * Call after operating upon another core via the 'other' register region.
+ * Must be called after mips_cm_lock_other.
+ */
+extern void mips_cm_unlock_other(void);
+
+#else /* !CONFIG_MIPS_CM */
+
+static inline void mips_cm_lock_other(unsigned int core) { }
+static inline void mips_cm_unlock_other(void) { }
+
+#endif /* !CONFIG_MIPS_CM */
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
index f386f32702f17f75782ba9a58ffe5fa0ee37e186..e09035239e5383117947fcabe8920cdf8d7608f1 100644 (file)
@@ -149,7 +149,8 @@ BUILD_CPC_Cx_RW(other,              0x10)
  * core: the other core to be accessed
  *
  * Call before operating upon a core via the 'other' register region in
- * order to prevent the region being moved during access. Must be followed
+ * order to prevent the region being moved during access. Must be called
+ * within the bounds of a mips_cm_{lock,unlock}_other pair, and followed
  * by a call to mips_cpc_unlock_other.
  */
 extern void mips_cpc_lock_other(unsigned int core);
index c64781cf649f86b4ca4eec0fee38ba4c4da523e7..e43aca183c9918d4138f000c4a385659f8523eae 100644 (file)
@@ -50,7 +50,9 @@
 #define CP0_PAGEMASK $5
 #define CP0_WIRED $6
 #define CP0_INFO $7
+#define CP0_HWRENA $7, 0
 #define CP0_BADVADDR $8
+#define CP0_BADINSTR $8, 1
 #define CP0_COUNT $9
 #define CP0_ENTRYHI $10
 #define CP0_COMPARE $11
 #define CP0_CAUSE $13
 #define CP0_EPC $14
 #define CP0_PRID $15
+#define CP0_EBASE $15, 1
+#define CP0_CMGCRBASE $15, 3
 #define CP0_CONFIG $16
+#define CP0_CONFIG3 $16, 3
+#define CP0_CONFIG5 $16, 5
 #define CP0_LLADDR $17
 #define CP0_WATCHLO $18
 #define CP0_WATCHHI $19
 #define R3K_ENTRYLO_N          (_ULCAST_(1) << 11)
 
 /* MIPS32/64 EntryLo bit definitions */
-#ifdef CONFIG_64BIT
-/* as read by dmfc0 */
-#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 62)
-#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 63)
-#else
-/* as read by mfc0 */
-#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 30)
-#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 31)
-#endif
+#define MIPS_ENTRYLO_PFN_SHIFT 6
+#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << (BITS_PER_LONG - 2))
+#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << (BITS_PER_LONG - 1))
 
 /*
  * Values for PageMask register
index 89dd7fed1a570cf312e74b9216342fa6abbfdf22..ad1fccdb8d13ee3d14e97efe3831bd266ba65a4b 100644 (file)
@@ -33,7 +33,7 @@
 #define PAGE_SHIFT     16
 #endif
 #define PAGE_SIZE      (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK      (~((1 << PAGE_SHIFT) - 1))
+#define PAGE_MASK      (~(PAGE_SIZE - 1))
 
 /*
  * This is used for calculating the real page sizes
index 59ee6dcf6eed9fd2b336347b0d674070baf9f298..3f832c3dd8f5f1cad76461b47ee00a0b7f85722d 100644 (file)
@@ -36,12 +36,6 @@ extern unsigned int vced_count, vcei_count;
  */
 #define HAVE_ARCH_PICK_MMAP_LAYOUT 1
 
-/*
- * A special page (the vdso) is mapped into all processes at the very
- * top of the virtual memory space.
- */
-#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 */
@@ -80,7 +74,7 @@ extern unsigned int vced_count, vcei_count;
 
 #endif
 
-#define STACK_TOP      ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
+#define STACK_TOP      (TASK_SIZE & PAGE_MASK)
 
 /*
  * This decides where the kernel will search for a free chunk of vm
index cca56aa40ff4a1cd475457c16783bc71855f43c5..8f4ca5dd992b1e8ed28791488c1ebe8403f80d7c 100644 (file)
 /*
- * 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) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
  *
- * Copyright (C) 2009 Cavium Networks
+ * 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.
  */
 
 #ifndef __ASM_VDSO_H
 #define __ASM_VDSO_H
 
-#include <linux/types.h>
+#include <linux/mm_types.h>
 
+#include <asm/barrier.h>
 
-#ifdef CONFIG_32BIT
-struct mips_vdso {
-       u32 signal_trampoline[2];
-       u32 rt_signal_trampoline[2];
+/**
+ * struct mips_vdso_image - Details of a VDSO image.
+ * @data: Pointer to VDSO image data (page-aligned).
+ * @size: Size of the VDSO image data (page-aligned).
+ * @off_sigreturn: Offset of the sigreturn() trampoline.
+ * @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline.
+ * @mapping: Special mapping structure.
+ *
+ * This structure contains details of a VDSO image, including the image data
+ * and offsets of certain symbols required by the kernel. It is generated as
+ * part of the VDSO build process, aside from the mapping page array, which is
+ * populated at runtime.
+ */
+struct mips_vdso_image {
+       void *data;
+       unsigned long size;
+
+       unsigned long off_sigreturn;
+       unsigned long off_rt_sigreturn;
+
+       struct vm_special_mapping mapping;
 };
-#else  /* !CONFIG_32BIT */
-struct mips_vdso {
-       u32 o32_signal_trampoline[2];
-       u32 o32_rt_signal_trampoline[2];
-       u32 rt_signal_trampoline[2];
-       u32 n32_rt_signal_trampoline[2];
+
+/*
+ * The following structures are auto-generated as part of the build for each
+ * ABI by genvdso, see arch/mips/vdso/Makefile.
+ */
+
+extern struct mips_vdso_image vdso_image;
+
+#ifdef CONFIG_MIPS32_O32
+extern struct mips_vdso_image vdso_image_o32;
+#endif
+
+#ifdef CONFIG_MIPS32_N32
+extern struct mips_vdso_image vdso_image_n32;
+#endif
+
+/**
+ * union mips_vdso_data - Data provided by the kernel for the VDSO.
+ * @xtime_sec:         Current real time (seconds part).
+ * @xtime_nsec:                Current real time (nanoseconds part, shifted).
+ * @wall_to_mono_sec:  Wall-to-monotonic offset (seconds part).
+ * @wall_to_mono_nsec: Wall-to-monotonic offset (nanoseconds part).
+ * @seq_count:         Counter to synchronise updates (odd = updating).
+ * @cs_shift:          Clocksource shift value.
+ * @clock_mode:                Clocksource to use for time functions.
+ * @cs_mult:           Clocksource multiplier value.
+ * @cs_cycle_last:     Clock cycle value at last update.
+ * @cs_mask:           Clocksource mask value.
+ * @tz_minuteswest:    Minutes west of Greenwich (from timezone).
+ * @tz_dsttime:                Type of DST correction (from timezone).
+ *
+ * This structure contains data needed by functions within the VDSO. It is
+ * populated by the kernel and mapped read-only into user memory. The time
+ * fields are mirrors of internal data from the timekeeping infrastructure.
+ *
+ * Note: Care should be taken when modifying as the layout must remain the same
+ * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
+ */
+union mips_vdso_data {
+       struct {
+               u64 xtime_sec;
+               u64 xtime_nsec;
+               u32 wall_to_mono_sec;
+               u32 wall_to_mono_nsec;
+               u32 seq_count;
+               u32 cs_shift;
+               u8 clock_mode;
+               u32 cs_mult;
+               u64 cs_cycle_last;
+               u64 cs_mask;
+               s32 tz_minuteswest;
+               s32 tz_dsttime;
+       };
+
+       u8 page[PAGE_SIZE];
 };
-#endif /* CONFIG_32BIT */
+
+static inline u32 vdso_data_read_begin(const union mips_vdso_data *data)
+{
+       u32 seq;
+
+       while (true) {
+               seq = ACCESS_ONCE(data->seq_count);
+               if (likely(!(seq & 1))) {
+                       /* Paired with smp_wmb() in vdso_data_write_*(). */
+                       smp_rmb();
+                       return seq;
+               }
+
+               cpu_relax();
+       }
+}
+
+static inline bool vdso_data_read_retry(const union mips_vdso_data *data,
+                                       u32 start_seq)
+{
+       /* Paired with smp_wmb() in vdso_data_write_*(). */
+       smp_rmb();
+       return unlikely(data->seq_count != start_seq);
+}
+
+static inline void vdso_data_write_begin(union mips_vdso_data *data)
+{
+       ++data->seq_count;
+
+       /* Ensure sequence update is written before other data page values. */
+       smp_wmb();
+}
+
+static inline void vdso_data_write_end(union mips_vdso_data *data)
+{
+       /* Ensure data values are written before updating sequence again. */
+       smp_wmb();
+       ++data->seq_count;
+}
 
 #endif /* __ASM_VDSO_H */
index 96fe7395ed8dc8df6d2675bf31626b45133c15e4..f2cf4146114679253195769bab10b859f41026d6 100644 (file)
@@ -1,9 +1,9 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-generic-y += auxvec.h
 generic-y += ipcbuf.h
 
+header-y += auxvec.h
 header-y += bitfield.h
 header-y += bitsperlong.h
 header-y += break.h
diff --git a/arch/mips/include/uapi/asm/auxvec.h b/arch/mips/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..c9c7195
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* Location of VDSO image. */
+#define AT_SYSINFO_EHDR                33
+
+#endif /* __ASM_AUXVEC_H */
index 459cb017306c21eb63259b8cb0a406c65080cc8b..934b15b5b575f15b04fae0bf44065440773f7593 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/power_supply.h>
 #include <linux/power/jz4740-battery.h>
 #include <linux/power/gpio-charger.h>
+#include <linux/pwm.h>
 
 #include <asm/mach-jz4740/gpio.h>
 #include <asm/mach-jz4740/jz4740_fb.h>
@@ -34,8 +35,6 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 
-#include <linux/leds_pwm.h>
-
 #include <asm/mach-jz4740/platform.h>
 
 #include "clock.h"
@@ -399,13 +398,15 @@ static struct platform_device avt2_usb_regulator_device = {
        }
 };
 
+static struct pwm_lookup qi_lb60_pwm_lookup[] = {
+       PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0,
+                  PWM_POLARITY_NORMAL),
+};
+
 /* beeper */
 static struct platform_device qi_lb60_pwm_beeper = {
        .name = "pwm-beeper",
        .id = -1,
-       .dev = {
-               .platform_data = (void *)4,
-       },
 };
 
 /* charger */
@@ -491,6 +492,8 @@ static int __init qi_lb60_init_platform_devices(void)
                platform_device_register(&jz4740_usb_ohci_device);
        }
 
+       pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup));
+
        return platform_add_devices(jz_platform_devices,
                                        ARRAY_SIZE(jz_platform_devices));
 
index d982be1ea1c3f3125da9762f3e1b203ae939b1d0..68e2b7db9348f1d168666411544a90bd080d0ae0 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_MIPS_MT_FPAFF)   += mips-mt-fpaff.o
 obj-$(CONFIG_MIPS_MT_SMP)      += smp-mt.o
 obj-$(CONFIG_MIPS_CMP)         += smp-cmp.o
 obj-$(CONFIG_MIPS_CPS)         += smp-cps.o cps-vec.o
+obj-$(CONFIG_MIPS_CPS_NS16550) += cps-vec-ns16550.o
 obj-$(CONFIG_MIPS_GIC_IPI)     += smp-gic.o
 obj-$(CONFIG_MIPS_SPRAM)       += spram.o
 
diff --git a/arch/mips/kernel/cps-vec-ns16550.S b/arch/mips/kernel/cps-vec-ns16550.S
new file mode 100644 (file)
index 0000000..6d246ad
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <linux/serial_reg.h>
+
+#define UART_TX_OFS    (UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT)
+#define UART_LSR_OFS   (UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT)
+
+/**
+ * _mips_cps_putc() - write a character to the UART
+ * @a0: ASCII character to write
+ * @t9: UART base address
+ */
+LEAF(_mips_cps_putc)
+1:     lw              t0, UART_LSR_OFS(t9)
+       andi            t0, t0, UART_LSR_TEMT
+       beqz            t0, 1b
+       sb              a0, UART_TX_OFS(t9)
+       jr              ra
+       END(_mips_cps_putc)
+
+/**
+ * _mips_cps_puts() - write a string to the UART
+ * @a0: pointer to NULL-terminated ASCII string
+ * @t9: UART base address
+ *
+ * Write a null-terminated ASCII string to the UART.
+ */
+NESTED(_mips_cps_puts, 0, ra)
+       move            s7, ra
+       move            s6, a0
+
+1:     lb              a0, 0(s6)
+       beqz            a0, 2f
+       jal             _mips_cps_putc
+       PTR_ADDIU       s6, s6, 1
+       b               1b
+
+2:     jr              s7
+       END(_mips_cps_puts)
+
+/**
+ * _mips_cps_putx4 - write a 4b hex value to the UART
+ * @a0: the 4b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a single hexadecimal character to the UART.
+ */
+NESTED(_mips_cps_putx4, 0, ra)
+       andi            a0, a0, 0xf
+       li              t0, '0'
+       blt             a0, 10, 1f
+       li              t0, 'a'
+       addiu           a0, a0, -10
+1:     addu            a0, a0, t0
+       b               _mips_cps_putc
+       END(_mips_cps_putx4)
+
+/**
+ * _mips_cps_putx8 - write an 8b hex value to the UART
+ * @a0: the 8b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx8, 0, ra)
+       move            s3, ra
+       move            s2, a0
+       srl             a0, a0, 4
+       jal             _mips_cps_putx4
+       move            a0, s2
+       move            ra, s3
+       b               _mips_cps_putx4
+       END(_mips_cps_putx8)
+
+/**
+ * _mips_cps_putx16 - write a 16b hex value to the UART
+ * @a0: the 16b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx16, 0, ra)
+       move            s5, ra
+       move            s4, a0
+       srl             a0, a0, 8
+       jal             _mips_cps_putx8
+       move            a0, s4
+       move            ra, s5
+       b               _mips_cps_putx8
+       END(_mips_cps_putx16)
+
+/**
+ * _mips_cps_putx32 - write a 32b hex value to the UART
+ * @a0: the 32b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx32, 0, ra)
+       move            s7, ra
+       move            s6, a0
+       srl             a0, a0, 16
+       jal             _mips_cps_putx16
+       move            a0, s6
+       move            ra, s7
+       b               _mips_cps_putx16
+       END(_mips_cps_putx32)
+
+#ifdef CONFIG_64BIT
+
+/**
+ * _mips_cps_putx64 - write a 64b hex value to the UART
+ * @a0: the 64b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx64, 0, ra)
+       move            sp, ra
+       move            s8, a0
+       dsrl32          a0, a0, 0
+       jal             _mips_cps_putx32
+       move            a0, s8
+       move            ra, sp
+       b               _mips_cps_putx32
+       END(_mips_cps_putx64)
+
+#define _mips_cps_putxlong _mips_cps_putx64
+
+#else /* !CONFIG_64BIT */
+
+#define _mips_cps_putxlong _mips_cps_putx32
+
+#endif /* !CONFIG_64BIT */
+
+/**
+ * mips_cps_bev_dump() - dump relevant exception state to UART
+ * @a0: pointer to NULL-terminated ASCII string naming the exception
+ *
+ * Write information that may be useful in debugging an exception to the
+ * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception
+ * will only be run if something goes horribly wrong very early during
+ * the bringup of a core and it is very likely to be unsafe to perform
+ * memory accesses at that point (cache state indeterminate, EVA may not
+ * be configured, coherence may be disabled) let alone have a stack,
+ * this is all written in assembly using only registers & unmapped
+ * uncached access to the UART registers.
+ */
+LEAF(mips_cps_bev_dump)
+       move            s0, ra
+       move            s1, a0
+
+       li              t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)
+
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+       PTR_LA          a0, str_bev
+       jal             _mips_cps_puts
+       move            a0, s1
+       jal             _mips_cps_puts
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+
+#define DUMP_COP0_REG(reg, name, sz, _mfc0)            \
+       PTR_LA          a0, 8f;                         \
+       jal             _mips_cps_puts;                 \
+       _mfc0           a0, reg;                        \
+       jal             _mips_cps_putx##sz;             \
+       PTR_LA          a0, str_newline;                \
+       jal             _mips_cps_puts;                 \
+       TEXT(name)
+
+       DUMP_COP0_REG(CP0_CAUSE,    "Cause:    0x", 32, mfc0)
+       DUMP_COP0_REG(CP0_STATUS,   "Status:   0x", 32, mfc0)
+       DUMP_COP0_REG(CP0_EBASE,    "EBase:    0x", long, MFC0)
+       DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)
+       DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)
+
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+       jr              s0
+       END(mips_cps_bev_dump)
+
+.pushsection   .data
+str_bev: .asciiz "BEV Exception: "
+str_newline: .asciiz "\r\n"
+.popsection
index 209ded16806bf5a295ff202258f5b7ff42070940..8fd5a276cad23493f6500d0f4b01515ee20062f5 100644 (file)
 
 .set noreorder
 
+#ifdef CONFIG_64BIT
+# define STATUS_BITDEPS                ST0_KX
+#else
+# define STATUS_BITDEPS                0
+#endif
+
+#ifdef CONFIG_MIPS_CPS_NS16550
+
+#define DUMP_EXCEP(name)               \
+       PTR_LA  a0, 8f;                 \
+       jal     mips_cps_bev_dump;      \
+        nop;                           \
+       TEXT(name)
+
+#else /* !CONFIG_MIPS_CPS_NS16550 */
+
+#define DUMP_EXCEP(name)
+
+#endif /* !CONFIG_MIPS_CPS_NS16550 */
+
        /*
         * Set dest to non-zero if the core supports the MT ASE, else zero. If
         * MT is not supported then branch to nomt.
         */
        .macro  has_mt  dest, nomt
-       mfc0    \dest, CP0_CONFIG
-       bgez    \dest, \nomt
-        mfc0   \dest, CP0_CONFIG, 1
+       mfc0    \dest, CP0_CONFIG, 1
        bgez    \dest, \nomt
         mfc0   \dest, CP0_CONFIG, 2
        bgez    \dest, \nomt
 
 LEAF(mips_cps_core_entry)
        /*
-        * These first 12 bytes will be patched by cps_smp_setup to load the
-        * base address of the CM GCRs into register v1 and the CCA to use into
-        * register s0.
+        * These first 4 bytes will be patched by cps_smp_setup to load the
+        * CCA to use into register s0.
         */
-       .quad   0
        .word   0
 
        /* Check whether we're here due to an NMI */
@@ -71,7 +87,7 @@ not_nmi:
        mtc0    t0, CP0_CAUSE
 
        /* Setup Status */
-       li      t0, ST0_CU1 | ST0_CU0
+       li      t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
        mtc0    t0, CP0_STATUS
 
        /*
@@ -151,6 +167,12 @@ dcache_done:
        mtc0    t0, CP0_CONFIG
        ehb
 
+       /* Calculate an uncached address for the CM GCRs */
+       MFC0    v1, CP0_CMGCRBASE
+       PTR_SLL v1, v1, 4
+       PTR_LI  t0, UNCAC_BASE
+       PTR_ADDU v1, v1, t0
+
        /* Enter the coherent domain */
        li      t0, 0xff
        sw      t0, GCR_CL_COHERENCE_OFS(v1)
@@ -188,36 +210,42 @@ dcache_done:
 
 .org 0x200
 LEAF(excep_tlbfill)
+       DUMP_EXCEP("TLB Fill")
        b       .
         nop
        END(excep_tlbfill)
 
 .org 0x280
 LEAF(excep_xtlbfill)
+       DUMP_EXCEP("XTLB Fill")
        b       .
         nop
        END(excep_xtlbfill)
 
 .org 0x300
 LEAF(excep_cache)
+       DUMP_EXCEP("Cache")
        b       .
         nop
        END(excep_cache)
 
 .org 0x380
 LEAF(excep_genex)
+       DUMP_EXCEP("General")
        b       .
         nop
        END(excep_genex)
 
 .org 0x400
 LEAF(excep_intex)
+       DUMP_EXCEP("Interrupt")
        b       .
         nop
        END(excep_intex)
 
 .org 0x480
 LEAF(excep_ejtag)
+       DUMP_EXCEP("EJTAG")
        PTR_LA  k0, ejtag_debug_handler
        jr      k0
         nop
index 09a51d091941be3aa75ae37b53b386714a6d3db5..6b9064499bd3dfb49ef0c09ad3da48034dea0ff2 100644 (file)
@@ -536,8 +536,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
                c->options |= MIPS_CPU_SEGMENTS;
        if (config3 & MIPS_CONF3_MSA)
                c->ases |= MIPS_ASE_MSA;
-       /* Only tested on 32-bit cores */
-       if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT)) {
+       if (config3 & MIPS_CONF3_PW) {
                c->htw_seq = 0;
                c->options |= MIPS_CPU_HTW;
        }
index e5ed7ada14334c682218aa567e18414465fea81c..1f910563fdf60b3be0b4dcdca024837638818bf8 100644 (file)
@@ -28,6 +28,43 @@ static u64 notrace r4k_read_sched_clock(void)
        return read_c0_count();
 }
 
+static inline unsigned int rdhwr_count(void)
+{
+       unsigned int count;
+
+       __asm__ __volatile__(
+       "       .set push\n"
+       "       .set mips32r2\n"
+       "       rdhwr   %0, $2\n"
+       "       .set pop\n"
+       : "=r" (count));
+
+       return count;
+}
+
+static bool rdhwr_count_usable(void)
+{
+       unsigned int prev, curr, i;
+
+       /*
+        * Older QEMUs have a broken implementation of RDHWR for the CP0 count
+        * which always returns a constant value. Try to identify this and don't
+        * use it in the VDSO if it is broken. This workaround can be removed
+        * once the fix has been in QEMU stable for a reasonable amount of time.
+        */
+       for (i = 0, prev = rdhwr_count(); i < 100; i++) {
+               curr = rdhwr_count();
+
+               if (curr != prev)
+                       return true;
+
+               prev = curr;
+       }
+
+       pr_warn("Not using R4K clocksource in VDSO due to broken RDHWR\n");
+       return false;
+}
+
 int __init init_r4k_clocksource(void)
 {
        if (!cpu_has_counter || !mips_hpt_frequency)
@@ -36,6 +73,13 @@ int __init init_r4k_clocksource(void)
        /* Calculate a somewhat reasonable rating value */
        clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
 
+       /*
+        * R2 onwards makes the count accessible to user mode so it can be used
+        * by the VDSO (HWREna is configured by configure_hwrena()).
+        */
+       if (cpu_has_mips_r2_r6 && rdhwr_count_usable())
+               clocksource_mips.archdata.vdso_clock_mode = VDSO_CLOCK_R4K;
+
        clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
 
        sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
index d636c70fef19932ce557d32c5aa7b274026928ae..46794d64c0bfe3f9779cc43714cc7c3fbb6a10bc 100644 (file)
@@ -134,6 +134,16 @@ void __init check_wait(void)
                return;
        }
 
+       /*
+        * MIPSr6 specifies that masked interrupts should unblock an executing
+        * wait instruction, and thus that it is safe for us to use
+        * r4k_wait_irqoff. Yippee!
+        */
+       if (cpu_has_mips_r6) {
+               cpu_wait = r4k_wait_irqoff;
+               return;
+       }
+
        switch (current_cpu_type()) {
        case CPU_R3081:
        case CPU_R3081E:
@@ -155,6 +165,7 @@ void __init check_wait(void)
        case CPU_4KEC:
        case CPU_4KSC:
        case CPU_5KC:
+       case CPU_5KE:
        case CPU_25KF:
        case CPU_PR4450:
        case CPU_BMIPS3300:
@@ -197,7 +208,6 @@ void __init check_wait(void)
        case CPU_INTERAPTIV:
        case CPU_M5150:
        case CPU_QEMU_GENERIC:
-       case CPU_I6400:
                cpu_wait = r4k_wait;
                if (read_c0_config7() & MIPS_CONF7_WII)
                        cpu_wait = r4k_wait_irqoff;
index b8ceee576cdfce2e22e1b2d8ffab6f90bf69f6b8..1448c1f43d4e4ae6657b819a5c8ee238a7332e34 100644 (file)
@@ -9,6 +9,8 @@
  */
 
 #include <linux/errno.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
 
 #include <asm/mips-cm.h>
 #include <asm/mipsregs.h>
@@ -136,6 +138,9 @@ static char *cm3_causes[32] = {
        "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
 };
 
+static DEFINE_PER_CPU_ALIGNED(spinlock_t, cm_core_lock);
+static DEFINE_PER_CPU_ALIGNED(unsigned long, cm_core_lock_flags);
+
 phys_addr_t __mips_cm_phys_base(void)
 {
        u32 config3 = read_c0_config3();
@@ -200,6 +205,7 @@ int mips_cm_probe(void)
 {
        phys_addr_t addr;
        u32 base_reg;
+       unsigned cpu;
 
        /*
         * No need to probe again if we have already been
@@ -247,38 +253,70 @@ int mips_cm_probe(void)
        /* determine register width for this CM */
        mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
 
+       for_each_possible_cpu(cpu)
+               spin_lock_init(&per_cpu(cm_core_lock, cpu));
+
        return 0;
 }
 
-void mips_cm_error_report(void)
+void mips_cm_lock_other(unsigned int core, unsigned int vp)
 {
-       unsigned long revision = mips_cm_revision();
+       unsigned curr_core;
+       u32 val;
+
+       preempt_disable();
+       curr_core = current_cpu_data.core;
+       spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
+                         per_cpu(cm_core_lock_flags, curr_core));
+
+       if (mips_cm_revision() >= CM_REV_CM3) {
+               val = core << CM3_GCR_Cx_OTHER_CORE_SHF;
+               val |= vp << CM3_GCR_Cx_OTHER_VP_SHF;
+       } else {
+               BUG_ON(vp != 0);
+               val = core << CM_GCR_Cx_OTHER_CORENUM_SHF;
+       }
+
+       write_gcr_cl_other(val);
+
        /*
-        * CM3 has a 64-bit Error cause register with 0:57 containing the error
-        * info and 63:58 the error type. For old CMs, everything is contained
-        * in a single 32-bit register (0:26 and 31:27 respectively). Even
-        * though the cm_error is u64, we will simply ignore the upper word
-        * for CM2.
+        * Ensure the core-other region reflects the appropriate core &
+        * VP before any accesses to it occur.
         */
-       u64 cm_error = read_gcr_error_cause();
-       int cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
-                                ((revision >= CM_REV_CM3) ? 31 : 0);
-       unsigned long cm_addr = read_gcr_error_addr();
-       unsigned long cm_other = read_gcr_error_mult();
+       mb();
+}
+
+void mips_cm_unlock_other(void)
+{
+       unsigned curr_core = current_cpu_data.core;
+
+       spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core),
+                              per_cpu(cm_core_lock_flags, curr_core));
+       preempt_enable();
+}
+
+void mips_cm_error_report(void)
+{
+       u64 cm_error, cm_addr, cm_other;
+       unsigned long revision;
        int ocause, cause;
        char buf[256];
 
        if (!mips_cm_present())
                return;
 
-       cause = cm_error >> cm_error_cause_sft;
+       revision = mips_cm_revision();
 
-       if (!cause)
-               /* All good */
-               return;
-
-       ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
        if (revision < CM_REV_CM3) { /* CM2 */
+               cm_error = read_gcr_error_cause();
+               cm_addr = read_gcr_error_addr();
+               cm_other = read_gcr_error_mult();
+               cause = cm_error >> CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+               ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+
+               if (!cause)
+                       return;
+
                if (cause < 16) {
                        unsigned long cca_bits = (cm_error >> 15) & 7;
                        unsigned long tr_bits = (cm_error >> 12) & 7;
@@ -310,18 +348,30 @@ void mips_cm_error_report(void)
                }
                        pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error,
                               cm2_causes[cause], buf);
-               pr_err("CM_ADDR =%08lx\n", cm_addr);
-               pr_err("CM_OTHER=%08lx %s\n", cm_other, cm2_causes[ocause]);
+               pr_err("CM_ADDR =%08llx\n", cm_addr);
+               pr_err("CM_OTHER=%08llx %s\n", cm_other, cm2_causes[ocause]);
        } else { /* CM3 */
-       /* Used by cause == {1,2,3} */
-               unsigned long core_id_bits = (cm_error >> 22) & 0xf;
-               unsigned long vp_id_bits = (cm_error >> 18) & 0xf;
-               unsigned long cmd_bits = (cm_error >> 14) & 0xf;
-               unsigned long cmd_group_bits = (cm_error >> 11) & 0xf;
-               unsigned long cm3_cca_bits = (cm_error >> 8) & 7;
-               unsigned long mcp_bits = (cm_error >> 5) & 0xf;
-               unsigned long cm3_tr_bits = (cm_error >> 1) & 0xf;
-               unsigned long sched_bit = cm_error & 0x1;
+               ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits;
+               ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit;
+
+               cm_error = read64_gcr_error_cause();
+               cm_addr = read64_gcr_error_addr();
+               cm_other = read64_gcr_error_mult();
+               cause = cm_error >> CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+               ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+
+               if (!cause)
+                       return;
+
+               /* Used by cause == {1,2,3} */
+               core_id_bits = (cm_error >> 22) & 0xf;
+               vp_id_bits = (cm_error >> 18) & 0xf;
+               cmd_bits = (cm_error >> 14) & 0xf;
+               cmd_group_bits = (cm_error >> 11) & 0xf;
+               cm3_cca_bits = (cm_error >> 8) & 7;
+               mcp_bits = (cm_error >> 5) & 0xf;
+               cm3_tr_bits = (cm_error >> 1) & 0xf;
+               sched_bit = cm_error & 0x1;
 
                if (cause == 1 || cause == 3) { /* Tag ECC */
                        unsigned long tag_ecc = (cm_error >> 57) & 0x1;
@@ -363,12 +413,14 @@ void mips_cm_error_report(void)
                                 cm3_cmd_group[cmd_group_bits],
                                 cm3_cca_bits, 1 << mcp_bits,
                                 cm3_tr[cm3_tr_bits], sched_bit);
+               } else {
+                       buf[0] = 0;
                }
 
                pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
                       cm3_causes[cause], buf);
-               pr_err("CM_ADDR =%lx\n", cm_addr);
-               pr_err("CM_OTHER=%lx %s\n", cm_other, cm3_causes[ocause]);
+               pr_err("CM_ADDR =%llx\n", cm_addr);
+               pr_err("CM_OTHER=%llx %s\n", cm_other, cm3_causes[ocause]);
        }
 
        /* reprime cause register */
index 8af4d627b68b96d0d998ee7c4a06176af8234138..566b8d2c092c31de6293f245d81b12a899d40622 100644 (file)
@@ -76,6 +76,12 @@ void mips_cpc_lock_other(unsigned int core)
        spin_lock_irqsave(&per_cpu(cpc_core_lock, curr_core),
                          per_cpu(cpc_core_lock_flags, curr_core));
        write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF);
+
+       /*
+        * Ensure the core-other region reflects the appropriate core &
+        * VP before any accesses to it occur.
+        */
+       mb();
 }
 
 void mips_cpc_unlock_other(void)
index f2977f00911b303177fe086f72c0ae6be4a39313..1f5aac7f9ec3588ec3c48a563b057351b1abfe18 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/break.h>
+#include <asm/debug.h>
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
@@ -2363,7 +2364,6 @@ static const struct file_operations mipsr2_clear_fops = {
 
 static int __init mipsr2_init_debugfs(void)
 {
-       extern struct dentry    *mips_debugfs_dir;
        struct dentry           *mipsr2_emul;
 
        if (!mips_debugfs_dir)
index 076ead2a985948e145864a17a506b2ff3a93bc31..87bc74a5a518c5fca349104a6257a2ea6242710c 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <asm/cpu.h>
+#include <asm/debug.h>
 #include <asm/mipsregs.h>
 
 static void build_segment_config(char *str, unsigned int cfg)
@@ -91,7 +92,6 @@ static const struct file_operations segments_fops = {
 
 static int __init segments_info(void)
 {
-       extern struct dentry *mips_debugfs_dir;
        struct dentry *segments;
 
        if (cpu_has_segments) {
index 479515109e5badec96942ee594e3a450ab011f11..66aac55df3497f79d39f1b203601eccf3a25a48f 100644 (file)
 #include <asm/cache.h>
 #include <asm/cdmm.h>
 #include <asm/cpu.h>
+#include <asm/debug.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp-ops.h>
 #include <asm/prom.h>
 
+#ifdef CONFIG_MIPS_ELF_APPENDED_DTB
+const char __section(.appended_dtb) __appended_dtb[0x100000];
+#endif /* CONFIG_MIPS_ELF_APPENDED_DTB */
+
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
 EXPORT_SYMBOL(cpu_data);
@@ -616,6 +621,10 @@ static void __init request_crashkernel(struct resource *res)
 }
 #endif /* !defined(CONFIG_KEXEC)  */
 
+#define USE_PROM_CMDLINE       IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER)
+#define USE_DTB_CMDLINE                IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB)
+#define EXTEND_WITH_PROM       IS_ENABLED(CONFIG_MIPS_CMDLINE_EXTEND)
+
 static void __init arch_mem_init(char **cmdline_p)
 {
        struct memblock_region *reg;
@@ -640,18 +649,24 @@ static void __init arch_mem_init(char **cmdline_p)
        pr_info("Determined physical RAM map:\n");
        print_memory_map();
 
-#ifdef CONFIG_CMDLINE_BOOL
-#ifdef CONFIG_CMDLINE_OVERRIDE
+#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
        strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
 #else
+       if ((USE_PROM_CMDLINE && arcs_cmdline[0]) ||
+           (USE_DTB_CMDLINE && !boot_command_line[0]))
+               strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+
+       if (EXTEND_WITH_PROM && arcs_cmdline[0]) {
+               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+       }
+
+#if defined(CONFIG_CMDLINE_BOOL)
        if (builtin_cmdline[0]) {
-               strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
-               strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
        }
-       strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
 #endif
-#else
-       strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
 #endif
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 
index 2fec67bfc457cc969056f6f46258c0f00992be83..bf792e2839a6f31b5cde496cb84892ded60d5b5f 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/ucontext.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
-#include <asm/vdso.h>
 #include <asm/dsp.h>
 #include <asm/inst.h>
 #include <asm/msa.h>
@@ -752,16 +751,15 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
 struct mips_abi mips_abi = {
 #ifdef CONFIG_TRAD_SIGNALS
        .setup_frame    = setup_frame,
-       .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
 #endif
        .setup_rt_frame = setup_rt_frame,
-       .rt_signal_return_offset =
-               offsetof(struct mips_vdso, rt_signal_trampoline),
        .restart        = __NR_restart_syscall,
 
        .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
        .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
        .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
+
+       .vdso           = &vdso_image,
 };
 
 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
@@ -801,11 +799,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
        }
 
        if (sig_uses_siginfo(&ksig->ka))
-               ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
+               ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
                                          ksig, regs, oldset);
        else
-               ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
-                                      regs, oldset);
+               ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn,
+                                      ksig, regs, oldset);
 
        signal_setup_done(ret, ksig, 0);
 }
index f7e89524e3166fc23b0ea7ae08c10137d75de74e..4909639aa35ba7fcb3de868c4c28ca92e8f7a54e 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/ucontext.h>
 #include <asm/fpu.h>
 #include <asm/war.h>
-#include <asm/vdso.h>
 #include <asm/dsp.h>
 
 #include "signal-common.h"
@@ -406,14 +405,12 @@ static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
  */
 struct mips_abi mips_abi_32 = {
        .setup_frame    = setup_frame_32,
-       .signal_return_offset =
-               offsetof(struct mips_vdso, o32_signal_trampoline),
        .setup_rt_frame = setup_rt_frame_32,
-       .rt_signal_return_offset =
-               offsetof(struct mips_vdso, o32_rt_signal_trampoline),
        .restart        = __NR_O32_restart_syscall,
 
        .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
        .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
        .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
+
+       .vdso           = &vdso_image_o32,
 };
index 0d017fdcaf07aa50c583e644f4dc1f21d9ab80ee..a7bc384305008ece50b78c9ff72364e54c7af2e5 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/fpu.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
-#include <asm/vdso.h>
 
 #include "signal-common.h"
 
@@ -151,11 +150,11 @@ static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
 
 struct mips_abi mips_abi_n32 = {
        .setup_rt_frame = setup_rt_frame_n32,
-       .rt_signal_return_offset =
-               offsetof(struct mips_vdso, n32_rt_signal_trampoline),
        .restart        = __NR_N32_restart_syscall,
 
        .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
        .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
        .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
+
+       .vdso           = &vdso_image_n32,
 };
index c88937745b4ea18c7faf699f936f00cd42f9372d..e04c8057b88238956efe64c519dfa3aac41e1ba9 100644 (file)
@@ -8,6 +8,7 @@
  * option) any later version.
  */
 
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/irqchip/mips-gic.h>
 #include <linux/sched.h>
@@ -37,8 +38,9 @@ static unsigned core_vpe_count(unsigned core)
        if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
                return 1;
 
-       write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+       mips_cm_lock_other(core, 0);
        cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK;
+       mips_cm_unlock_other();
        return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
 }
 
@@ -133,11 +135,9 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
        /*
         * Patch the start of mips_cps_core_entry to provide:
         *
-        * v1 = CM base address
         * s0 = kseg0 CCA
         */
        entry_code = (u32 *)&mips_cps_core_entry;
-       UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
        uasm_i_addiu(&entry_code, 16, 0, cca);
        blast_dcache_range((unsigned long)&mips_cps_core_entry,
                           (unsigned long)entry_code);
@@ -190,10 +190,11 @@ err_out:
 
 static void boot_core(unsigned core)
 {
-       u32 access;
+       u32 access, stat, seq_state;
+       unsigned timeout;
 
        /* Select the appropriate core */
-       write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+       mips_cm_lock_other(core, 0);
 
        /* Set its reset vector */
        write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
@@ -210,12 +211,36 @@ static void boot_core(unsigned core)
                /* Reset the core */
                mips_cpc_lock_other(core);
                write_cpc_co_cmd(CPC_Cx_CMD_RESET);
+
+               timeout = 100;
+               while (true) {
+                       stat = read_cpc_co_stat_conf();
+                       seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE_MSK;
+
+                       /* U6 == coherent execution, ie. the core is up */
+                       if (seq_state == CPC_Cx_STAT_CONF_SEQSTATE_U6)
+                               break;
+
+                       /* Delay a little while before we start warning */
+                       if (timeout) {
+                               timeout--;
+                               mdelay(10);
+                               continue;
+                       }
+
+                       pr_warn("Waiting for core %u to start... STAT_CONF=0x%x\n",
+                               core, stat);
+                       mdelay(1000);
+               }
+
                mips_cpc_unlock_other();
        } else {
                /* Take the core out of reset */
                write_gcr_co_reset_release(0);
        }
 
+       mips_cm_unlock_other();
+
        /* The core is now powered up */
        bitmap_set(core_power, core, 1);
 }
index 5f0ab5bcd01edc5e454a3d534a996f6ed03697de..9b63829cf929408f3f75054478d6d3e637ff0c99 100644 (file)
@@ -46,9 +46,11 @@ void gic_send_ipi_single(int cpu, unsigned int action)
 
        if (mips_cpc_present() && (core != current_cpu_data.core)) {
                while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+                       mips_cm_lock_other(core, 0);
                        mips_cpc_lock_other(core);
                        write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
                        mips_cpc_unlock_other();
+                       mips_cm_unlock_other();
                }
        }
 
index 39f7ab7b04269b6a22b3573fc3f2bc377605d088..f7d86955d1b80b43b4321e1314ea6ceede4224f4 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/debugfs.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
-
+#include <asm/debug.h>
 
 static int ss_get(void *data, u64 *val)
 {
@@ -115,8 +115,6 @@ static int multi_get(void *data, u64 *val)
 
 DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
 
-
-extern struct dentry *mips_debugfs_dir;
 static int __init spinlock_test(void)
 {
        struct dentry *d;
index 1ba775d24d38f890d4e29a2168b533870d7cfb8b..506021f62549d98c7bc8260b300c659fd0118834 100644 (file)
  * Save stack-backtrace addresses into a stack_trace buffer:
  */
 static void save_raw_context_stack(struct stack_trace *trace,
-       unsigned long reg29)
+       unsigned long reg29, int savesched)
 {
        unsigned long *sp = (unsigned long *)reg29;
        unsigned long addr;
 
        while (!kstack_end(sp)) {
                addr = *sp++;
-               if (__kernel_text_address(addr)) {
+               if (__kernel_text_address(addr) &&
+                   (savesched || !in_sched_functions(addr))) {
                        if (trace->skip > 0)
                                trace->skip--;
                        else
@@ -31,7 +32,7 @@ static void save_raw_context_stack(struct stack_trace *trace,
 }
 
 static void save_context_stack(struct stack_trace *trace,
-       struct task_struct *tsk, struct pt_regs *regs)
+       struct task_struct *tsk, struct pt_regs *regs, int savesched)
 {
        unsigned long sp = regs->regs[29];
 #ifdef CONFIG_KALLSYMS
@@ -43,20 +44,22 @@ static void save_context_stack(struct stack_trace *trace,
                        (unsigned long)task_stack_page(tsk);
                if (stack_page && sp >= stack_page &&
                    sp <= stack_page + THREAD_SIZE - 32)
-                       save_raw_context_stack(trace, sp);
+                       save_raw_context_stack(trace, sp, savesched);
                return;
        }
        do {
-               if (trace->skip > 0)
-                       trace->skip--;
-               else
-                       trace->entries[trace->nr_entries++] = pc;
-               if (trace->nr_entries >= trace->max_entries)
-                       break;
+               if (savesched || !in_sched_functions(pc)) {
+                       if (trace->skip > 0)
+                               trace->skip--;
+                       else
+                               trace->entries[trace->nr_entries++] = pc;
+                       if (trace->nr_entries >= trace->max_entries)
+                               break;
+               }
                pc = unwind_stack(tsk, &sp, pc, &ra);
        } while (pc);
 #else
-       save_raw_context_stack(trace, sp);
+       save_raw_context_stack(trace, sp, savesched);
 #endif
 }
 
@@ -82,6 +85,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
                regs->cp0_epc = tsk->thread.reg31;
        } else
                prepare_frametrace(regs);
-       save_context_stack(trace, tsk, regs);
+       save_context_stack(trace, tsk, regs, tsk == current);
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
index efcedd43780fbf4a34c71bb215a4932145d2cfc4..886cb1976e90f682dafac7a958043d68bc4b6473 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/irq.h>
 #include <linux/perf_event.h>
 
+#include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
 #include <asm/break.h>
@@ -2206,12 +2207,8 @@ void __init trap_init(void)
                ebase = (unsigned long)
                        __alloc_bootmem(size, 1 << fls(size), 0);
        } else {
-#ifdef CONFIG_KVM_GUEST
-#define KVM_GUEST_KSEG0     0x40000000
-        ebase = KVM_GUEST_KSEG0;
-#else
-        ebase = CKSEG0;
-#endif
+               ebase = CAC_BASE;
+
                if (cpu_has_mips_r2_r6)
                        ebase += (read_c0_ebase() & 0x3ffff000);
        }
index 990354dd6bdedb79d77d8ec4291e14e3836dcba3..490cea569d57d0088e50e241f3465c91f07bbcc7 100644 (file)
@@ -85,6 +85,7 @@
 #include <asm/branch.h>
 #include <asm/byteorder.h>
 #include <asm/cop2.h>
+#include <asm/debug.h>
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
@@ -2295,7 +2296,6 @@ sigbus:
 }
 
 #ifdef CONFIG_DEBUG_FS
-extern struct dentry *mips_debugfs_dir;
 static int __init debugfs_unaligned(void)
 {
        struct dentry *d;
index ed2a278722a9599e9edfaf501bda7f88b66690f7..975e99759bab9ec1ae6aa80a47fa2f97765efcc6 100644 (file)
 /*
- * 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) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
  *
- * Copyright (C) 2009, 2010 Cavium Networks, 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.
  */
 
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
 #include <linux/binfmts.h>
 #include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/unistd.h>
-#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
 
+#include <asm/abi.h>
 #include <asm/vdso.h>
-#include <asm/uasm.h>
-#include <asm/processor.h>
+
+/* Kernel-provided data used by the VDSO. */
+static union mips_vdso_data vdso_data __page_aligned_data;
 
 /*
- * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
+ * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as
+ * what we map and where within the area they are mapped is determined at
+ * runtime.
  */
-#define __NR_O32_sigreturn             4119
-#define __NR_O32_rt_sigreturn          4193
-#define __NR_N32_rt_sigreturn          6211
+static struct page *no_pages[] = { NULL };
+static struct vm_special_mapping vdso_vvar_mapping = {
+       .name = "[vvar]",
+       .pages = no_pages,
+};
 
-static struct page *vdso_page;
-
-static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
+static void __init init_vdso_image(struct mips_vdso_image *image)
 {
-       uasm_i_addiu(&tramp, 2, 0, sigreturn);  /* li v0, sigreturn */
-       uasm_i_syscall(&tramp, 0);
+       unsigned long num_pages, i;
+
+       BUG_ON(!PAGE_ALIGNED(image->data));
+       BUG_ON(!PAGE_ALIGNED(image->size));
+
+       num_pages = image->size / PAGE_SIZE;
+
+       for (i = 0; i < num_pages; i++) {
+               image->mapping.pages[i] =
+                       virt_to_page(image->data + (i * PAGE_SIZE));
+       }
 }
 
 static int __init init_vdso(void)
 {
-       struct mips_vdso *vdso;
-
-       vdso_page = alloc_page(GFP_KERNEL);
-       if (!vdso_page)
-               panic("Cannot allocate vdso");
-
-       vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
-       if (!vdso)
-               panic("Cannot map vdso");
-       clear_page(vdso);
-
-       install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
-#ifdef CONFIG_32BIT
-       install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
-#else
-       install_trampoline(vdso->n32_rt_signal_trampoline,
-                          __NR_N32_rt_sigreturn);
-       install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
-       install_trampoline(vdso->o32_rt_signal_trampoline,
-                          __NR_O32_rt_sigreturn);
+       init_vdso_image(&vdso_image);
+
+#ifdef CONFIG_MIPS32_O32
+       init_vdso_image(&vdso_image_o32);
 #endif
 
-       vunmap(vdso);
+#ifdef CONFIG_MIPS32_N32
+       init_vdso_image(&vdso_image_n32);
+#endif
 
        return 0;
 }
 subsys_initcall(init_vdso);
 
-static unsigned long vdso_addr(unsigned long start)
+void update_vsyscall(struct timekeeper *tk)
 {
-       unsigned long offset = 0UL;
-
-       if (current->flags & PF_RANDOMIZE) {
-               offset = get_random_int();
-               offset <<= PAGE_SHIFT;
-               if (TASK_IS_32BIT_ADDR)
-                       offset &= 0xfffffful;
-               else
-                       offset &= 0xffffffful;
+       vdso_data_write_begin(&vdso_data);
+
+       vdso_data.xtime_sec = tk->xtime_sec;
+       vdso_data.xtime_nsec = tk->tkr_mono.xtime_nsec;
+       vdso_data.wall_to_mono_sec = tk->wall_to_monotonic.tv_sec;
+       vdso_data.wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec;
+       vdso_data.cs_shift = tk->tkr_mono.shift;
+
+       vdso_data.clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode;
+       if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+               vdso_data.cs_mult = tk->tkr_mono.mult;
+               vdso_data.cs_cycle_last = tk->tkr_mono.cycle_last;
+               vdso_data.cs_mask = tk->tkr_mono.mask;
        }
 
-       return STACK_TOP + offset;
+       vdso_data_write_end(&vdso_data);
+}
+
+void update_vsyscall_tz(void)
+{
+       if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+               vdso_data.tz_minuteswest = sys_tz.tz_minuteswest;
+               vdso_data.tz_dsttime = sys_tz.tz_dsttime;
+       }
 }
 
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
-       int ret;
-       unsigned long addr;
+       struct mips_vdso_image *image = current->thread.abi->vdso;
        struct mm_struct *mm = current->mm;
+       unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr;
+       struct vm_area_struct *vma;
+       struct resource gic_res;
+       int ret;
 
        down_write(&mm->mmap_sem);
 
-       addr = vdso_addr(mm->start_stack);
+       /*
+        * Determine total area size. This includes the VDSO data itself, the
+        * data page, and the GIC user page if present. Always create a mapping
+        * for the GIC user area if the GIC is present regardless of whether it
+        * is the current clocksource, in case it comes into use later on. We
+        * only map a page even though the total area is 64K, as we only need
+        * the counter registers at the start.
+        */
+       gic_size = gic_present ? PAGE_SIZE : 0;
+       vvar_size = gic_size + PAGE_SIZE;
+       size = vvar_size + image->size;
+
+       base = get_unmapped_area(NULL, 0, size, 0, 0);
+       if (IS_ERR_VALUE(base)) {
+               ret = base;
+               goto out;
+       }
+
+       data_addr = base + gic_size;
+       vdso_addr = data_addr + PAGE_SIZE;
 
-       addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
-       if (IS_ERR_VALUE(addr)) {
-               ret = addr;
-               goto up_fail;
+       vma = _install_special_mapping(mm, base, vvar_size,
+                                      VM_READ | VM_MAYREAD,
+                                      &vdso_vvar_mapping);
+       if (IS_ERR(vma)) {
+               ret = PTR_ERR(vma);
+               goto out;
        }
 
-       ret = install_special_mapping(mm, addr, PAGE_SIZE,
-                                     VM_READ|VM_EXEC|
-                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-                                     &vdso_page);
+       /* Map GIC user page. */
+       if (gic_size) {
+               ret = gic_get_usm_range(&gic_res);
+               if (ret)
+                       goto out;
+
+               ret = io_remap_pfn_range(vma, base,
+                                        gic_res.start >> PAGE_SHIFT,
+                                        gic_size,
+                                        pgprot_noncached(PAGE_READONLY));
+               if (ret)
+                       goto out;
+       }
 
+       /* Map data page. */
+       ret = remap_pfn_range(vma, data_addr,
+                             virt_to_phys(&vdso_data) >> PAGE_SHIFT,
+                             PAGE_SIZE, PAGE_READONLY);
        if (ret)
-               goto up_fail;
+               goto out;
+
+       /* Map VDSO image. */
+       vma = _install_special_mapping(mm, vdso_addr, image->size,
+                                      VM_READ | VM_EXEC |
+                                      VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+                                      &image->mapping);
+       if (IS_ERR(vma)) {
+               ret = PTR_ERR(vma);
+               goto out;
+       }
 
-       mm->context.vdso = (void *)addr;
+       mm->context.vdso = (void *)vdso_addr;
+       ret = 0;
 
-up_fail:
+out:
        up_write(&mm->mmap_sem);
        return ret;
 }
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-       if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
-               return "[vdso]";
-       return NULL;
-}
index cce2fcb58881f48cc071230698c4da85a8350360..0a93e83cd01479a4abc952e2e41a853dbf4159b9 100644 (file)
@@ -139,6 +139,11 @@ SECTIONS
        __appended_dtb = .;
        /* leave space for appended DTB */
        . += 0x100000;
+#elif defined(CONFIG_MIPS_ELF_APPENDED_DTB)
+       .appended_dtb : AT(ADDR(.appended_dtb) - LOAD_OFFSET) {
+               *(.appended_dtb)
+               KEEP(*(.appended_dtb))
+       }
 #endif
        /*
         * Align to 64K in attempt to eliminate holes before the
index c567240386a0f10818b0e06433f4b33b1bf5e6dc..7bab3a4e8f7d90b541b457f4f66138899db6db8a 100644 (file)
 #define PT_HOST_USERLOCAL   PT_EPC
 
 #define CP0_DDATA_LO        $28,3
-#define CP0_CONFIG3         $16,3
-#define CP0_CONFIG5         $16,5
-#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? */
index 77e4bdb1fe8cae2145b0d9875f1d8b69e3fe5d10..7376ce817eda6c6d23a20f1d1c853c24ccd5eb27 100644 (file)
 #define CLOCK_240M     240000000
 #define CLOCK_250M     250000000
 #define CLOCK_266M     266666666
+#define CLOCK_288M     288888888
 #define CLOCK_300M     300000000
 #define CLOCK_333M     333333333
+#define CLOCK_360M     360000000
 #define CLOCK_393M     393215332
 #define CLOCK_400M     400000000
+#define CLOCK_432M     432000000
 #define CLOCK_450M     450000000
 #define CLOCK_500M     500000000
 #define CLOCK_600M     600000000
+#define CLOCK_666M     666666666
+#define CLOCK_720M     720000000
 
 /* clock out speeds */
 #define CLOCK_32_768K  32768
@@ -80,4 +85,12 @@ extern unsigned long ltq_vr9_cpu_hz(void);
 extern unsigned long ltq_vr9_fpi_hz(void);
 extern unsigned long ltq_vr9_pp32_hz(void);
 
+extern unsigned long ltq_ar10_cpu_hz(void);
+extern unsigned long ltq_ar10_fpi_hz(void);
+extern unsigned long ltq_ar10_pp32_hz(void);
+
+extern unsigned long ltq_grx390_cpu_hz(void);
+extern unsigned long ltq_grx390_fpi_hz(void);
+extern unsigned long ltq_grx390_pp32_hz(void);
+
 #endif
index 2c218c3bbca57be3d029cdb3320b712092bccd46..2e7f60c9fc5dfc9a56f3d5db2aed46fcbffc6002 100644 (file)
@@ -369,8 +369,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
                if (of_address_to_resource(node, i, &res))
                        panic("Failed to get icu memory range");
 
-               if (request_mem_region(res.start, resource_size(&res),
-                                       res.name) < 0)
+               if (!request_mem_region(res.start, resource_size(&res),
+                                       res.name))
                        pr_err("Failed to request icu memory");
 
                ltq_icu_membase[i] = ioremap_nocache(res.start,
@@ -449,8 +449,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
                if (ret != exin_avail)
                        panic("failed to load external irq resources");
 
-               if (request_mem_region(res.start, resource_size(&res),
-                                                       res.name) < 0)
+               if (!request_mem_region(res.start, resource_size(&res),
+                                                       res.name))
                        pr_err("Failed to request eiu memory");
 
                ltq_eiu_membase = ioremap_nocache(res.start,
index 0db099ecc01648cca11a69cddcaab31c8c0a099e..297bcaa6b5d32b346c25fc9414a1e4690094c092 100644 (file)
@@ -77,8 +77,6 @@ void __init plat_mem_setup(void)
         * parsed resulting in our memory appearing
         */
        __dt_setup_arch(__dtb_start);
-
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 }
 
 void __init device_tree_init(void)
index 8750dc0a1bf678c5bd8500260816d6070b949aca..07f6d5b0b65ee10ccca231e0abab24d08462332e 100644 (file)
@@ -4,6 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/io.h>
@@ -25,9 +26,9 @@ static unsigned int ram_clocks[] = {
 /* legacy xway clock */
 #define CGU_SYS                        0x10
 
-/* vr9 clock */
-#define CGU_SYS_VR9            0x0c
-#define CGU_IF_CLK_VR9         0x24
+/* vr9, ar10/grx390 clock */
+#define CGU_SYS_XRX            0x0c
+#define CGU_IF_CLK_AR10                0x24
 
 unsigned long ltq_danube_fpi_hz(void)
 {
@@ -87,8 +88,9 @@ unsigned long ltq_ar9_fpi_hz(void)
        unsigned long sys = ltq_ar9_sys_hz();
 
        if (ltq_cgu_r32(CGU_SYS) & BIT(0))
-               return sys;
-       return sys >> 1;
+               return sys / 3;
+       else
+               return sys / 2;
 }
 
 unsigned long ltq_ar9_cpu_hz(void)
@@ -104,7 +106,7 @@ unsigned long ltq_vr9_cpu_hz(void)
        unsigned int cpu_sel;
        unsigned long clk;
 
-       cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf;
+       cpu_sel = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0xf;
 
        switch (cpu_sel) {
        case 0:
@@ -145,7 +147,7 @@ unsigned long ltq_vr9_fpi_hz(void)
        unsigned long clk;
 
        cpu_clk = ltq_vr9_cpu_hz();
-       ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3;
+       ocp_sel = ltq_cgu_r32(CGU_SYS_XRX) & 0x3;
 
        switch (ocp_sel) {
        case 0:
@@ -174,15 +176,18 @@ unsigned long ltq_vr9_fpi_hz(void)
 
 unsigned long ltq_vr9_pp32_hz(void)
 {
-       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3;
+       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
        unsigned long clk;
 
        switch (clksys) {
+       case 0:
+               clk = CLOCK_500M;
+               break;
        case 1:
-               clk = CLOCK_450M;
+               clk = CLOCK_432M;
                break;
        case 2:
-               clk = CLOCK_300M;
+               clk = CLOCK_288M;
                break;
        default:
                clk = CLOCK_500M;
@@ -191,3 +196,158 @@ unsigned long ltq_vr9_pp32_hz(void)
 
        return clk;
 }
+
+unsigned long ltq_ar10_cpu_hz(void)
+{
+       unsigned int clksys;
+       int cpu_fs = (ltq_cgu_r32(CGU_SYS_XRX) >> 8) & 0x1;
+       int freq_div = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7;
+
+       switch (cpu_fs) {
+       case 0:
+               clksys = CLOCK_500M;
+               break;
+       case 1:
+               clksys = CLOCK_600M;
+               break;
+       default:
+               clksys = CLOCK_500M;
+               break;
+       }
+
+       switch (freq_div) {
+       case 0:
+               return clksys;
+       case 1:
+               return clksys >> 1;
+       case 2:
+               return clksys >> 2;
+       default:
+               return clksys;
+       }
+}
+
+unsigned long ltq_ar10_fpi_hz(void)
+{
+       int freq_fpi = (ltq_cgu_r32(CGU_IF_CLK_AR10) >> 25) & 0xf;
+
+       switch (freq_fpi) {
+       case 1:
+               return CLOCK_300M;
+       case 5:
+               return CLOCK_250M;
+       case 2:
+               return CLOCK_150M;
+       case 6:
+               return CLOCK_125M;
+
+       default:
+               return CLOCK_125M;
+       }
+}
+
+unsigned long ltq_ar10_pp32_hz(void)
+{
+       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
+       unsigned long clk;
+
+       switch (clksys) {
+       case 1:
+               clk = CLOCK_250M;
+               break;
+       case 4:
+               clk = CLOCK_400M;
+               break;
+       default:
+               clk = CLOCK_250M;
+               break;
+       }
+
+       return clk;
+}
+
+unsigned long ltq_grx390_cpu_hz(void)
+{
+       unsigned int clksys;
+       int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
+       int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7);
+
+       switch (cpu_fs) {
+       case 0:
+               clksys = CLOCK_600M;
+               break;
+       case 1:
+               clksys = CLOCK_666M;
+               break;
+       case 2:
+               clksys = CLOCK_720M;
+               break;
+       default:
+               clksys = CLOCK_600M;
+               break;
+       }
+
+       switch (freq_div) {
+       case 0:
+               return clksys;
+       case 1:
+               return clksys >> 1;
+       case 2:
+               return clksys >> 2;
+       default:
+               return clksys;
+       }
+}
+
+unsigned long ltq_grx390_fpi_hz(void)
+{
+       /* fpi clock is derived from ddr_clk */
+       unsigned int clksys;
+       int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
+       int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX)) & 0x7);
+       switch (cpu_fs) {
+       case 0:
+               clksys = CLOCK_600M;
+               break;
+       case 1:
+               clksys = CLOCK_666M;
+               break;
+       case 2:
+               clksys = CLOCK_720M;
+               break;
+       default:
+               clksys = CLOCK_600M;
+               break;
+       }
+
+       switch (freq_div) {
+       case 1:
+               return clksys >> 1;
+       case 2:
+               return clksys >> 2;
+       default:
+               return clksys >> 1;
+       }
+}
+
+unsigned long ltq_grx390_pp32_hz(void)
+{
+       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
+       unsigned long clk;
+
+       switch (clksys) {
+       case 1:
+               clk = CLOCK_250M;
+               break;
+       case 2:
+               clk = CLOCK_432M;
+               break;
+       case 4:
+               clk = CLOCK_400M;
+               break;
+       default:
+               clk = CLOCK_250M;
+               break;
+       }
+       return clk;
+}
index 248429ab2622bb7e404c204e08551ef57787ffaa..8f6e02f1e9650b99830a14bd160ddf12856a9ee1 100644 (file)
@@ -4,6 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/export.h>
 #define SOC_TWINPASS   "Twinpass"
 #define SOC_AMAZON_SE  "Amazon_SE"
 #define SOC_AR9                "AR9"
-#define SOC_GR9                "GR9"
-#define SOC_VR9                "VR9"
+#define SOC_GR9                "GRX200"
+#define SOC_VR9                "xRX200"
+#define SOC_VRX220     "xRX220"
+#define SOC_AR10       "xRX300"
+#define SOC_GRX390     "xRX330"
 
 #define COMP_DANUBE    "lantiq,danube"
 #define COMP_TWINPASS  "lantiq,twinpass"
@@ -28,6 +32,8 @@
 #define COMP_AR9       "lantiq,ar9"
 #define COMP_GR9       "lantiq,gr9"
 #define COMP_VR9       "lantiq,vr9"
+#define COMP_AR10      "lantiq,ar10"
+#define COMP_GRX390    "lantiq,grx390"
 
 #define PART_SHIFT     12
 #define PART_MASK      0x0FFFFFFF
@@ -101,6 +107,12 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
                i->compatible = COMP_VR9;
                break;
 
+       case SOC_ID_VRX220:
+               i->name = SOC_VRX220;
+               i->type = SOC_TYPE_VRX220;
+               i->compatible = COMP_VR9;
+               break;
+
        case SOC_ID_GRX282_2:
        case SOC_ID_GRX288_2:
                i->name = SOC_GR9;
@@ -108,6 +120,25 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
                i->compatible = COMP_GR9;
                break;
 
+       case SOC_ID_ARX362:
+       case SOC_ID_ARX368:
+       case SOC_ID_ARX382:
+       case SOC_ID_ARX388:
+       case SOC_ID_URX388:
+               i->name = SOC_AR10;
+               i->type = SOC_TYPE_AR10;
+               i->compatible = COMP_AR10;
+               break;
+
+       case SOC_ID_GRX383:
+       case SOC_ID_GRX369:
+       case SOC_ID_GRX387:
+       case SOC_ID_GRX389:
+               i->name = SOC_GRX390;
+               i->type = SOC_TYPE_GRX390;
+               i->compatible = COMP_GRX390;
+               break;
+
        default:
                unreachable();
                break;
index fe68f9ae47c1487afde62c2bddcf1d5a94ff758a..bc29bb349e94e227fc0b015544d588eddafe5a57 100644 (file)
@@ -4,6 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/init.h>
@@ -22,9 +23,6 @@
 
 #include "../prom.h"
 
-#define ltq_rcu_w32(x, y)      ltq_w32((x), ltq_rcu_membase + (y))
-#define ltq_rcu_r32(x)         ltq_r32(ltq_rcu_membase + (x))
-
 /* reset request register */
 #define RCU_RST_REQ            0x0010
 /* reset status register */
 /* vr9 gphy registers */
 #define RCU_GFS_ADD0_XRX200    0x0020
 #define RCU_GFS_ADD1_XRX200    0x0068
+/* xRX300 gphy registers */
+#define RCU_GFS_ADD0_XRX300    0x0020
+#define RCU_GFS_ADD1_XRX300    0x0058
+#define RCU_GFS_ADD2_XRX300    0x00AC
+/* xRX330 gphy registers */
+#define RCU_GFS_ADD0_XRX330    0x0020
+#define RCU_GFS_ADD1_XRX330    0x0058
+#define RCU_GFS_ADD2_XRX330    0x00AC
+#define RCU_GFS_ADD3_XRX330    0x0264
+
+/* xbar BE flag */
+#define RCU_AHB_ENDIAN          0x004C
+#define RCU_VR9_BE_AHB1S        0x00000008
 
 /* reboot bit */
 #define RCU_RD_GPHY0_XRX200    BIT(31)
 #define RCU_RD_SRST            BIT(30)
 #define RCU_RD_GPHY1_XRX200    BIT(29)
+/* xRX300 bits */
+#define RCU_RD_GPHY0_XRX300    BIT(31)
+#define RCU_RD_GPHY1_XRX300    BIT(29)
+#define RCU_RD_GPHY2_XRX300    BIT(28)
+/* xRX330 bits */
+#define RCU_RD_GPHY0_XRX330    BIT(31)
+#define RCU_RD_GPHY1_XRX330    BIT(29)
+#define RCU_RD_GPHY2_XRX330    BIT(28)
+#define RCU_RD_GPHY3_XRX330    BIT(10)
 
 /* reset cause */
 #define RCU_STAT_SHIFT         26
 #define RCU_BOOT_SEL(x)                ((x >> 18) & 0x7)
 #define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
 
+/* dwc2 USB configuration registers */
+#define RCU_USB1CFG            0x0018
+#define RCU_USB2CFG            0x0034
+
+/* USB DMA endianness bits */
+#define RCU_USBCFG_HDSEL_BIT   BIT(11)
+#define RCU_USBCFG_HOST_END_BIT        BIT(10)
+#define RCU_USBCFG_SLV_END_BIT BIT(9)
+
+/* USB reset bits */
+#define RCU_USBRESET           0x0010
+
+#define USBRESET_BIT           BIT(4)
+
+#define RCU_USBRESET2          0x0048
+
+#define USB1RESET_BIT          BIT(4)
+#define USB2RESET_BIT          BIT(5)
+
+#define RCU_CFG1A              0x0038
+#define RCU_CFG1B              0x003C
+
+/* USB PMU devices */
+#define PMU_AHBM               BIT(15)
+#define PMU_USB0               BIT(6)
+#define PMU_USB1               BIT(27)
+
+/* USB PHY PMU devices */
+#define PMU_USB0_P             BIT(0)
+#define PMU_USB1_P             BIT(26)
+
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
 static struct device_node *ltq_rcu_np;
+static DEFINE_SPINLOCK(ltq_rcu_lock);
+
+static void ltq_rcu_w32(uint32_t val, uint32_t reg_off)
+{
+       ltq_w32(val, ltq_rcu_membase + reg_off);
+}
+
+static uint32_t ltq_rcu_r32(uint32_t reg_off)
+{
+       return ltq_r32(ltq_rcu_membase + reg_off);
+}
+
+static void ltq_rcu_w32_mask(uint32_t clr, uint32_t set, uint32_t reg_off)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ltq_rcu_lock, flags);
+       ltq_rcu_w32((ltq_rcu_r32(reg_off) & ~(clr)) | (set), reg_off);
+       spin_unlock_irqrestore(&ltq_rcu_lock, flags);
+}
 
 /* This function is used by the watchdog driver */
 int ltq_reset_cause(void)
@@ -67,15 +138,40 @@ unsigned char ltq_boot_select(void)
        return RCU_BOOT_SEL(val);
 }
 
-/* reset / boot a gphy */
-static struct ltq_xrx200_gphy_reset {
+struct ltq_gphy_reset {
        u32 rd;
        u32 addr;
-} xrx200_gphy[] = {
+};
+
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx200_gphy[] = {
        {RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
        {RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
 };
 
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx300_gphy[] = {
+       {RCU_RD_GPHY0_XRX300, RCU_GFS_ADD0_XRX300},
+       {RCU_RD_GPHY1_XRX300, RCU_GFS_ADD1_XRX300},
+       {RCU_RD_GPHY2_XRX300, RCU_GFS_ADD2_XRX300},
+};
+
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx330_gphy[] = {
+       {RCU_RD_GPHY0_XRX330, RCU_GFS_ADD0_XRX330},
+       {RCU_RD_GPHY1_XRX330, RCU_GFS_ADD1_XRX330},
+       {RCU_RD_GPHY2_XRX330, RCU_GFS_ADD2_XRX330},
+       {RCU_RD_GPHY3_XRX330, RCU_GFS_ADD3_XRX330},
+};
+
+static void xrx200_gphy_boot_addr(struct ltq_gphy_reset *phy_regs,
+                                 dma_addr_t dev_addr)
+{
+       ltq_rcu_w32_mask(0, phy_regs->rd, RCU_RST_REQ);
+       ltq_rcu_w32(dev_addr, phy_regs->addr);
+       ltq_rcu_w32_mask(phy_regs->rd, 0,  RCU_RST_REQ);
+}
+
 /* reset and boot a gphy. these phys only exist on xrx200 SoC */
 int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
 {
@@ -86,23 +182,34 @@ int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
                return -EINVAL;
        }
 
-       clk = clk_get_sys("1f203000.rcu", "gphy");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       clk_enable(clk);
-
-       if (id > 1) {
-               dev_err(dev, "%u is an invalid gphy id\n", id);
-               return -EINVAL;
+       if (of_machine_is_compatible("lantiq,vr9")) {
+               clk = clk_get_sys("1f203000.rcu", "gphy");
+               if (IS_ERR(clk))
+                       return PTR_ERR(clk);
+               clk_enable(clk);
        }
+
        dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
 
-       ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
-                       RCU_RST_REQ);
-       ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
-       ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
-                       RCU_RST_REQ);
+       if (of_machine_is_compatible("lantiq,vr9")) {
+               if (id >= ARRAY_SIZE(xrx200_gphy)) {
+                       dev_err(dev, "%u is an invalid gphy id\n", id);
+                       return -EINVAL;
+               }
+               xrx200_gphy_boot_addr(&xrx200_gphy[id], dev_addr);
+       } else if (of_machine_is_compatible("lantiq,ar10")) {
+               if (id >= ARRAY_SIZE(xrx300_gphy)) {
+                       dev_err(dev, "%u is an invalid gphy id\n", id);
+                       return -EINVAL;
+               }
+               xrx200_gphy_boot_addr(&xrx300_gphy[id], dev_addr);
+       } else if (of_machine_is_compatible("lantiq,grx390")) {
+               if (id >= ARRAY_SIZE(xrx330_gphy)) {
+                       dev_err(dev, "%u is an invalid gphy id\n", id);
+                       return -EINVAL;
+               }
+               xrx200_gphy_boot_addr(&xrx330_gphy[id], dev_addr);
+       }
        return 0;
 }
 
@@ -200,6 +307,45 @@ static void ltq_machine_power_off(void)
        unreachable();
 }
 
+static void ltq_usb_init(void)
+{
+       /* Power for USB cores 1 & 2 */
+       ltq_pmu_enable(PMU_AHBM);
+       ltq_pmu_enable(PMU_USB0);
+       ltq_pmu_enable(PMU_USB1);
+
+       ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1A) | BIT(0), RCU_CFG1A);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1B) | BIT(0), RCU_CFG1B);
+
+       /* Enable USB PHY power for cores 1 & 2 */
+       ltq_pmu_enable(PMU_USB0_P);
+       ltq_pmu_enable(PMU_USB1_P);
+
+       /* Configure cores to host mode */
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT,
+               RCU_USB1CFG);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT,
+               RCU_USB2CFG);
+
+       /* Select DMA endianness (Host-endian: big-endian) */
+       ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT)
+               | RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG);
+       ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT)
+               | RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG);
+
+       /* Hard reset USB state machines */
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | USBRESET_BIT, RCU_USBRESET);
+       udelay(50 * 1000);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) & ~USBRESET_BIT, RCU_USBRESET);
+
+       /* Soft reset USB state machines */
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+               | USB1RESET_BIT | USB2RESET_BIT, RCU_USBRESET2);
+       udelay(50 * 1000);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+               & ~(USB1RESET_BIT | USB2RESET_BIT), RCU_USBRESET2);
+}
+
 static int __init mips_reboot_setup(void)
 {
        struct resource res;
@@ -216,13 +362,21 @@ static int __init mips_reboot_setup(void)
        if (of_address_to_resource(ltq_rcu_np, 0, &res))
                panic("Failed to get rcu memory range");
 
-       if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
+       if (!request_mem_region(res.start, resource_size(&res), res.name))
                pr_err("Failed to request rcu memory");
 
        ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
        if (!ltq_rcu_membase)
                panic("Failed to remap core memory");
 
+       if (of_machine_is_compatible("lantiq,ar9") ||
+           of_machine_is_compatible("lantiq,vr9"))
+               ltq_usb_init();
+
+       if (of_machine_is_compatible("lantiq,vr9"))
+               ltq_rcu_w32(ltq_rcu_r32(RCU_AHB_ENDIAN) | RCU_VR9_BE_AHB1S,
+                           RCU_AHB_ENDIAN);
+
        _machine_restart = ltq_machine_restart;
        _machine_halt = ltq_machine_halt;
        pm_power_off = ltq_machine_power_off;
index 2b15491de49462e27e71df6758a49efbd4b29ef4..80554e8f603758f78352b8eb3a8fa4d20df9af7f 100644 (file)
@@ -4,11 +4,13 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/ioport.h>
 #include <linux/export.h>
 #include <linux/clkdev.h>
+#include <linux/spinlock.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include "../clk.h"
 #include "../prom.h"
 
-/* clock control register */
+/* clock control register for legacy */
 #define CGU_IFCCR      0x0018
 #define CGU_IFCCR_VR9  0x0024
-/* system clock register */
+/* system clock register for legacy */
 #define CGU_SYS                0x0010
 /* pci control register */
 #define CGU_PCICR      0x0034
 #define CGU_PCICR_VR9  0x0038
 /* ephy configuration register */
 #define CGU_EPHY       0x10
+
+/* Legacy PMU register for ar9, ase, danube */
 /* power control register */
 #define PMU_PWDCR      0x1C
 /* power status register */
 /* power status register */
 #define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR))
 
+
+/* PMU register for ar10 and grx390 */
+
+/* First register set */
+#define PMU_CLK_SR     0x20 /* status */
+#define PMU_CLK_CR_A   0x24 /* Enable */
+#define PMU_CLK_CR_B   0x28 /* Disable */
+/* Second register set */
+#define PMU_CLK_SR1    0x30 /* status */
+#define PMU_CLK_CR1_A  0x34 /* Enable */
+#define PMU_CLK_CR1_B  0x38 /* Disable */
+/* Third register set */
+#define PMU_ANA_SR     0x40 /* status */
+#define PMU_ANA_CR_A   0x44 /* Enable */
+#define PMU_ANA_CR_B   0x48 /* Disable */
+
+/* Status */
+static u32 pmu_clk_sr[] = {
+       PMU_CLK_SR,
+       PMU_CLK_SR1,
+       PMU_ANA_SR,
+};
+
+/* Enable */
+static u32 pmu_clk_cr_a[] = {
+       PMU_CLK_CR_A,
+       PMU_CLK_CR1_A,
+       PMU_ANA_CR_A,
+};
+
+/* Disable */
+static u32 pmu_clk_cr_b[] = {
+       PMU_CLK_CR_B,
+       PMU_CLK_CR1_B,
+       PMU_ANA_CR_B,
+};
+
+#define PWDCR_EN_XRX(x)                (pmu_clk_cr_a[(x)])
+#define PWDCR_DIS_XRX(x)       (pmu_clk_cr_b[(x)])
+#define PWDSR_XRX(x)           (pmu_clk_sr[(x)])
+
 /* clock gates that we can en/disable */
 #define PMU_USB0_P     BIT(0)
+#define PMU_ASE_SDIO   BIT(2) /* ASE special */
 #define PMU_PCI                BIT(4)
 #define PMU_DMA                BIT(5)
 #define PMU_USB0       BIT(6)
 #define PMU_ASC0       BIT(7)
 #define PMU_EPHY       BIT(7)  /* ase */
+#define PMU_USIF       BIT(7) /* from vr9 until grx390 */
 #define PMU_SPI                BIT(8)
 #define PMU_DFE                BIT(9)
 #define PMU_EBU                BIT(10)
 #define PMU_AHBS       BIT(13) /* vr9 */
 #define PMU_FPI                BIT(14)
 #define PMU_AHBM       BIT(15)
+#define PMU_SDIO       BIT(16) /* danube, ar9, vr9 */
 #define PMU_ASC1       BIT(17)
 #define PMU_PPE_QSB    BIT(18)
 #define PMU_PPE_SLL01  BIT(19)
+#define PMU_DEU                BIT(20)
 #define PMU_PPE_TC     BIT(21)
 #define PMU_PPE_EMA    BIT(22)
 #define PMU_PPE_DPLUM  BIT(23)
+#define PMU_PPE_DP     BIT(23)
 #define PMU_PPE_DPLUS  BIT(24)
 #define PMU_USB1_P     BIT(26)
 #define PMU_USB1       BIT(27)
 #define PMU_GPHY       BIT(30)
 #define PMU_PCIE_CLK   BIT(31)
 
-#define PMU1_PCIE_PHY  BIT(0)
+#define PMU1_PCIE_PHY  BIT(0)  /* vr9-specific,moved in ar10/grx390 */
 #define PMU1_PCIE_CTL  BIT(1)
 #define PMU1_PCIE_PDI  BIT(4)
 #define PMU1_PCIE_MSI  BIT(5)
+#define PMU1_CKE       BIT(6)
+#define PMU1_PCIE1_CTL BIT(17)
+#define PMU1_PCIE1_PDI BIT(20)
+#define PMU1_PCIE1_MSI BIT(21)
+#define PMU1_PCIE2_CTL BIT(25)
+#define PMU1_PCIE2_PDI BIT(26)
+#define PMU1_PCIE2_MSI BIT(27)
+
+#define PMU_ANALOG_USB0_P      BIT(0)
+#define PMU_ANALOG_USB1_P      BIT(1)
+#define PMU_ANALOG_PCIE0_P     BIT(8)
+#define PMU_ANALOG_PCIE1_P     BIT(9)
+#define PMU_ANALOG_PCIE2_P     BIT(10)
+#define PMU_ANALOG_DSL_AFE     BIT(16)
+#define PMU_ANALOG_DCDC_2V5    BIT(17)
+#define PMU_ANALOG_DCDC_1VX    BIT(18)
+#define PMU_ANALOG_DCDC_1V0    BIT(19)
 
 #define pmu_w32(x, y)  ltq_w32((x), pmu_membase + (y))
 #define pmu_r32(x)     ltq_r32(pmu_membase + (x))
 
+#define XBAR_ALWAYS_LAST       0x430
+#define XBAR_FPI_BURST_EN      BIT(1)
+#define XBAR_AHB_BURST_EN      BIT(2)
+
+#define xbar_w32(x, y) ltq_w32((x), ltq_xbar_membase + (y))
+#define xbar_r32(x)    ltq_r32(ltq_xbar_membase + (x))
+
 static void __iomem *pmu_membase;
+static void __iomem *ltq_xbar_membase;
 void __iomem *ltq_cgu_membase;
 void __iomem *ltq_ebu_membase;
 
 static u32 ifccr = CGU_IFCCR;
 static u32 pcicr = CGU_PCICR;
 
+static DEFINE_SPINLOCK(g_pmu_lock);
+
 /* legacy function kept alive to ease clkdev transition */
 void ltq_pmu_enable(unsigned int module)
 {
-       int err = 1000000;
+       int retry = 1000000;
 
+       spin_lock(&g_pmu_lock);
        pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
-       do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
+       do {} while (--retry && (pmu_r32(PMU_PWDSR) & module));
+       spin_unlock(&g_pmu_lock);
 
-       if (!err)
+       if (!retry)
                panic("activating PMU module failed!");
 }
 EXPORT_SYMBOL(ltq_pmu_enable);
@@ -101,7 +180,15 @@ EXPORT_SYMBOL(ltq_pmu_enable);
 /* legacy function kept alive to ease clkdev transition */
 void ltq_pmu_disable(unsigned int module)
 {
+       int retry = 1000000;
+
+       spin_lock(&g_pmu_lock);
        pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
+       do {} while (--retry && (!(pmu_r32(PMU_PWDSR) & module)));
+       spin_unlock(&g_pmu_lock);
+
+       if (!retry)
+               pr_warn("deactivating PMU module failed!");
 }
 EXPORT_SYMBOL(ltq_pmu_disable);
 
@@ -123,9 +210,20 @@ static int pmu_enable(struct clk *clk)
 {
        int retry = 1000000;
 
-       pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
-               PWDCR(clk->module));
-       do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
+       if (of_machine_is_compatible("lantiq,ar10")
+           || of_machine_is_compatible("lantiq,grx390")) {
+               pmu_w32(clk->bits, PWDCR_EN_XRX(clk->module));
+               do {} while (--retry &&
+                            (!(pmu_r32(PWDSR_XRX(clk->module)) & clk->bits)));
+
+       } else {
+               spin_lock(&g_pmu_lock);
+               pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
+                               PWDCR(clk->module));
+               do {} while (--retry &&
+                            (pmu_r32(PWDSR(clk->module)) & clk->bits));
+               spin_unlock(&g_pmu_lock);
+       }
 
        if (!retry)
                panic("activating PMU module failed!");
@@ -136,8 +234,24 @@ static int pmu_enable(struct clk *clk)
 /* disable a clock gate */
 static void pmu_disable(struct clk *clk)
 {
-       pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
-               PWDCR(clk->module));
+       int retry = 1000000;
+
+       if (of_machine_is_compatible("lantiq,ar10")
+           || of_machine_is_compatible("lantiq,grx390")) {
+               pmu_w32(clk->bits, PWDCR_DIS_XRX(clk->module));
+               do {} while (--retry &&
+                            (pmu_r32(PWDSR_XRX(clk->module)) & clk->bits));
+       } else {
+               spin_lock(&g_pmu_lock);
+               pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
+                               PWDCR(clk->module));
+               do {} while (--retry &&
+                            (!(pmu_r32(PWDSR(clk->module)) & clk->bits)));
+               spin_unlock(&g_pmu_lock);
+       }
+
+       if (!retry)
+               pr_warn("deactivating PMU module failed!");
 }
 
 /* the pci enable helper */
@@ -179,6 +293,16 @@ static void pci_ext_disable(struct clk *clk)
        ltq_cgu_w32((1 << 31) | (1 << 30), pcicr);
 }
 
+static void xbar_fpi_burst_disable(void)
+{
+       u32 reg;
+
+       /* bit 1 as 1 --burst; bit 1 as 0 -- single */
+       reg = xbar_r32(XBAR_ALWAYS_LAST);
+       reg &= ~XBAR_FPI_BURST_EN;
+       xbar_w32(reg, XBAR_ALWAYS_LAST);
+}
+
 /* enable a clockout source */
 static int clkout_enable(struct clk *clk)
 {
@@ -202,8 +326,8 @@ static int clkout_enable(struct clk *clk)
 }
 
 /* manage the clock gates via PMU */
-static void clkdev_add_pmu(const char *dev, const char *con,
-                                       unsigned int module, unsigned int bits)
+static void clkdev_add_pmu(const char *dev, const char *con, bool deactivate,
+                          unsigned int module, unsigned int bits)
 {
        struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
@@ -214,6 +338,13 @@ static void clkdev_add_pmu(const char *dev, const char *con,
        clk->disable = pmu_disable;
        clk->module = module;
        clk->bits = bits;
+       if (deactivate) {
+               /*
+                * Disable it during the initialization. Module should enable
+                * when used
+                */
+               pmu_disable(clk);
+       }
        clkdev_add(&clk->cl);
 }
 
@@ -312,12 +443,12 @@ void __init ltq_soc_init(void)
                        of_address_to_resource(np_ebu, 0, &res_ebu))
                panic("Failed to get core resources");
 
-       if ((request_mem_region(res_pmu.start, resource_size(&res_pmu),
-                               res_pmu.name) < 0) ||
-               (request_mem_region(res_cgu.start, resource_size(&res_cgu),
-                               res_cgu.name) < 0) ||
-               (request_mem_region(res_ebu.start, resource_size(&res_ebu),
-                               res_ebu.name) < 0))
+       if (!request_mem_region(res_pmu.start, resource_size(&res_pmu),
+                               res_pmu.name) ||
+               !request_mem_region(res_cgu.start, resource_size(&res_cgu),
+                               res_cgu.name) ||
+               !request_mem_region(res_ebu.start, resource_size(&res_ebu),
+                               res_ebu.name))
                pr_err("Failed to request core resources");
 
        pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu));
@@ -328,17 +459,37 @@ void __init ltq_soc_init(void)
        if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase)
                panic("Failed to remap core resources");
 
+       if (of_machine_is_compatible("lantiq,vr9")) {
+               struct resource res_xbar;
+               struct device_node *np_xbar =
+                               of_find_compatible_node(NULL, NULL,
+                                                       "lantiq,xbar-xway");
+
+               if (!np_xbar)
+                       panic("Failed to load xbar nodes from devicetree");
+               if (of_address_to_resource(np_pmu, 0, &res_xbar))
+                       panic("Failed to get xbar resources");
+               if (request_mem_region(res_xbar.start, resource_size(&res_xbar),
+                       res_xbar.name) < 0)
+                       panic("Failed to get xbar resources");
+
+               ltq_xbar_membase = ioremap_nocache(res_xbar.start,
+                                                  resource_size(&res_xbar));
+               if (!ltq_xbar_membase)
+                       panic("Failed to remap xbar resources");
+       }
+
        /* make sure to unprotect the memory region where flash is located */
        ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
 
        /* add our generic xway clocks */
-       clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI);
-       clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0);
-       clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT);
-       clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP);
-       clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA);
-       clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI);
-       clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU);
+       clkdev_add_pmu("10000000.fpi", NULL, 0, 0, PMU_FPI);
+       clkdev_add_pmu("1e100400.serial", NULL, 0, 0, PMU_ASC0);
+       clkdev_add_pmu("1e100a00.gptu", NULL, 1, 0, PMU_GPT);
+       clkdev_add_pmu("1e100bb0.stp", NULL, 1, 0, PMU_STP);
+       clkdev_add_pmu("1e104100.dma", NULL, 1, 0, PMU_DMA);
+       clkdev_add_pmu("1e100800.spi", NULL, 1, 0, PMU_SPI);
+       clkdev_add_pmu("1e105300.ebu", NULL, 0, 0, PMU_EBU);
        clkdev_add_clkout();
 
        /* add the soc dependent clocks */
@@ -346,14 +497,30 @@ void __init ltq_soc_init(void)
                ifccr = CGU_IFCCR_VR9;
                pcicr = CGU_PCICR_VR9;
        } else {
-               clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE);
+               clkdev_add_pmu("1e180000.etop", NULL, 1, 0, PMU_PPE);
        }
 
        if (!of_machine_is_compatible("lantiq,ase")) {
-               clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1);
+               clkdev_add_pmu("1e100c00.serial", NULL, 0, 0, PMU_ASC1);
                clkdev_add_pci();
        }
 
+       if (of_machine_is_compatible("lantiq,grx390") ||
+           of_machine_is_compatible("lantiq,ar10")) {
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 2, PMU_ANALOG_USB0_P);
+               clkdev_add_pmu("1e106000.usb", "phy", 1, 2, PMU_ANALOG_USB1_P);
+               /* rc 0 */
+               clkdev_add_pmu("1d900000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE0_P);
+               clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI);
+               clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI);
+               clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL);
+               /* rc 1 */
+               clkdev_add_pmu("19000000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE1_P);
+               clkdev_add_pmu("19000000.pcie", "msi", 1, 1, PMU1_PCIE1_MSI);
+               clkdev_add_pmu("19000000.pcie", "pdi", 1, 1, PMU1_PCIE1_PDI);
+               clkdev_add_pmu("19000000.pcie", "ctl", 1, 1, PMU1_PCIE1_CTL);
+       }
+
        if (of_machine_is_compatible("lantiq,ase")) {
                if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
                        clkdev_add_static(CLOCK_266M, CLOCK_133M,
@@ -361,28 +528,84 @@ void __init ltq_soc_init(void)
                else
                        clkdev_add_static(CLOCK_133M, CLOCK_133M,
                                                CLOCK_133M, CLOCK_133M);
-               clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
-               clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e180000.etop", "ppe", 1, 0, PMU_PPE);
+               clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY);
+               clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+       } else if (of_machine_is_compatible("lantiq,grx390")) {
+               clkdev_add_static(ltq_grx390_cpu_hz(), ltq_grx390_fpi_hz(),
+                                 ltq_grx390_fpi_hz(), ltq_grx390_pp32_hz());
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+               /* rc 2 */
+               clkdev_add_pmu("1a800000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE2_P);
+               clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI);
+               clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI);
+               clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL);
+               clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP);
+               clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+       } else if (of_machine_is_compatible("lantiq,ar10")) {
+               clkdev_add_static(ltq_ar10_cpu_hz(), ltq_ar10_fpi_hz(),
+                                 ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz());
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+               clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH |
+                              PMU_PPE_DP | PMU_PPE_TC);
+               clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+               clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
        } else if (of_machine_is_compatible("lantiq,vr9")) {
                clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
                                ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz());
-               clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
-               clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
-               clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
-               clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
-               clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
-               clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
-               clkdev_add_pmu("1e108000.eth", NULL, 0,
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0 | PMU_AHBM);
+               clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1 | PMU_AHBM);
+               clkdev_add_pmu("1d900000.pcie", "phy", 1, 1, PMU1_PCIE_PHY);
+               clkdev_add_pmu("1d900000.pcie", "bus", 1, 0, PMU_PCIE_CLK);
+               clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI);
+               clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI);
+               clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL);
+               clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS);
+
+               clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+               clkdev_add_pmu("1e108000.eth", NULL, 1, 0,
                                PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
                                PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
                                PMU_PPE_QSB | PMU_PPE_TOP);
-               clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY);
+               clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
        } else if (of_machine_is_compatible("lantiq,ar9")) {
                clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
                                ltq_ar9_fpi_hz(), CLOCK_250M);
-               clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+               clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P);
+               clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+               clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0);
        } else {
                clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
                                ltq_danube_fpi_hz(), ltq_danube_pp32_hz());
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+               clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0);
        }
+
+       if (of_machine_is_compatible("lantiq,vr9"))
+               xbar_fpi_burst_disable();
 }
index 1e9e900cd3c382a4a8c3bce2ab7ca2987a1acfcd..0344e575f522982dc4725479d66544d79837b0b4 100644 (file)
@@ -15,4 +15,4 @@ obj-$(CONFIG_CPU_R3000)               += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)       += r3k_dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
-obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o
+obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/bswapdi.c b/arch/mips/lib/bswapdi.c
new file mode 100644 (file)
index 0000000..77e5f9c
--- /dev/null
@@ -0,0 +1,15 @@
+#include <linux/module.h>
+
+unsigned long long __bswapdi2(unsigned long long u)
+{
+       return (((u) & 0xff00000000000000ull) >> 56) |
+              (((u) & 0x00ff000000000000ull) >> 40) |
+              (((u) & 0x0000ff0000000000ull) >> 24) |
+              (((u) & 0x000000ff00000000ull) >>  8) |
+              (((u) & 0x00000000ff000000ull) <<  8) |
+              (((u) & 0x0000000000ff0000ull) << 24) |
+              (((u) & 0x000000000000ff00ull) << 40) |
+              (((u) & 0x00000000000000ffull) << 56);
+}
+
+EXPORT_SYMBOL(__bswapdi2);
diff --git a/arch/mips/lib/bswapsi.c b/arch/mips/lib/bswapsi.c
new file mode 100644 (file)
index 0000000..2b302ff
--- /dev/null
@@ -0,0 +1,11 @@
+#include <linux/module.h>
+
+unsigned int __bswapsi2(unsigned int u)
+{
+       return (((u) & 0xff000000) >> 24) |
+              (((u) & 0x00ff0000) >>  8) |
+              (((u) & 0x0000ff00) <<  8) |
+              (((u) & 0x000000ff) << 24);
+}
+
+EXPORT_SYMBOL(__bswapsi2);
index 497912b38d8ebd82458f225a8b1fc2a5cbaf0d13..8e6e292675b24525f3b50e14e4214fe251914ae1 100644 (file)
@@ -120,11 +120,6 @@ config RS780_HPET
 
          If unsure, say Yes.
 
-config LOONGSON_SUSPEND
-       bool
-       default y
-       depends on CPU_SUPPORTS_CPUFREQ && SUSPEND
-
 config LOONGSON_UART_BASE
        bool
        default y
index f2e8153e44f536213e196002f005bb86da9ef72f..074d9cb15cd20dcb5551a65d99464bc0d0588992 100644 (file)
@@ -23,7 +23,7 @@ obj-$(CONFIG_CS5536) += cs5536/
 # Suspend Support
 #
 
-obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
 
 #
 # Big Memory (SWIOTLB) Support
index 4f9eaa328a1601a3ff63beaf14b86b65f960a469..08b8abcbfef537f11bd7a1c2a747665070bc9bf7 100644 (file)
@@ -8,4 +8,4 @@ obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o
 # Suspend Support
 #
 
-obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
index 506a67a98cdf5cadf12420c17bb89ef4d4af41d9..be650ed7db596bb8b586c7b65bfdddce56f65b3b 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/types.h>
+#include <asm/debug.h>
 #include <asm/fpu_emulator.h>
 #include <asm/local.h>
 
@@ -27,7 +28,6 @@ static int fpuemu_stat_get(void *data, u64 *val)
 }
 DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
 
-extern struct dentry *mips_debugfs_dir;
 static int __init debugfs_fpuemu(void)
 {
        struct dentry *d, *dir;
index 67ede4ef9b8d62c2e0db236fc5890914cebe4ee0..b4c64bd3f723903296c73d75dba3c3e29b861591 100644 (file)
@@ -28,3 +28,4 @@ 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_SCACHE_DEBUGFS)   += sc-debugfs.o
diff --git a/arch/mips/mm/sc-debugfs.c b/arch/mips/mm/sc-debugfs.c
new file mode 100644 (file)
index 0000000..5eefe32
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bcache.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+
+static ssize_t sc_prefetch_read(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       bool enabled = bc_prefetch_is_enabled();
+       char buf[3];
+
+       buf[0] = enabled ? 'Y' : 'N';
+       buf[1] = '\n';
+       buf[2] = 0;
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t sc_prefetch_write(struct file *file,
+                                const char __user *user_buf,
+                                size_t count, loff_t *ppos)
+{
+       char buf[32];
+       ssize_t buf_size;
+       bool enabled;
+       int err;
+
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+       err = strtobool(buf, &enabled);
+       if (err)
+               return err;
+
+       if (enabled)
+               bc_prefetch_enable();
+       else
+               bc_prefetch_disable();
+
+       return count;
+}
+
+static const struct file_operations sc_prefetch_fops = {
+       .open = simple_open,
+       .llseek = default_llseek,
+       .read = sc_prefetch_read,
+       .write = sc_prefetch_write,
+};
+
+static int __init sc_debugfs_init(void)
+{
+       struct dentry *dir, *file;
+
+       if (!mips_debugfs_dir)
+               return -ENODEV;
+
+       dir = debugfs_create_dir("l2cache", mips_debugfs_dir);
+       if (IS_ERR(dir))
+               return PTR_ERR(dir);
+
+       file = debugfs_create_file("prefetch", S_IRUGO | S_IWUSR, dir,
+                                  NULL, &sc_prefetch_fops);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       return 0;
+}
+late_initcall(sc_debugfs_init);
index 53ea8391f9bbf9c2ddf81a114e59f52d05ad7abf..3bd0597d9c3da3a56ea6ba083ca05c67bd71c5e7 100644 (file)
@@ -51,11 +51,69 @@ static void mips_sc_disable(void)
        /* L2 cache is permanently enabled */
 }
 
+static void mips_sc_prefetch_enable(void)
+{
+       unsigned long pftctl;
+
+       if (mips_cm_revision() < CM_REV_CM2_5)
+               return;
+
+       /*
+        * If there is one or more L2 prefetch unit present then enable
+        * prefetching for both code & data, for all ports.
+        */
+       pftctl = read_gcr_l2_pft_control();
+       if (pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK) {
+               pftctl &= ~CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
+               pftctl |= PAGE_MASK & CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
+               pftctl |= CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
+               write_gcr_l2_pft_control(pftctl);
+
+               pftctl = read_gcr_l2_pft_control_b();
+               pftctl |= CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
+               pftctl |= CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
+               write_gcr_l2_pft_control_b(pftctl);
+       }
+}
+
+static void mips_sc_prefetch_disable(void)
+{
+       unsigned long pftctl;
+
+       if (mips_cm_revision() < CM_REV_CM2_5)
+               return;
+
+       pftctl = read_gcr_l2_pft_control();
+       pftctl &= ~CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
+       write_gcr_l2_pft_control(pftctl);
+
+       pftctl = read_gcr_l2_pft_control_b();
+       pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
+       pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
+       write_gcr_l2_pft_control_b(pftctl);
+}
+
+static bool mips_sc_prefetch_is_enabled(void)
+{
+       unsigned long pftctl;
+
+       if (mips_cm_revision() < CM_REV_CM2_5)
+               return false;
+
+       pftctl = read_gcr_l2_pft_control();
+       if (!(pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK))
+               return false;
+       return !!(pftctl & CM_GCR_L2_PFT_CONTROL_PFTEN_MSK);
+}
+
 static struct bcache_ops mips_sc_ops = {
        .bc_enable = mips_sc_enable,
        .bc_disable = mips_sc_disable,
        .bc_wback_inv = mips_sc_wback_inv,
-       .bc_inv = mips_sc_inv
+       .bc_inv = mips_sc_inv,
+       .bc_prefetch_enable = mips_sc_prefetch_enable,
+       .bc_prefetch_disable = mips_sc_prefetch_disable,
+       .bc_prefetch_is_enabled = mips_sc_prefetch_is_enabled,
 };
 
 /*
@@ -162,13 +220,13 @@ static inline int __init mips_sc_probe(void)
                return 0;
 
        tmp = (config2 >> 8) & 0x0f;
-       if (0 <= tmp && tmp <= 7)
+       if (tmp <= 7)
                c->scache.sets = 64 << tmp;
        else
                return 0;
 
        tmp = (config2 >> 0) & 0x0f;
-       if (0 <= tmp && tmp <= 7)
+       if (tmp <= 7)
                c->scache.ways = tmp + 1;
        else
                return 0;
@@ -186,6 +244,7 @@ int mips_sc_init(void)
        int found = mips_sc_probe();
        if (found) {
                mips_sc_enable();
+               mips_sc_prefetch_enable();
                bcops = &mips_sc_ops;
        }
        return found;
index 323d1d302f2bd898372c5143c1b8c7fb2714a1ad..32e0be27673fefbeca6839929e61a581c8980902 100644 (file)
@@ -311,6 +311,7 @@ static struct uasm_label labels[128];
 static struct uasm_reloc relocs[128];
 
 static int check_for_high_segbits;
+static bool fill_includes_sw_bits;
 
 static unsigned int kscratch_used_mask;
 
@@ -630,8 +631,14 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 static __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
                                                        unsigned int reg)
 {
-       if (cpu_has_rixi) {
-               UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
+       if (cpu_has_rixi && _PAGE_NO_EXEC) {
+               if (fill_includes_sw_bits) {
+                       UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
+               } else {
+                       UASM_i_SRL(p, reg, reg, ilog2(_PAGE_NO_EXEC));
+                       UASM_i_ROTR(p, reg, reg,
+                                   ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
+               }
        } else {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
                uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL));
@@ -1005,21 +1012,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
         * 64bit address support (36bit on a 32bit CPU) in a 32bit
         * Kernel is a special case. Only a few CPUs use it.
         */
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
-       if (cpu_has_64bits) {
-               uasm_i_ld(p, tmp, 0, ptep); /* get even pte */
-               uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
-               if (cpu_has_rixi) {
-                       UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
-                       UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-                       UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
-               } else {
-                       uasm_i_dsrl_safe(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
-                       UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-                       uasm_i_dsrl_safe(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
-               }
-               UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
-       } else {
+       if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) {
                int pte_off_even = sizeof(pte_t) / 2;
                int pte_off_odd = pte_off_even + sizeof(pte_t);
 #ifdef CONFIG_XPA
@@ -1043,31 +1036,23 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
                uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
                uasm_i_mthc0(p, ptep, C0_ENTRYLO1);
 #endif
+               return;
        }
-#else
+
        UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
        UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
        if (r45k_bvahwbug())
                build_tlb_probe_entry(p);
-       if (cpu_has_rixi) {
-               UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
-               if (r4k_250MHZhwbug())
-                       UASM_i_MTC0(p, 0, C0_ENTRYLO0);
-               UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-               UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
-       } else {
-               UASM_i_SRL(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
-               if (r4k_250MHZhwbug())
-                       UASM_i_MTC0(p, 0, C0_ENTRYLO0);
-               UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-               UASM_i_SRL(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
-               if (r45k_bvahwbug())
-                       uasm_i_mfc0(p, tmp, C0_INDEX);
-       }
+       build_convert_pte_to_entrylo(p, tmp);
+       if (r4k_250MHZhwbug())
+               UASM_i_MTC0(p, 0, C0_ENTRYLO0);
+       UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
+       build_convert_pte_to_entrylo(p, ptep);
+       if (r45k_bvahwbug())
+               uasm_i_mfc0(p, tmp, C0_INDEX);
        if (r4k_250MHZhwbug())
                UASM_i_MTC0(p, 0, C0_ENTRYLO1);
        UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
-#endif
 }
 
 struct mips_huge_tlb_info {
@@ -2299,6 +2284,10 @@ static void config_htw_params(void)
        /* re-initialize the PTI field including the even/odd bit */
        pwfield &= ~MIPS_PWFIELD_PTI_MASK;
        pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
+       if (CONFIG_PGTABLE_LEVELS >= 3) {
+               pwfield &= ~MIPS_PWFIELD_MDI_MASK;
+               pwfield |= PMD_SHIFT << MIPS_PWFIELD_MDI_SHIFT;
+       }
        /* Set the PTEI right shift */
        ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
        pwfield |= ptei;
@@ -2320,9 +2309,11 @@ static void config_htw_params(void)
 
        pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
        pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
+       if (CONFIG_PGTABLE_LEVELS >= 3)
+               pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT;
 
        /* If XPA has been enabled, PTEs are 64-bit in size. */
-       if (read_c0_pagegrain() & PG_ELPA)
+       if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA))
                pwsize |= 1;
 
        write_c0_pwsize(pwsize);
@@ -2360,6 +2351,41 @@ static void config_xpa_params(void)
 #endif
 }
 
+static void check_pabits(void)
+{
+       unsigned long entry;
+       unsigned pabits, fillbits;
+
+       if (!cpu_has_rixi || !_PAGE_NO_EXEC) {
+               /*
+                * We'll only be making use of the fact that we can rotate bits
+                * into the fill if the CPU supports RIXI, so don't bother
+                * probing this for CPUs which don't.
+                */
+               return;
+       }
+
+       write_c0_entrylo0(~0ul);
+       back_to_back_c0_hazard();
+       entry = read_c0_entrylo0();
+
+       /* clear all non-PFN bits */
+       entry &= ~((1 << MIPS_ENTRYLO_PFN_SHIFT) - 1);
+       entry &= ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
+
+       /* find a lower bound on PABITS, and upper bound on fill bits */
+       pabits = fls_long(entry) + 6;
+       fillbits = max_t(int, (int)BITS_PER_LONG - pabits, 0);
+
+       /* minus the RI & XI bits */
+       fillbits -= min_t(unsigned, fillbits, 2);
+
+       if (fillbits >= ilog2(_PAGE_NO_EXEC))
+               fill_includes_sw_bits = true;
+
+       pr_debug("Entry* registers contain %u fill bits\n", fillbits);
+}
+
 void build_tlb_refill_handler(void)
 {
        /*
@@ -2370,6 +2396,7 @@ void build_tlb_refill_handler(void)
        static int run_once = 0;
 
        output_pgtable_bits_defines();
+       check_pabits();
 
 #ifdef CONFIG_64BIT
        check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
index ea35587a5c2920a0e32c4a00fdc346ac41d4cd9d..5827af77c18e9931c43af5e5df2881f94df44c25 100644 (file)
@@ -5,9 +5,18 @@
 # Copyright (C) 2008 Wind River Systems, Inc.
 #   written by Ralf Baechle <ralf@linux-mips.org>
 #
-obj-y                          := malta-display.o malta-dt.o malta-init.o \
-                                  malta-int.o malta-memory.o malta-platform.o \
-                                  malta-reset.o malta-setup.o malta-time.o
+obj-y                          += malta-display.o
+obj-y                          += malta-dt.o
+obj-y                          += malta-dtshim.o
+obj-y                          += malta-init.o
+obj-y                          += malta-int.o
+obj-y                          += malta-memory.o
+obj-y                          += malta-platform.o
+obj-y                          += malta-reset.o
+obj-y                          += malta-setup.o
+obj-y                          += malta-time.o
 
 obj-$(CONFIG_MIPS_CMP)         += malta-amon.o
 obj-$(CONFIG_MIPS_MALTA_PM)    += malta-pm.o
+
+CFLAGS_malta-dtshim.o = -I$(src)/../../../scripts/dtc/libfdt
diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
new file mode 100644 (file)
index 0000000..f7133ef
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/sizes.h>
+#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
+#include <asm/page.h>
+
+static unsigned char fdt_buf[16 << 10] __initdata;
+
+/* determined physical memory size, not overridden by command line args         */
+extern unsigned long physical_memsize;
+
+#define MAX_MEM_ARRAY_ENTRIES 1
+
+static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
+{
+       unsigned long size_preio;
+       unsigned entries;
+
+       entries = 1;
+       mem_array[0] = cpu_to_be32(PHYS_OFFSET);
+       if (config_enabled(CONFIG_EVA)) {
+               /*
+                * The current Malta EVA configuration is "special" in that it
+                * always makes use of addresses in the upper half of the 32 bit
+                * physical address map, which gives it a contiguous region of
+                * DDR but limits it to 2GB.
+                */
+               mem_array[1] = cpu_to_be32(size);
+       } else {
+               size_preio = min_t(unsigned long, size, SZ_256M);
+               mem_array[1] = cpu_to_be32(size_preio);
+       }
+
+       BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
+       return entries;
+}
+
+static void __init append_memory(void *fdt, int root_off)
+{
+       __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
+       unsigned long memsize;
+       unsigned mem_entries;
+       int i, err, mem_off;
+       char *var, param_name[10], *var_names[] = {
+               "ememsize", "memsize",
+       };
+
+       /* if a memory node already exists, leave it alone */
+       mem_off = fdt_path_offset(fdt, "/memory");
+       if (mem_off >= 0)
+               return;
+
+       /* find memory size from the bootloader environment */
+       for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+               var = fw_getenv(var_names[i]);
+               if (!var)
+                       continue;
+
+               err = kstrtoul(var, 0, &physical_memsize);
+               if (!err)
+                       break;
+
+               pr_warn("Failed to read the '%s' env variable '%s'\n",
+                       var_names[i], var);
+       }
+
+       if (!physical_memsize) {
+               pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
+               physical_memsize = 32 << 20;
+       }
+
+       if (config_enabled(CONFIG_CPU_BIG_ENDIAN)) {
+               /*
+                * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
+                * the last word of physical memory.
+                */
+               physical_memsize -= PAGE_SIZE;
+       }
+
+       /* default to using all available RAM */
+       memsize = physical_memsize;
+
+       /* allow the user to override the usable memory */
+       for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+               snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
+               var = strstr(arcs_cmdline, param_name);
+               if (!var)
+                       continue;
+
+               memsize = memparse(var + strlen(param_name), NULL);
+       }
+
+       /* if the user says there's more RAM than we thought, believe them */
+       physical_memsize = max_t(unsigned long, physical_memsize, memsize);
+
+       /* append memory to the DT */
+       mem_off = fdt_add_subnode(fdt, root_off, "memory");
+       if (mem_off < 0)
+               panic("Unable to add memory node to DT: %d", mem_off);
+
+       err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
+       if (err)
+               panic("Unable to set memory node device_type: %d", err);
+
+       mem_entries = gen_fdt_mem_array(mem_array, physical_memsize);
+       err = fdt_setprop(fdt, mem_off, "reg", mem_array,
+                         mem_entries * 2 * sizeof(mem_array[0]));
+       if (err)
+               panic("Unable to set memory regs property: %d", err);
+
+       mem_entries = gen_fdt_mem_array(mem_array, memsize);
+       err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
+                         mem_entries * 2 * sizeof(mem_array[0]));
+       if (err)
+               panic("Unable to set linux,usable-memory property: %d", err);
+}
+
+void __init *malta_dt_shim(void *fdt)
+{
+       int root_off, len, err;
+       const char *compat;
+
+       if (fdt_check_header(fdt))
+               panic("Corrupt DT");
+
+       err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
+       if (err)
+               panic("Unable to open FDT: %d", err);
+
+       root_off = fdt_path_offset(fdt_buf, "/");
+       if (root_off < 0)
+               panic("No / node in DT");
+
+       compat = fdt_getprop(fdt_buf, root_off, "compatible", &len);
+       if (!compat)
+               panic("No root compatible property in DT: %d", len);
+
+       /* if this isn't Malta, leave the DT alone */
+       if (strncmp(compat, "mti,malta", len))
+               return fdt;
+
+       append_memory(fdt_buf, root_off);
+
+       err = fdt_pack(fdt_buf);
+       if (err)
+               panic("Unable to pack FDT: %d\n", err);
+
+       return fdt_buf;
+}
index 53c24784a2f7bd2e8c0ae719f1f07c9ad60dd52b..571148c5fd0baa5ce8656e87574144d90b58e346 100644 (file)
@@ -302,6 +302,7 @@ mips_pci_controller:
                return;
        if (!register_vsmp_smp_ops())
                return;
+       register_up_smp_ops();
 }
 
 void platform_early_l2_init(void)
index dadeb83791828249e3af6d62ad55f1e9a2756a8a..d5f8dae6a7978a5b7e3c62c4c70bef756941a061 100644 (file)
 #include <asm/sections.h>
 #include <asm/fw/fw.h>
 
-static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS];
-
 /* determined physical memory size, not overridden by command line args         */
 unsigned long physical_memsize = 0L;
 
-fw_memblock_t * __init fw_getmdesc(int eva)
-{
-       char *memsize_str, *ememsize_str = NULL, *ptr;
-       unsigned long memsize = 0, ememsize = 0;
-       static char cmdline[COMMAND_LINE_SIZE] __initdata;
-       int tmp;
-
-       /* otherwise look in the environment */
-
-       memsize_str = fw_getenv("memsize");
-       if (memsize_str) {
-               tmp = kstrtoul(memsize_str, 0, &memsize);
-               if (tmp)
-                       pr_warn("Failed to read the 'memsize' env variable.\n");
-       }
-       if (eva) {
-       /* Look for ememsize for EVA */
-               ememsize_str = fw_getenv("ememsize");
-               if (ememsize_str) {
-                       tmp = kstrtoul(ememsize_str, 0, &ememsize);
-                       if (tmp)
-                               pr_warn("Failed to read the 'ememsize' env variable.\n");
-               }
-       }
-       if (!memsize && !ememsize) {
-               pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
-               physical_memsize = 0x02000000;
-       } else {
-               if (memsize > (256 << 20)) { /* memsize should be capped to 256M */
-                       pr_warn("Unsupported memsize value (0x%lx) detected! "
-                               "Using 0x10000000 (256M) instead\n",
-                               memsize);
-                       memsize = 256 << 20;
-               }
-               /* If ememsize is set, then set physical_memsize to that */
-               physical_memsize = ememsize ? : memsize;
-       }
-
-#ifdef CONFIG_CPU_BIG_ENDIAN
-       /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
-          word of physical memory */
-       physical_memsize -= PAGE_SIZE;
-#endif
-
-       /* Check the command line for a memsize directive that overrides
-          the physical/default amount */
-       strcpy(cmdline, arcs_cmdline);
-       ptr = strstr(cmdline, "memsize=");
-       if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
-               ptr = strstr(ptr, " memsize=");
-       /* And now look for ememsize */
-       if (eva) {
-               ptr = strstr(cmdline, "ememsize=");
-               if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
-                       ptr = strstr(ptr, " ememsize=");
-       }
-
-       if (ptr)
-               memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr);
-       else
-               memsize = physical_memsize;
-
-       /* Last 64K for HIGHMEM arithmetics */
-       if (memsize > 0x7fff0000)
-               memsize = 0x7fff0000;
-
-       memset(mdesc, 0, sizeof(mdesc));
-
-       mdesc[0].type = fw_dontuse;
-       mdesc[0].base = PHYS_OFFSET;
-       mdesc[0].size = 0x00001000;
-
-       mdesc[1].type = fw_code;
-       mdesc[1].base = mdesc[0].base + 0x00001000UL;
-       mdesc[1].size = 0x000ef000;
-
-       /*
-        * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
-        * south bridge and PCI access always forwarded to the ISA Bus and
-        * BIOSCS# is always generated.
-        * This mean that this area can't be used as DMA memory for PCI
-        * devices.
-        */
-       mdesc[2].type = fw_dontuse;
-       mdesc[2].base = mdesc[0].base + 0x000f0000UL;
-       mdesc[2].size = 0x00010000;
-
-       mdesc[3].type = fw_dontuse;
-       mdesc[3].base = mdesc[0].base + 0x00100000UL;
-       mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
-               0x00100000UL;
-
-       mdesc[4].type = fw_free;
-       mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end));
-       mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base);
-
-       return &mdesc[0];
-}
-
 static void free_init_pages_eva_malta(void *begin, void *end)
 {
        free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
                        __pa_symbol((unsigned long *)end));
 }
 
-static int __init fw_memtype_classify(unsigned int type)
-{
-       switch (type) {
-       case fw_free:
-               return BOOT_MEM_RAM;
-       case fw_code:
-               return BOOT_MEM_ROM_DATA;
-       default:
-               return BOOT_MEM_RESERVED;
-       }
-}
-
 void __init fw_meminit(void)
 {
-       fw_memblock_t *p;
-
-       p = fw_getmdesc(config_enabled(CONFIG_EVA));
-       free_init_pages_eva = (config_enabled(CONFIG_EVA) ?
-                              free_init_pages_eva_malta : NULL);
+       bool eva = config_enabled(CONFIG_EVA);
 
-       while (p->size) {
-               long type;
-               unsigned long base, size;
-
-               type = fw_memtype_classify(p->type);
-               base = p->base;
-               size = p->size;
-
-               add_memory_region(base, size, type);
-               p++;
-       }
+       free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL;
 }
 
 void __init prom_free_prom_memory(void)
index 9d1e7f5ec36cac95dbad432f0a8c1378b5c75195..4740c82fb97a14e95118d05590b66b3192e9f1f5 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/time.h>
 
 #include <asm/fw/fw.h>
+#include <asm/mach-malta/malta-dtshim.h>
 #include <asm/mips-cm.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/malta.h>
@@ -250,8 +251,10 @@ static void __init bonito_quirks_setup(void)
 void __init plat_mem_setup(void)
 {
        unsigned int i;
+       void *fdt = __dtb_start;
 
-       __dt_setup_arch(__dtb_start);
+       fdt = malta_dt_shim(fdt);
+       __dt_setup_arch(fdt);
 
        if (config_enabled(CONFIG_EVA))
                /* EVA has already been configured in mach-malta/kernel-init.h */
index a625bdb6d6aa0e2f23de8c629f34e28803d19d66..856a6e6d296e978a6435707a781bc15df412824e 100644 (file)
@@ -87,7 +87,6 @@ void __init *xlp_dt_init(void *fdtp)
 void __init xlp_early_init_devtree(void)
 {
        __dt_setup_arch(xlp_fdt_blob);
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 }
 
 void __init device_tree_init(void)
index ed6732f9aa874c2557a93de78e9cb1c816320af1..53a42b07008b99f2043ac1da444b9732c4af8c2b 100644 (file)
@@ -432,8 +432,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
 
        /* find the interrupt controller child node */
        for_each_child_of_node(np, child) {
-               if (of_get_property(child, "interrupt-controller", NULL) &&
-                   of_node_get(child)) {
+               if (of_get_property(child, "interrupt-controller", NULL)) {
                        rpc->intc_of_node = child;
                        break;
                }
@@ -449,8 +448,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
        /* find the PCI host bridge child node */
        for_each_child_of_node(np, child) {
                if (child->type &&
-                   of_node_cmp(child->type, "pci") == 0 &&
-                   of_node_get(child)) {
+                   of_node_cmp(child->type, "pci") == 0) {
                        rpc->pci_controller.of_node = child;
                        break;
                }
index 8bd8ebb20a72631501e5365478d10aa0d07b992b..96ba2cc9ad3e34da3948c3103d41629e24c88227 100644 (file)
@@ -58,7 +58,6 @@ void __init plat_mem_setup(void)
                panic("Device-tree not present");
 
        __dt_setup_arch((void *)fw_arg1);
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 
        plat_setup_iocoherency();
 }
index a8e70a9f274bdf70b0be449bee57c71c513e6fc4..e46f91f971c54f85759067c26b8a5d27d98f6a74 100644 (file)
@@ -48,7 +48,7 @@ static int systick_next_event(unsigned long delta,
        sdev = container_of(evt, struct systick_device, dev);
        count = ioread32(sdev->membase + SYSTICK_COUNT);
        count = (count + delta) % SYSTICK_FREQ;
-       iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE);
+       iowrite32(count, sdev->membase + SYSTICK_COMPARE);
 
        return 0;
 }
index 255d695ec8c609168e92d1b9ec5cafe5020eda1b..3c59ffe5f5f54116785a501ad39abaccd1ad11a5 100644 (file)
 #define MT7628_CHIP_NAME1      0x20203832
 
 #define UART_REG_TX            0x04
+#define UART_REG_LCR           0x0c
 #define UART_REG_LSR           0x14
 #define UART_REG_LSR_RT2880    0x1c
 
 static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE);
 static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE);
+static int init_complete;
 
 static inline void uart_w32(u32 val, unsigned reg)
 {
@@ -47,8 +49,32 @@ static inline int soc_is_mt7628(void)
                (__raw_readl(chipid_membase) == MT7628_CHIP_NAME1);
 }
 
+static void find_uart_base(void)
+{
+       int i;
+
+       if (!soc_is_mt7628())
+               return;
+
+       for (i = 0; i < 3; i++) {
+               u32 reg = uart_r32(UART_REG_LCR + (0x100 * i));
+
+               if (!reg)
+                       continue;
+
+               uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE +
+                                                         (0x100 * i));
+               break;
+       }
+}
+
 void prom_putchar(unsigned char ch)
 {
+       if (!init_complete) {
+               find_uart_base();
+               init_complete = 1;
+       }
+
        if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) {
                uart_w32(ch, UART_TX);
                while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
index 2ea5ff6dc22e6d769cc851347b5c7492535e0596..dfb04fcedb042d9b80621ac3197886a1ea3bccda 100644 (file)
 #define PMU1_CFG               0x8C
 #define DIG_SW_SEL             BIT(25)
 
-/* is this a MT7620 or a MT7628 */
-enum mt762x_soc_type mt762x_soc;
+/* clock scaling */
+#define CLKCFG_FDIV_MASK       0x1f00
+#define CLKCFG_FDIV_USB_VAL    0x0300
+#define CLKCFG_FFRAC_MASK      0x001f
+#define CLKCFG_FFRAC_USB_VAL   0x0003
+
+/* EFUSE bits */
+#define EFUSE_MT7688           0x100000
+
+/* DRAM type bit */
+#define DRAM_TYPE_MT7628_MASK  0x1
 
 /* does the board have sdram or ddram */
 static int dram_type;
@@ -227,6 +236,12 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
        { 0 }
 };
 
+static inline int is_mt76x8(void)
+{
+       return ralink_soc == MT762X_SOC_MT7628AN ||
+              ralink_soc == MT762X_SOC_MT7688;
+}
+
 static __init u32
 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div)
 {
@@ -381,7 +396,7 @@ void __init ralink_clk_init(void)
 #define RINT(x)                ((x) / 1000000)
 #define RFRAC(x)       (((x) / 1000) % 1000)
 
-       if (mt762x_soc == MT762X_SOC_MT7628AN) {
+       if (is_mt76x8()) {
                if (xtal_rate == MHZ(40))
                        cpu_rate = MHZ(580);
                else
@@ -423,6 +438,20 @@ void __init ralink_clk_init(void)
        ralink_clk_add("10000b00.spi", sys_rate);
        ralink_clk_add("10000c00.uartlite", periph_rate);
        ralink_clk_add("10180000.wmac", xtal_rate);
+
+       if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) {
+               /*
+                * When the CPU goes into sleep mode, the BUS clock will be
+                * too low for USB to function properly. Adjust the busses
+                * fractional divider to fix this
+                */
+               u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG);
+
+               val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK);
+               val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL;
+
+               rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG);
+       }
 }
 
 void __init ralink_of_remap(void)
@@ -499,20 +528,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
 
        if (n0 == MT7620_CHIP_NAME0 && n1 == MT7620_CHIP_NAME1) {
                if (bga) {
-                       mt762x_soc = MT762X_SOC_MT7620A;
+                       ralink_soc = MT762X_SOC_MT7620A;
                        name = "MT7620A";
                        soc_info->compatible = "ralink,mt7620a-soc";
                } else {
-                       mt762x_soc = MT762X_SOC_MT7620N;
+                       ralink_soc = MT762X_SOC_MT7620N;
                        name = "MT7620N";
                        soc_info->compatible = "ralink,mt7620n-soc";
-#ifdef CONFIG_PCI
-                       panic("mt7620n is only supported for non pci kernels");
-#endif
                }
        } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) {
-               mt762x_soc = MT762X_SOC_MT7628AN;
-               name = "MT7628AN";
+               u32 efuse = __raw_readl(sysc + SYSC_REG_EFUSE_CFG);
+
+               if (efuse & EFUSE_MT7688) {
+                       ralink_soc = MT762X_SOC_MT7688;
+                       name = "MT7688";
+               } else {
+                       ralink_soc = MT762X_SOC_MT7628AN;
+                       name = "MT7628AN";
+               }
                soc_info->compatible = "ralink,mt7628an-soc";
        } else {
                panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
@@ -525,10 +558,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
                (rev & CHIP_REV_ECO_MASK));
 
        cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
-       dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK;
+       if (is_mt76x8())
+               dram_type = cfg0 & DRAM_TYPE_MT7628_MASK;
+       else
+               dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) &
+                           SYSCFG0_DRAM_TYPE_MASK;
 
        soc_info->mem_base = MT7620_DRAM_BASE;
-       if (mt762x_soc == MT762X_SOC_MT7628AN)
+       if (is_mt76x8())
                mt7628_dram_init(soc_info);
        else
                mt7620_dram_init(soc_info);
@@ -541,7 +578,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
        pr_info("Digital PMU set to %s control\n",
                (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw"));
 
-       if (mt762x_soc == MT762X_SOC_MT7628AN)
+       if (is_mt76x8())
                rt2880_pinmux_data = mt7628an_pinmux_data;
        else
                rt2880_pinmux_data = mt7620a_pinmux_data;
index 0d30dcd6324623a3ed6dc635ec653a2619228132..f9eda5d8f82cd54681efbdf65c4f55123a3dfeed 100644 (file)
@@ -74,8 +74,6 @@ void __init plat_mem_setup(void)
         */
        __dt_setup_arch(__dtb_start);
 
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
-
        of_scan_flat_dt(early_init_dt_find_memory, NULL);
        if (memory_dtb)
                of_scan_flat_dt(early_init_dt_scan_memory, NULL);
index 09419f67da3990985be6d0a4db5de6460def0607..39a9142f71be214ed97194edc15f0398a028ffbd 100644 (file)
 #include <asm/bootinfo.h>
 #include <asm/addrspace.h>
 
+#include <asm/mach-ralink/ralink_regs.h>
+
 #include "common.h"
 
 struct ralink_soc_info soc_info;
 struct rt2880_pmx_group *rt2880_pinmux_data = NULL;
 
+enum ralink_soc_type ralink_soc;
+EXPORT_SYMBOL_GPL(ralink_soc);
+
 const char *get_system_type(void)
 {
        return soc_info.sys_type;
index 55c7ec59df3cca8a73259ee84731189a91db49ce..ee117c4bc4a36cc6f974c5efc89751300a535108 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/pm.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/delay.h>
 #include <linux/reset-controller.h>
 
 #include <asm/reboot.h>
 #include <asm/mach-ralink/ralink_regs.h>
 
 /* Reset Control */
-#define SYSC_REG_RESET_CTRL     0x034
-#define RSTCTL_RESET_SYSTEM     BIT(0)
+#define SYSC_REG_RESET_CTRL    0x034
+
+#define RSTCTL_RESET_PCI       BIT(26)
+#define RSTCTL_RESET_SYSTEM    BIT(0)
 
 static int ralink_assert_device(struct reset_controller_dev *rcdev,
                                unsigned long id)
@@ -83,6 +86,11 @@ void ralink_rst_init(void)
 
 static void ralink_restart(char *command)
 {
+       if (IS_ENABLED(CONFIG_PCI)) {
+               rt_sysc_m32(0, RSTCTL_RESET_PCI, SYSC_REG_RESET_CTRL);
+               mdelay(50);
+       }
+
        local_irq_disable();
        rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL);
        unreachable();
@@ -98,7 +106,6 @@ static int __init mips_reboot_setup(void)
 {
        _machine_restart = ralink_restart;
        _machine_halt = ralink_halt;
-       pm_power_off = ralink_halt;
 
        return 0;
 }
index 738cec865f41a1a371d1c5506f0c4e50b268dce6..844f5cd55c8f1c1e96e20db2a888c22e1fb12327 100644 (file)
@@ -119,4 +119,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
        soc_info->mem_size_max = RT2880_MEM_SIZE_MAX;
 
        rt2880_pinmux_data = rt2880_pinmux_data_act;
+       ralink_soc == RT2880_SOC;
 }
index c40776ab67db5e0147d250e83990f6577c693268..9e45725920650bd55350549097f9330403f3ef6a 100644 (file)
@@ -21,8 +21,6 @@
 
 #include "common.h"
 
-enum rt305x_soc_type rt305x_soc;
-
 static struct rt2880_pmx_func i2c_func[] =  { FUNC("i2c", 0, 1, 2) };
 static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) };
 static struct rt2880_pmx_func uartf_func[] = {
@@ -201,6 +199,7 @@ void __init ralink_clk_init(void)
        }
 
        ralink_clk_add("cpu", cpu_rate);
+       ralink_clk_add("sys", sys_rate);
        ralink_clk_add("10000b00.spi", sys_rate);
        ralink_clk_add("10000100.timer", wdt_rate);
        ralink_clk_add("10000120.watchdog", wdt_rate);
@@ -235,24 +234,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
 
                icache_sets = (read_c0_config1() >> 22) & 7;
                if (icache_sets == 1) {
-                       rt305x_soc = RT305X_SOC_RT3050;
+                       ralink_soc = RT305X_SOC_RT3050;
                        name = "RT3050";
                        soc_info->compatible = "ralink,rt3050-soc";
                } else {
-                       rt305x_soc = RT305X_SOC_RT3052;
+                       ralink_soc = RT305X_SOC_RT3052;
                        name = "RT3052";
                        soc_info->compatible = "ralink,rt3052-soc";
                }
        } else if (n0 == RT3350_CHIP_NAME0 && n1 == RT3350_CHIP_NAME1) {
-               rt305x_soc = RT305X_SOC_RT3350;
+               ralink_soc = RT305X_SOC_RT3350;
                name = "RT3350";
                soc_info->compatible = "ralink,rt3350-soc";
        } else if (n0 == RT3352_CHIP_NAME0 && n1 == RT3352_CHIP_NAME1) {
-               rt305x_soc = RT305X_SOC_RT3352;
+               ralink_soc = RT305X_SOC_RT3352;
                name = "RT3352";
                soc_info->compatible = "ralink,rt3352-soc";
        } else if (n0 == RT5350_CHIP_NAME0 && n1 == RT5350_CHIP_NAME1) {
-               rt305x_soc = RT305X_SOC_RT5350;
+               ralink_soc = RT305X_SOC_RT5350;
                name = "RT5350";
                soc_info->compatible = "ralink,rt5350-soc";
        } else {
index 86a535c770d84e4768680b7a58e06acf97a247e8..582995aaaf4e7e8a9848c512d150b515f3628344 100644 (file)
@@ -153,4 +153,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
        soc_info->mem_size_max = RT3883_MEM_SIZE_MAX;
 
        rt2880_pinmux_data = rt3883_pinmux_data;
+
+       ralink_soc == RT3883_SOC;
 }
diff --git a/arch/mips/vdso/.gitignore b/arch/mips/vdso/.gitignore
new file mode 100644 (file)
index 0000000..5286a7d
--- /dev/null
@@ -0,0 +1,4 @@
+*.so*
+vdso-*image.c
+genvdso
+vdso*.lds
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
new file mode 100644 (file)
index 0000000..ef5f348
--- /dev/null
@@ -0,0 +1,160 @@
+# Objects to go into the VDSO.
+obj-vdso-y := elf.o gettimeofday.o sigreturn.o
+
+# Common compiler flags between ABIs.
+ccflags-vdso := \
+       $(filter -I%,$(KBUILD_CFLAGS)) \
+       $(filter -E%,$(KBUILD_CFLAGS)) \
+       $(filter -march=%,$(KBUILD_CFLAGS))
+cflags-vdso := $(ccflags-vdso) \
+       $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
+       -O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \
+       $(call cc-option, -fno-stack-protector)
+aflags-vdso := $(ccflags-vdso) \
+       $(filter -I%,$(KBUILD_CFLAGS)) \
+       $(filter -E%,$(KBUILD_CFLAGS)) \
+       -D__ASSEMBLY__ -Wa,-gdwarf-2
+
+#
+# For the pre-R6 code in arch/mips/vdso/vdso.h for locating
+# the base address of VDSO, the linker will emit a R_MIPS_PC32
+# relocation in binutils > 2.25 but it will fail with older versions
+# because that relocation is not supported for that symbol. As a result
+# of which we are forced to disable the VDSO symbols when building
+# with < 2.25 binutils on pre-R6 kernels. For more references on why we
+# can't use other methods to get the base address of VDSO please refer to
+# the comments on that file.
+#
+ifndef CONFIG_CPU_MIPSR6
+  ifeq ($(call ld-ifversion, -gt, 22400000, y),)
+    $(warning MIPS VDSO requires binutils > 2.24)
+    obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
+    ccflags-vdso += -DDISABLE_MIPS_VDSO
+  endif
+endif
+
+# VDSO linker flags.
+VDSO_LDFLAGS := \
+       -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
+       -nostdlib -shared \
+       $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
+       $(call cc-ldoption, -Wl$(comma)--build-id)
+
+GCOV_PROFILE := n
+
+#
+# Shared build commands.
+#
+
+quiet_cmd_vdsold = VDSO    $@
+      cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
+                   -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
+
+hostprogs-y := genvdso
+
+quiet_cmd_genvdso = GENVDSO $@
+define cmd_genvdso
+       cp $< $(<:%.dbg=%) && \
+       $(OBJCOPY) -S $< $(<:%.dbg=%) && \
+       $(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME)
+endef
+
+#
+# Build native VDSO.
+#
+
+native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS))
+
+targets += $(obj-vdso-y)
+targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c
+
+obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o)
+
+$(obj-vdso): KBUILD_CFLAGS := $(cflags-vdso) $(native-abi)
+$(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi)
+
+$(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi)
+
+$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
+       $(call if_changed,vdsold)
+
+$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE
+       $(call if_changed,genvdso)
+
+obj-y += vdso-image.o
+
+#
+# Build O32 VDSO.
+#
+
+# Define these outside the ifdef to ensure they are picked up by clean.
+targets += $(obj-vdso-y:%.o=%-o32.o)
+targets += vdso-o32.lds vdso-o32.so.dbg vdso-o32.so vdso-o32-image.c
+
+ifdef CONFIG_MIPS32_O32
+
+obj-vdso-o32 := $(obj-vdso-y:%.o=$(obj)/%-o32.o)
+
+$(obj-vdso-o32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=32
+$(obj-vdso-o32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=32
+
+$(obj)/%-o32.o: $(src)/%.S FORCE
+       $(call if_changed_dep,as_o_S)
+
+$(obj)/%-o32.o: $(src)/%.c FORCE
+       $(call cmd,force_checksrc)
+       $(call if_changed_rule,cc_o_c)
+
+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
+$(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
+       $(call if_changed_dep,cpp_lds_S)
+
+$(obj)/vdso-o32.so.dbg: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
+       $(call if_changed,vdsold)
+
+$(obj)/vdso-o32-image.c: VDSO_NAME := o32
+$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg $(obj)/genvdso FORCE
+       $(call if_changed,genvdso)
+
+obj-y += vdso-o32-image.o
+
+endif
+
+#
+# Build N32 VDSO.
+#
+
+targets += $(obj-vdso-y:%.o=%-n32.o)
+targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c
+
+ifdef CONFIG_MIPS32_N32
+
+obj-vdso-n32 := $(obj-vdso-y:%.o=$(obj)/%-n32.o)
+
+$(obj-vdso-n32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=n32
+$(obj-vdso-n32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=n32
+
+$(obj)/%-n32.o: $(src)/%.S FORCE
+       $(call if_changed_dep,as_o_S)
+
+$(obj)/%-n32.o: $(src)/%.c FORCE
+       $(call cmd,force_checksrc)
+       $(call if_changed_rule,cc_o_c)
+
+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
+$(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
+       $(call if_changed_dep,cpp_lds_S)
+
+$(obj)/vdso-n32.so.dbg: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
+       $(call if_changed,vdsold)
+
+$(obj)/vdso-n32-image.c: VDSO_NAME := n32
+$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg $(obj)/genvdso FORCE
+       $(call if_changed,genvdso)
+
+obj-y += vdso-n32-image.o
+
+endif
+
+# FIXME: Need install rule for debug.
+# Needs to deal with dependency for generation of dbg by cmd_genvdso...
diff --git a/arch/mips/vdso/elf.S b/arch/mips/vdso/elf.S
new file mode 100644 (file)
index 0000000..be37bbb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <linux/elfnote.h>
+#include <linux/version.h>
+
+ELFNOTE_START(Linux, 0, "a")
+       .long LINUX_VERSION_CODE
+ELFNOTE_END
+
+/*
+ * The .MIPS.abiflags section must be defined with the FP ABI flags set
+ * to 'any' to be able to link with both old and new libraries.
+ * Newer toolchains are capable of automatically generating this, but we want
+ * to work with older toolchains as well. Therefore, we define the contents of
+ * this section here (under different names), and then genvdso will patch
+ * it to have the correct name and type.
+ *
+ * We base the .MIPS.abiflags section on preprocessor definitions rather than
+ * CONFIG_* because we need to match the particular ABI we are building the
+ * VDSO for.
+ *
+ * See https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
+ * for the .MIPS.abiflags section description.
+ */
+
+       .section .mips_abiflags, "a"
+       .align 3
+__mips_abiflags:
+       .hword  0               /* version */
+       .byte   __mips          /* isa_level */
+
+       /* isa_rev */
+#ifdef __mips_isa_rev
+       .byte   __mips_isa_rev
+#else
+       .byte   0
+#endif
+
+       /* gpr_size */
+#ifdef __mips64
+       .byte   2               /* AFL_REG_64 */
+#else
+       .byte   1               /* AFL_REG_32 */
+#endif
+
+       /* cpr1_size */
+#if (defined(__mips_isa_rev) && __mips_isa_rev >= 6) || defined(__mips64)
+       .byte   2               /* AFL_REG_64 */
+#else
+       .byte   1               /* AFL_REG_32 */
+#endif
+
+       .byte   0               /* cpr2_size (AFL_REG_NONE) */
+       .byte   0               /* fp_abi (Val_GNU_MIPS_ABI_FP_ANY) */
+       .word   0               /* isa_ext */
+       .word   0               /* ases */
+       .word   0               /* flags1 */
+       .word   0               /* flags2 */
diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c
new file mode 100644 (file)
index 0000000..530a36f
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * This tool is used to generate the real VDSO images from the raw image. It
+ * first patches up the MIPS ABI flags and GNU attributes sections defined in
+ * elf.S to have the correct name and type. It then generates a C source file
+ * to be compiled into the kernel containing the VDSO image data and a
+ * mips_vdso_image struct for it, including symbol offsets extracted from the
+ * image.
+ *
+ * We need to be passed both a stripped and unstripped VDSO image. The stripped
+ * image is compiled into the kernel, but we must also patch up the unstripped
+ * image's ABI flags sections so that it can be installed and used for
+ * debugging.
+ */
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <byteswap.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Define these in case the system elf.h is not new enough to have them. */
+#ifndef SHT_GNU_ATTRIBUTES
+# define SHT_GNU_ATTRIBUTES    0x6ffffff5
+#endif
+#ifndef SHT_MIPS_ABIFLAGS
+# define SHT_MIPS_ABIFLAGS     0x7000002a
+#endif
+
+enum {
+       ABI_O32 = (1 << 0),
+       ABI_N32 = (1 << 1),
+       ABI_N64 = (1 << 2),
+
+       ABI_ALL = ABI_O32 | ABI_N32 | ABI_N64,
+};
+
+/* Symbols the kernel requires offsets for. */
+static struct {
+       const char *name;
+       const char *offset_name;
+       unsigned int abis;
+} vdso_symbols[] = {
+       { "__vdso_sigreturn", "off_sigreturn", ABI_O32 },
+       { "__vdso_rt_sigreturn", "off_rt_sigreturn", ABI_ALL },
+       {}
+};
+
+static const char *program_name;
+static const char *vdso_name;
+static unsigned char elf_class;
+static unsigned int elf_abi;
+static bool need_swap;
+static FILE *out_file;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define HOST_ORDER            ELFDATA2LSB
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define HOST_ORDER            ELFDATA2MSB
+#endif
+
+#define BUILD_SWAP(bits)                                               \
+       static uint##bits##_t swap_uint##bits(uint##bits##_t val)       \
+       {                                                               \
+               return need_swap ? bswap_##bits(val) : val;             \
+       }
+
+BUILD_SWAP(16)
+BUILD_SWAP(32)
+BUILD_SWAP(64)
+
+#define __FUNC(name, bits) name##bits
+#define _FUNC(name, bits) __FUNC(name, bits)
+#define FUNC(name) _FUNC(name, ELF_BITS)
+
+#define __ELF(x, bits) Elf##bits##_##x
+#define _ELF(x, bits) __ELF(x, bits)
+#define ELF(x) _ELF(x, ELF_BITS)
+
+/*
+ * Include genvdso.h twice with ELF_BITS defined differently to get functions
+ * for both ELF32 and ELF64.
+ */
+
+#define ELF_BITS 64
+#include "genvdso.h"
+#undef ELF_BITS
+
+#define ELF_BITS 32
+#include "genvdso.h"
+#undef ELF_BITS
+
+static void *map_vdso(const char *path, size_t *_size)
+{
+       int fd;
+       struct stat stat;
+       void *addr;
+       const Elf32_Ehdr *ehdr;
+
+       fd = open(path, O_RDWR);
+       if (fd < 0) {
+               fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
+                       path, strerror(errno));
+               return NULL;
+       }
+
+       if (fstat(fd, &stat) != 0) {
+               fprintf(stderr, "%s: Failed to stat '%s': %s\n", program_name,
+                       path, strerror(errno));
+               return NULL;
+       }
+
+       addr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+                   0);
+       if (addr == MAP_FAILED) {
+               fprintf(stderr, "%s: Failed to map '%s': %s\n", program_name,
+                       path, strerror(errno));
+               return NULL;
+       }
+
+       /* ELF32/64 header formats are the same for the bits we're checking. */
+       ehdr = addr;
+
+       if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
+               fprintf(stderr, "%s: '%s' is not an ELF file\n", program_name,
+                       path);
+               return NULL;
+       }
+
+       elf_class = ehdr->e_ident[EI_CLASS];
+       switch (elf_class) {
+       case ELFCLASS32:
+       case ELFCLASS64:
+               break;
+       default:
+               fprintf(stderr, "%s: '%s' has invalid ELF class\n",
+                       program_name, path);
+               return NULL;
+       }
+
+       switch (ehdr->e_ident[EI_DATA]) {
+       case ELFDATA2LSB:
+       case ELFDATA2MSB:
+               need_swap = ehdr->e_ident[EI_DATA] != HOST_ORDER;
+               break;
+       default:
+               fprintf(stderr, "%s: '%s' has invalid ELF data order\n",
+                       program_name, path);
+               return NULL;
+       }
+
+       if (swap_uint16(ehdr->e_machine) != EM_MIPS) {
+               fprintf(stderr,
+                       "%s: '%s' has invalid ELF machine (expected EM_MIPS)\n",
+                       program_name, path);
+               return NULL;
+       } else if (swap_uint16(ehdr->e_type) != ET_DYN) {
+               fprintf(stderr,
+                       "%s: '%s' has invalid ELF type (expected ET_DYN)\n",
+                       program_name, path);
+               return NULL;
+       }
+
+       *_size = stat.st_size;
+       return addr;
+}
+
+static bool patch_vdso(const char *path, void *vdso)
+{
+       if (elf_class == ELFCLASS64)
+               return patch_vdso64(path, vdso);
+       else
+               return patch_vdso32(path, vdso);
+}
+
+static bool get_symbols(const char *path, void *vdso)
+{
+       if (elf_class == ELFCLASS64)
+               return get_symbols64(path, vdso);
+       else
+               return get_symbols32(path, vdso);
+}
+
+int main(int argc, char **argv)
+{
+       const char *dbg_vdso_path, *vdso_path, *out_path;
+       void *dbg_vdso, *vdso;
+       size_t dbg_vdso_size, vdso_size, i;
+
+       program_name = argv[0];
+
+       if (argc < 4 || argc > 5) {
+               fprintf(stderr,
+                       "Usage: %s <debug VDSO> <stripped VDSO> <output file> [<name>]\n",
+                       program_name);
+               return EXIT_FAILURE;
+       }
+
+       dbg_vdso_path = argv[1];
+       vdso_path = argv[2];
+       out_path = argv[3];
+       vdso_name = (argc > 4) ? argv[4] : "";
+
+       dbg_vdso = map_vdso(dbg_vdso_path, &dbg_vdso_size);
+       if (!dbg_vdso)
+               return EXIT_FAILURE;
+
+       vdso = map_vdso(vdso_path, &vdso_size);
+       if (!vdso)
+               return EXIT_FAILURE;
+
+       /* Patch both the VDSOs' ABI flags sections. */
+       if (!patch_vdso(dbg_vdso_path, dbg_vdso))
+               return EXIT_FAILURE;
+       if (!patch_vdso(vdso_path, vdso))
+               return EXIT_FAILURE;
+
+       if (msync(dbg_vdso, dbg_vdso_size, MS_SYNC) != 0) {
+               fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
+                       dbg_vdso_path, strerror(errno));
+               return EXIT_FAILURE;
+       } else if (msync(vdso, vdso_size, MS_SYNC) != 0) {
+               fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
+                       vdso_path, strerror(errno));
+               return EXIT_FAILURE;
+       }
+
+       out_file = fopen(out_path, "w");
+       if (!out_file) {
+               fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
+                       out_path, strerror(errno));
+               return EXIT_FAILURE;
+       }
+
+       fprintf(out_file, "/* Automatically generated - do not edit */\n");
+       fprintf(out_file, "#include <linux/linkage.h>\n");
+       fprintf(out_file, "#include <linux/mm.h>\n");
+       fprintf(out_file, "#include <asm/vdso.h>\n");
+
+       /* Write out the stripped VDSO data. */
+       fprintf(out_file,
+               "static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t",
+               vdso_size);
+       for (i = 0; i < vdso_size; i++) {
+               if (!(i % 10))
+                       fprintf(out_file, "\n\t");
+               fprintf(out_file, "0x%02x, ", ((unsigned char *)vdso)[i]);
+       }
+       fprintf(out_file, "\n};\n");
+
+       /* Preallocate a page array. */
+       fprintf(out_file,
+               "static struct page *vdso_pages[PAGE_ALIGN(%zu) / PAGE_SIZE];\n",
+               vdso_size);
+
+       fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n",
+               (vdso_name[0]) ? "_" : "", vdso_name);
+       fprintf(out_file, "\t.data = vdso_data,\n");
+       fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size);
+       fprintf(out_file, "\t.mapping = {\n");
+       fprintf(out_file, "\t\t.name = \"[vdso]\",\n");
+       fprintf(out_file, "\t\t.pages = vdso_pages,\n");
+       fprintf(out_file, "\t},\n");
+
+       /* Calculate and write symbol offsets to <output file> */
+       if (!get_symbols(dbg_vdso_path, dbg_vdso)) {
+               unlink(out_path);
+               return EXIT_FAILURE;
+       }
+
+       fprintf(out_file, "};\n");
+
+       return EXIT_SUCCESS;
+}
diff --git a/arch/mips/vdso/genvdso.h b/arch/mips/vdso/genvdso.h
new file mode 100644 (file)
index 0000000..9433472
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+static inline bool FUNC(patch_vdso)(const char *path, void *vdso)
+{
+       const ELF(Ehdr) *ehdr = vdso;
+       void *shdrs;
+       ELF(Shdr) *shdr;
+       char *shstrtab, *name;
+       uint16_t sh_count, sh_entsize, i;
+       unsigned int local_gotno, symtabno, gotsym;
+       ELF(Dyn) *dyn = NULL;
+
+       shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
+       sh_count = swap_uint16(ehdr->e_shnum);
+       sh_entsize = swap_uint16(ehdr->e_shentsize);
+
+       shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx));
+       shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+
+       for (i = 0; i < sh_count; i++) {
+               shdr = shdrs + (i * sh_entsize);
+               name = shstrtab + swap_uint32(shdr->sh_name);
+
+               /*
+                * Ensure there are no relocation sections - ld.so does not
+                * relocate the VDSO so if there are relocations things will
+                * break.
+                */
+               switch (swap_uint32(shdr->sh_type)) {
+               case SHT_REL:
+               case SHT_RELA:
+                       fprintf(stderr,
+                               "%s: '%s' contains relocation sections\n",
+                               program_name, path);
+                       return false;
+               case SHT_DYNAMIC:
+                       dyn = vdso + FUNC(swap_uint)(shdr->sh_offset);
+                       break;
+               }
+
+               /* Check for existing sections. */
+               if (strcmp(name, ".MIPS.abiflags") == 0) {
+                       fprintf(stderr,
+                               "%s: '%s' already contains a '.MIPS.abiflags' section\n",
+                               program_name, path);
+                       return false;
+               }
+
+               if (strcmp(name, ".mips_abiflags") == 0) {
+                       strcpy(name, ".MIPS.abiflags");
+                       shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS);
+                       shdr->sh_entsize = shdr->sh_size;
+               }
+       }
+
+       /*
+        * Ensure the GOT has no entries other than the standard 2, for the same
+        * reason we check that there's no relocation sections above.
+        * The standard two entries are:
+        * - Lazy resolver
+        * - Module pointer
+        */
+       if (dyn) {
+               local_gotno = symtabno = gotsym = 0;
+
+               while (FUNC(swap_uint)(dyn->d_tag) != DT_NULL) {
+                       switch (FUNC(swap_uint)(dyn->d_tag)) {
+                       /*
+                        * This member holds the number of local GOT entries.
+                        */
+                       case DT_MIPS_LOCAL_GOTNO:
+                               local_gotno = FUNC(swap_uint)(dyn->d_un.d_val);
+                               break;
+                       /*
+                        * This member holds the number of entries in the
+                        * .dynsym section.
+                        */
+                       case DT_MIPS_SYMTABNO:
+                               symtabno = FUNC(swap_uint)(dyn->d_un.d_val);
+                               break;
+                       /*
+                        * This member holds the index of the first dynamic
+                        * symbol table entry that corresponds to an entry in
+                        * the GOT.
+                        */
+                       case DT_MIPS_GOTSYM:
+                               gotsym = FUNC(swap_uint)(dyn->d_un.d_val);
+                               break;
+                       }
+
+                       dyn++;
+               }
+
+               if (local_gotno > 2 || symtabno - gotsym) {
+                       fprintf(stderr,
+                               "%s: '%s' contains unexpected GOT entries\n",
+                               program_name, path);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static inline bool FUNC(get_symbols)(const char *path, void *vdso)
+{
+       const ELF(Ehdr) *ehdr = vdso;
+       void *shdrs, *symtab;
+       ELF(Shdr) *shdr;
+       const ELF(Sym) *sym;
+       char *strtab, *name;
+       uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j;
+       uint64_t offset;
+       uint32_t flags;
+
+       shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
+       sh_count = swap_uint16(ehdr->e_shnum);
+       sh_entsize = swap_uint16(ehdr->e_shentsize);
+
+       for (i = 0; i < sh_count; i++) {
+               shdr = shdrs + (i * sh_entsize);
+
+               if (swap_uint32(shdr->sh_type) == SHT_SYMTAB)
+                       break;
+       }
+
+       if (i == sh_count) {
+               fprintf(stderr, "%s: '%s' has no symbol table\n", program_name,
+                       path);
+               return false;
+       }
+
+       /* Get flags */
+       flags = swap_uint32(ehdr->e_flags);
+       if (elf_class == ELFCLASS64)
+               elf_abi = ABI_N64;
+       else if (flags & EF_MIPS_ABI2)
+               elf_abi = ABI_N32;
+       else
+               elf_abi = ABI_O32;
+
+       /* Get symbol table. */
+       symtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+       st_entsize = FUNC(swap_uint)(shdr->sh_entsize);
+       st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize;
+
+       /* Get string table. */
+       shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize);
+       strtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+
+       /* Write offsets for symbols needed by the kernel. */
+       for (i = 0; vdso_symbols[i].name; i++) {
+               if (!(vdso_symbols[i].abis & elf_abi))
+                       continue;
+
+               for (j = 0; j < st_count; j++) {
+                       sym = symtab + (j * st_entsize);
+                       name = strtab + swap_uint32(sym->st_name);
+
+                       if (!strcmp(name, vdso_symbols[i].name)) {
+                               offset = FUNC(swap_uint)(sym->st_value);
+
+                               fprintf(out_file,
+                                       "\t.%s = 0x%" PRIx64 ",\n",
+                                       vdso_symbols[i].offset_name, offset);
+                               break;
+                       }
+               }
+
+               if (j == st_count) {
+                       fprintf(stderr,
+                               "%s: '%s' is missing required symbol '%s'\n",
+                               program_name, path, vdso_symbols[i].name);
+                       return false;
+               }
+       }
+
+       return true;
+}
diff --git a/arch/mips/vdso/gettimeofday.c b/arch/mips/vdso/gettimeofday.c
new file mode 100644 (file)
index 0000000..ce89c9e
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <linux/compiler.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/time.h>
+
+#include <asm/clocksource.h>
+#include <asm/io.h>
+#include <asm/mips-cm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+static __always_inline int do_realtime_coarse(struct timespec *ts,
+                                             const union mips_vdso_data *data)
+{
+       u32 start_seq;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               ts->tv_sec = data->xtime_sec;
+               ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+       } while (vdso_data_read_retry(data, start_seq));
+
+       return 0;
+}
+
+static __always_inline int do_monotonic_coarse(struct timespec *ts,
+                                              const union mips_vdso_data *data)
+{
+       u32 start_seq;
+       u32 to_mono_sec;
+       u32 to_mono_nsec;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               ts->tv_sec = data->xtime_sec;
+               ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+
+               to_mono_sec = data->wall_to_mono_sec;
+               to_mono_nsec = data->wall_to_mono_nsec;
+       } while (vdso_data_read_retry(data, start_seq));
+
+       ts->tv_sec += to_mono_sec;
+       timespec_add_ns(ts, to_mono_nsec);
+
+       return 0;
+}
+
+#ifdef CONFIG_CSRC_R4K
+
+static __always_inline u64 read_r4k_count(void)
+{
+       unsigned int count;
+
+       __asm__ __volatile__(
+       "       .set push\n"
+       "       .set mips32r2\n"
+       "       rdhwr   %0, $2\n"
+       "       .set pop\n"
+       : "=r" (count));
+
+       return count;
+}
+
+#endif
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static __always_inline u64 read_gic_count(const union mips_vdso_data *data)
+{
+       void __iomem *gic = get_gic(data);
+       u32 hi, hi2, lo;
+
+       do {
+               hi = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+               lo = __raw_readl(gic + GIC_UMV_SH_COUNTER_31_00_OFS);
+               hi2 = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+       } while (hi2 != hi);
+
+       return (((u64)hi) << 32) + lo;
+}
+
+#endif
+
+static __always_inline u64 get_ns(const union mips_vdso_data *data)
+{
+       u64 cycle_now, delta, nsec;
+
+       switch (data->clock_mode) {
+#ifdef CONFIG_CSRC_R4K
+       case VDSO_CLOCK_R4K:
+               cycle_now = read_r4k_count();
+               break;
+#endif
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+       case VDSO_CLOCK_GIC:
+               cycle_now = read_gic_count(data);
+               break;
+#endif
+       default:
+               return 0;
+       }
+
+       delta = (cycle_now - data->cs_cycle_last) & data->cs_mask;
+
+       nsec = (delta * data->cs_mult) + data->xtime_nsec;
+       nsec >>= data->cs_shift;
+
+       return nsec;
+}
+
+static __always_inline int do_realtime(struct timespec *ts,
+                                      const union mips_vdso_data *data)
+{
+       u32 start_seq;
+       u64 ns;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               if (data->clock_mode == VDSO_CLOCK_NONE)
+                       return -ENOSYS;
+
+               ts->tv_sec = data->xtime_sec;
+               ns = get_ns(data);
+       } while (vdso_data_read_retry(data, start_seq));
+
+       ts->tv_nsec = 0;
+       timespec_add_ns(ts, ns);
+
+       return 0;
+}
+
+static __always_inline int do_monotonic(struct timespec *ts,
+                                       const union mips_vdso_data *data)
+{
+       u32 start_seq;
+       u64 ns;
+       u32 to_mono_sec;
+       u32 to_mono_nsec;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               if (data->clock_mode == VDSO_CLOCK_NONE)
+                       return -ENOSYS;
+
+               ts->tv_sec = data->xtime_sec;
+               ns = get_ns(data);
+
+               to_mono_sec = data->wall_to_mono_sec;
+               to_mono_nsec = data->wall_to_mono_nsec;
+       } while (vdso_data_read_retry(data, start_seq));
+
+       ts->tv_sec += to_mono_sec;
+       ts->tv_nsec = 0;
+       timespec_add_ns(ts, ns + to_mono_nsec);
+
+       return 0;
+}
+
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+       const union mips_vdso_data *data = get_vdso_data();
+       struct timespec ts;
+       int ret;
+
+       ret = do_realtime(&ts, data);
+       if (ret)
+               return ret;
+
+       if (tv) {
+               tv->tv_sec = ts.tv_sec;
+               tv->tv_usec = ts.tv_nsec / 1000;
+       }
+
+       if (tz) {
+               tz->tz_minuteswest = data->tz_minuteswest;
+               tz->tz_dsttime = data->tz_dsttime;
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
+int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
+{
+       const union mips_vdso_data *data = get_vdso_data();
+       int ret;
+
+       switch (clkid) {
+       case CLOCK_REALTIME_COARSE:
+               ret = do_realtime_coarse(ts, data);
+               break;
+       case CLOCK_MONOTONIC_COARSE:
+               ret = do_monotonic_coarse(ts, data);
+               break;
+       case CLOCK_REALTIME:
+               ret = do_realtime(ts, data);
+               break;
+       case CLOCK_MONOTONIC:
+               ret = do_monotonic(ts, data);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       /* If we return -ENOSYS libc should fall back to a syscall. */
+       return ret;
+}
diff --git a/arch/mips/vdso/sigreturn.S b/arch/mips/vdso/sigreturn.S
new file mode 100644 (file)
index 0000000..715bf59
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <uapi/asm/unistd.h>
+
+#include <asm/regdef.h>
+#include <asm/asm.h>
+
+       .section        .text
+       .cfi_sections   .debug_frame
+
+LEAF(__vdso_rt_sigreturn)
+       .cfi_startproc
+       .frame  sp, 0, ra
+       .mask   0x00000000, 0
+       .fmask  0x00000000, 0
+       .cfi_signal_frame
+
+       li      v0, __NR_rt_sigreturn
+       syscall
+
+       .cfi_endproc
+       END(__vdso_rt_sigreturn)
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+LEAF(__vdso_sigreturn)
+       .cfi_startproc
+       .frame  sp, 0, ra
+       .mask   0x00000000, 0
+       .fmask  0x00000000, 0
+       .cfi_signal_frame
+
+       li      v0, __NR_sigreturn
+       syscall
+
+       .cfi_endproc
+       END(__vdso_sigreturn)
+
+#endif
diff --git a/arch/mips/vdso/vdso.h b/arch/mips/vdso/vdso.h
new file mode 100644 (file)
index 0000000..cfb1be4
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/sgidefs.h>
+
+#if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT)
+
+/* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */
+#undef CONFIG_64BIT
+#define CONFIG_32BIT 1
+#ifndef __ASSEMBLY__
+#include <asm-generic/atomic64.h>
+#endif
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <asm/asm.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+static inline unsigned long get_vdso_base(void)
+{
+       unsigned long addr;
+
+       /*
+        * We can't use cpu_has_mips_r6 since it needs the cpu_data[]
+        * kernel symbol.
+        */
+#ifdef CONFIG_CPU_MIPSR6
+       /*
+        * lapc <symbol> is an alias to addiupc reg, <symbol> - .
+        *
+        * We can't use addiupc because there is no label-label
+        * support for the addiupc reloc
+        */
+       __asm__("lapc   %0, _start                      \n"
+               : "=r" (addr) : :);
+#else
+       /*
+        * Get the base load address of the VDSO. We have to avoid generating
+        * relocations and references to the GOT because ld.so does not peform
+        * relocations on the VDSO. We use the current offset from the VDSO base
+        * and perform a PC-relative branch which gives the absolute address in
+        * ra, and take the difference. The assembler chokes on
+        * "li %0, _start - .", so embed the offset as a word and branch over
+        * it.
+        *
+        */
+
+       __asm__(
+       "       .set push                               \n"
+       "       .set noreorder                          \n"
+       "       bal     1f                              \n"
+       "        nop                                    \n"
+       "       .word   _start - .                      \n"
+       "1:     lw      %0, 0($31)                      \n"
+       "       " STR(PTR_ADDU) " %0, $31, %0           \n"
+       "       .set pop                                \n"
+       : "=r" (addr)
+       :
+       : "$31");
+#endif /* CONFIG_CPU_MIPSR6 */
+
+       return addr;
+}
+
+static inline const union mips_vdso_data *get_vdso_data(void)
+{
+       return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE);
+}
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static inline void __iomem *get_gic(const union mips_vdso_data *data)
+{
+       return (void __iomem *)data - PAGE_SIZE;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
+#endif /* __ASSEMBLY__ */
diff --git a/arch/mips/vdso/vdso.lds.S b/arch/mips/vdso/vdso.lds.S
new file mode 100644 (file)
index 0000000..8df7dd5
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/sgidefs.h>
+
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips")
+#elif _MIPS_SIM == _MIPS_SIM_NABI32
+OUTPUT_FORMAT("elf32-ntradlittlemips", "elf32-ntradbigmips", "elf32-ntradlittlemips")
+#else
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips")
+#endif
+
+OUTPUT_ARCH(mips)
+
+SECTIONS
+{
+       PROVIDE(_start = .);
+       . = SIZEOF_HEADERS;
+
+       /*
+        * In order to retain compatibility with older toolchains we provide the
+        * ABI flags section ourself. Newer assemblers will automatically
+        * generate .MIPS.abiflags sections so we discard such input sections,
+        * and then manually define our own section here. genvdso will patch
+        * this section to have the correct name/type.
+        */
+       .mips_abiflags  : { *(.mips_abiflags) }         :text :abiflags
+
+       .reginfo        : { *(.reginfo) }               :text :reginfo
+
+       .hash           : { *(.hash) }                  :text
+       .gnu.hash       : { *(.gnu.hash) }
+       .dynsym         : { *(.dynsym) }
+       .dynstr         : { *(.dynstr) }
+       .gnu.version    : { *(.gnu.version) }
+       .gnu.version_d  : { *(.gnu.version_d) }
+       .gnu.version_r  : { *(.gnu.version_r) }
+
+       .note           : { *(.note.*) }                :text :note
+
+       .text           : { *(.text*) }                 :text
+       PROVIDE (__etext = .);
+       PROVIDE (_etext = .);
+       PROVIDE (etext = .);
+
+       .eh_frame_hdr   : { *(.eh_frame_hdr) }          :text :eh_frame_hdr
+       .eh_frame       : { KEEP (*(.eh_frame)) }       :text
+
+       .dynamic        : { *(.dynamic) }               :text :dynamic
+
+       .rodata         : { *(.rodata*) }               :text
+
+       _end = .;
+       PROVIDE(end = .);
+
+       /DISCARD/       : {
+               *(.MIPS.abiflags)
+               *(.gnu.attributes)
+               *(.note.GNU-stack)
+               *(.data .data.* .gnu.linkonce.d.* .sdata*)
+               *(.bss .sbss .dynbss .dynsbss)
+       }
+}
+
+PHDRS
+{
+       /*
+        * Provide a PT_MIPS_ABIFLAGS header to assign the ABI flags section
+        * to. We can specify the header type directly here so no modification
+        * is needed later on.
+        */
+       abiflags        0x70000003;
+
+       /*
+        * The ABI flags header must exist directly after the PT_INTERP header,
+        * so we must explicitly place the PT_MIPS_REGINFO header after it to
+        * stop the linker putting one in at the start.
+        */
+       reginfo         0x70000000;
+
+       text            PT_LOAD         FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+       dynamic         PT_DYNAMIC      FLAGS(4);               /* PF_R */
+       note            PT_NOTE         FLAGS(4);               /* PF_R */
+       eh_frame_hdr    PT_GNU_EH_FRAME;
+}
+
+VERSION
+{
+       LINUX_2.6 {
+#ifndef DISABLE_MIPS_VDSO
+       global:
+               __vdso_clock_gettime;
+               __vdso_gettimeofday;
+#endif
+       local: *;
+       };
+}
diff --git a/arch/mips/xilfpga/Kconfig b/arch/mips/xilfpga/Kconfig
new file mode 100644 (file)
index 0000000..42a030a
--- /dev/null
@@ -0,0 +1,9 @@
+choice
+       prompt "Machine type"
+       depends on MACH_XILFPGA
+       default XILFPGA_NEXYS4DDR
+
+config XILFPGA_NEXYS4DDR
+       bool "Nexys4DDR by Digilent"
+
+endchoice
diff --git a/arch/mips/xilfpga/Makefile b/arch/mips/xilfpga/Makefile
new file mode 100644 (file)
index 0000000..a4deec6
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Xilfpga
+#
+
+obj-y +=       init.o
+obj-y +=       intc.o
+obj-y +=       time.o
diff --git a/arch/mips/xilfpga/Platform b/arch/mips/xilfpga/Platform
new file mode 100644 (file)
index 0000000..ed375af
--- /dev/null
@@ -0,0 +1,3 @@
+platform-$(CONFIG_MACH_XILFPGA) += xilfpga/
+cflags-$(CONFIG_MACH_XILFPGA) += -I$(srctree)/arch/mips/include/asm/mach-xilfpga
+load-$(CONFIG_MACH_XILFPGA) += 0xffffffff80100000
diff --git a/arch/mips/xilfpga/init.c b/arch/mips/xilfpga/init.c
new file mode 100644 (file)
index 0000000..ce2aee2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Xilfpga platform setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+#include <asm/prom.h>
+
+#define XILFPGA_UART_BASE      0xb0401000
+
+const char *get_system_type(void)
+{
+       return "MIPSfpga";
+}
+
+void __init plat_mem_setup(void)
+{
+       __dt_setup_arch(__dtb_start);
+       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+}
+
+void __init prom_init(void)
+{
+       setup_8250_early_printk_port(XILFPGA_UART_BASE, 2, 50000);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init device_tree_init(void)
+{
+       if (!initial_boot_params)
+               return;
+
+       unflatten_and_copy_device_tree();
+}
+
+static int __init plat_of_setup(void)
+{
+       if (!of_have_populated_dt())
+               panic("Device tree not present");
+
+       if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
+               panic("Failed to populate DT");
+
+       return 0;
+}
+arch_initcall(plat_of_setup);
diff --git a/arch/mips/xilfpga/intc.c b/arch/mips/xilfpga/intc.c
new file mode 100644 (file)
index 0000000..c4d1a71
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Xilfpga interrupt controller setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+#include <asm/irq_cpu.h>
+
+static struct of_device_id of_irq_ids[] __initdata = {
+       { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
+       {},
+};
+
+void __init arch_init_irq(void)
+{
+       of_irq_init(of_irq_ids);
+}
diff --git a/arch/mips/xilfpga/time.c b/arch/mips/xilfpga/time.c
new file mode 100644 (file)
index 0000000..a1c0fc8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Xilfpga clocksource/timer setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/of.h>
+
+#include <asm/time.h>
+
+void __init plat_time_init(void)
+{
+       struct device_node *np;
+       struct clk *clk;
+
+       of_clk_init(NULL);
+       clocksource_of_init();
+
+       np = of_get_cpu_node(0, NULL);
+       if (!np) {
+               pr_err("Failed to get CPU node\n");
+               return;
+       }
+
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk)) {
+               pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
+               return;
+       }
+
+       mips_hpt_frequency = clk_get_rate(clk) / 2;
+       clk_put(clk);
+}
index 02a1945e5093f7c3c9efa83ee1af822ecc2b127d..89d3e4d7900c51f384f3b90200c1fecb2bab013f 100644 (file)
@@ -140,9 +140,10 @@ static cycle_t gic_hpt_read(struct clocksource *cs)
 }
 
 static struct clocksource gic_clocksource = {
-       .name   = "GIC",
-       .read   = gic_hpt_read,
-       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+       .name           = "GIC",
+       .read           = gic_hpt_read,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .archdata       = { .vdso_clock_mode = VDSO_CLOCK_GIC },
 };
 
 static void __init __gic_clocksource_init(void)
index aeaa061f0dbfd3694d8a9f890822eba266e2e4e0..9e17ef27a183d6f62a6f2860ee416674a314465c 100644 (file)
@@ -29,6 +29,7 @@ struct gic_pcpu_mask {
        DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
 };
 
+static unsigned long __gic_base_addr;
 static void __iomem *gic_base;
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
@@ -301,6 +302,17 @@ int gic_get_c0_fdc_int(void)
                                  GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC));
 }
 
+int gic_get_usm_range(struct resource *gic_usm_res)
+{
+       if (!gic_present)
+               return -1;
+
+       gic_usm_res->start = __gic_base_addr + USM_VISIBLE_SECTION_OFS;
+       gic_usm_res->end = gic_usm_res->start + (USM_VISIBLE_SECTION_SIZE - 1);
+
+       return 0;
+}
+
 static void gic_handle_shared_int(bool chained)
 {
        unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
@@ -798,6 +810,8 @@ static void __init __gic_init(unsigned long gic_base_addr,
 {
        unsigned int gicconfig;
 
+       __gic_base_addr = gic_base_addr;
+
        gic_base = ioremap_nocache(gic_base_addr, gic_addrspace_size);
 
        gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
index 4e6861605050489e4ca3df78d94520993805c0ce..ce824db48d64c7fd29fc41babb0df6923da0774f 100644 (file)
@@ -9,6 +9,7 @@
 #define __LINUX_IRQCHIP_MIPS_GIC_H
 
 #include <linux/clocksource.h>
+#include <linux/ioport.h>
 
 #define GIC_MAX_INTRS                  256
 
 #define GIC_SHARED_TO_HWIRQ(x) (GIC_SHARED_HWIRQ_BASE + (x))
 #define GIC_HWIRQ_TO_SHARED(x) ((x) - GIC_SHARED_HWIRQ_BASE)
 
+#ifdef CONFIG_MIPS_GIC
+
 extern unsigned int gic_present;
 
 extern void gic_init(unsigned long gic_base_addr,
@@ -264,4 +267,18 @@ extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern int gic_get_c0_compare_int(void);
 extern int gic_get_c0_perfcount_int(void);
 extern int gic_get_c0_fdc_int(void);
+extern int gic_get_usm_range(struct resource *gic_usm_res);
+
+#else /* CONFIG_MIPS_GIC */
+
+#define gic_present    0
+
+static inline int gic_get_usm_range(struct resource *gic_usm_res)
+{
+       /* Shouldn't be called. */
+       return -1;
+}
+
+#endif /* CONFIG_MIPS_GIC */
+
 #endif /* __LINUX_IRQCHIP_MIPS_GIC_H */