Merge tag 'mips_4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/mips
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 7 Feb 2018 19:22:44 +0000 (11:22 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 7 Feb 2018 19:22:44 +0000 (11:22 -0800)
Pull MIPS updates from James Hogan:
 "These are the main MIPS changes for 4.16.

  Rough overview:

   (1) Basic support for the Ingenic JZ4770 based GCW Zero open-source
       handheld video game console

   (2) Support for the Ranchu board (used by Android emulator)

   (3) Various cleanups and misc improvements

  More detailed summary:

  Fixes:
   - Fix generic platform's USB_*HCI_BIG_ENDIAN selects (4.9)
   - Fix vmlinuz default build when ZBOOT selected
   - Fix clean up of vmlinuz targets
   - Fix command line duplication (in preparation for Ingenic JZ4770)

  Miscellaneous:
   - Allow Processor ID reads to be to be optimised away by the compiler
     (improves performance when running in guest)
   - Push ARCH_MIGHT_HAVE_PC_SERIO/PARPORT down to platform level to
     disable on generic platform with Ranchu board support
   - Add helpers for assembler macro instructions for older assemblers
   - Use assembler macro instructions to support VZ, XPA & MSA
     operations on older assemblers, removing C wrapper duplication
   - Various improvements to VZ & XPA assembly wrappers
   - Add drivers/platform/mips/ to MIPS MAINTAINERS entry

  Minor cleanups:
   - Misc FPU emulation cleanups (removal of unnecessary include, moving
     macros to common header, checkpatch and sparse fixes)
   - Remove duplicate assignment of core in play_dead()
   - Remove duplication in watchpoint handling
   - Remove mips_dma_mapping_error() stub
   - Use NULL instead of 0 in prepare_ftrace_return()
   - Use proper kernel-doc Return keyword for
     __compute_return_epc_for_insn()
   - Remove duplicate semicolon in csum_fold()

  Platform support:

  Broadcom:
   - Enable ZBOOT on BCM47xx

  Generic platform:
   - Add Ranchu board support, used by Android emulator
   - Fix machine compatible string matching for Ranchu
   - Support GIC in EIC mode

  Ingenic platforms:
   - Add DT, defconfig and other support for JZ4770 SoC and GCW Zero
   - Support dynamnic machine types (i.e. JZ4740 / JZ4770 / JZ4780)
   - Add Ingenic JZ4770 CGU clocks
   - General Ingenic clk changes to prepare for JZ4770 SoC support
   - Use common command line handling code
   - Add DT vendor prefix to GCW (Game Consoles Worldwide)

  Loongson:
   - Add MAINTAINERS entry for Loongson2 and Loongson3 platforms
   - Drop 32-bit support for Loongson 2E/2F devices
   - Fix build failures due to multiple use of 'MEM_RESERVED'"

* tag 'mips_4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/mips: (53 commits)
  MIPS: Malta: Sanitize mouse and keyboard configuration.
  MIPS: Update defconfigs after previous patch.
  MIPS: Push ARCH_MIGHT_HAVE_PC_SERIO down to platform level
  MIPS: Push ARCH_MIGHT_HAVE_PC_PARPORT down to platform level
  MIPS: SMP-CPS: Remove duplicate assignment of core in play_dead
  MIPS: Generic: Support GIC in EIC mode
  MIPS: generic: Fix Makefile alignment
  MIPS: generic: Fix ranchu_of_match[] termination
  MIPS: generic: Fix machine compatible matching
  MIPS: Loongson fix name confict - MEM_RESERVED
  MIPS: bcm47xx: enable ZBOOT support
  MIPS: Fix trailing semicolon
  MIPS: Watch: Avoid duplication of bits in mips_read_watch_registers
  MIPS: Watch: Avoid duplication of bits in mips_install_watch_registers.
  MIPS: MSA: Update helpers to use new asm macros
  MIPS: XPA: Standardise readx/writex accessors
  MIPS: XPA: Allow use of $0 (zero) to MTHC0
  MIPS: XPA: Use XPA instructions in assembly
  MIPS: VZ: Pass GC0 register names in $n format
  MIPS: VZ: Update helpers to use new asm macros
  ...

77 files changed:
Documentation/devicetree/bindings/vendor-prefixes.txt
MAINTAINERS
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/bcm47xx/Platform
arch/mips/boot/compressed/Makefile
arch/mips/boot/dts/ingenic/Makefile
arch/mips/boot/dts/ingenic/gcw0.dts [new file with mode: 0644]
arch/mips/boot/dts/ingenic/jz4770.dtsi [new file with mode: 0644]
arch/mips/configs/bigsur_defconfig
arch/mips/configs/gcw0_defconfig [new file with mode: 0644]
arch/mips/configs/generic/board-ranchu.config [new file with mode: 0644]
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip32_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_defconfig
arch/mips/configs/maltasmvp_eva_defconfig
arch/mips/configs/maltaup_defconfig
arch/mips/configs/maltaup_xpa_defconfig
arch/mips/configs/nlm_xlp_defconfig
arch/mips/configs/nlm_xlr_defconfig
arch/mips/configs/pnx8335_stb225_defconfig
arch/mips/configs/sb1250_swarm_defconfig
arch/mips/generic/Kconfig
arch/mips/generic/Makefile
arch/mips/generic/board-ranchu.c [new file with mode: 0644]
arch/mips/generic/irq.c
arch/mips/include/asm/bootinfo.h
arch/mips/include/asm/checksum.h
arch/mips/include/asm/mach-loongson64/boot_param.h
arch/mips/include/asm/machine.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/msa.h
arch/mips/jz4740/Kconfig
arch/mips/jz4740/prom.c
arch/mips/jz4740/setup.c
arch/mips/jz4740/time.c
arch/mips/kernel/branch.c
arch/mips/kernel/ftrace.c
arch/mips/kernel/setup.c
arch/mips/kernel/smp-cps.c
arch/mips/kernel/watch.c
arch/mips/loongson64/Kconfig
arch/mips/loongson64/common/mem.c
arch/mips/loongson64/loongson-3/numa.c
arch/mips/math-emu/cp1emu.c
arch/mips/math-emu/dp_add.c
arch/mips/math-emu/dp_div.c
arch/mips/math-emu/dp_fmax.c
arch/mips/math-emu/dp_fmin.c
arch/mips/math-emu/dp_maddf.c
arch/mips/math-emu/dp_mul.c
arch/mips/math-emu/dp_sqrt.c
arch/mips/math-emu/dp_sub.c
arch/mips/math-emu/ieee754dp.h
arch/mips/math-emu/sp_add.c
arch/mips/math-emu/sp_div.c
arch/mips/math-emu/sp_fdp.c
arch/mips/math-emu/sp_fmax.c
arch/mips/math-emu/sp_fmin.c
arch/mips/math-emu/sp_maddf.c
arch/mips/math-emu/sp_mul.c
arch/mips/math-emu/sp_sqrt.c
arch/mips/math-emu/sp_sub.c
arch/mips/math-emu/sp_tlong.c
arch/mips/mm/dma-default.c
arch/mips/mm/sc-mips.c
drivers/clk/ingenic/Makefile
drivers/clk/ingenic/cgu.c
drivers/clk/ingenic/cgu.h
drivers/clk/ingenic/jz4770-cgu.c [new file with mode: 0644]
drivers/clk/ingenic/jz4780-cgu.c
include/dt-bindings/clock/jz4770-cgu.h [new file with mode: 0644]

index b1fa64a1d4d0f6a9a20945cb7be0dc9e7e936fd8..ae850d6c0ad3779f2e9fa0f1ba60f49b5b864e8a 100644 (file)
@@ -125,6 +125,7 @@ focaltech   FocalTech Systems Co.,Ltd
 friendlyarm    Guangzhou FriendlyARM Computer Tech Co., Ltd
 fsl    Freescale Semiconductor
 fujitsu        Fujitsu Ltd.
+gcw Game Consoles Worldwide
 ge     General Electric Company
 geekbuying     GeekBuying
 gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
index 7653656e64b29a29970acd78ab7dca0b81e8165e..ba3842a9e73ef3392426ecfbbd04ec3decc0fa8a 100644 (file)
@@ -9188,6 +9188,7 @@ S:        Supported
 F:     Documentation/devicetree/bindings/mips/
 F:     Documentation/mips/
 F:     arch/mips/
+F:     drivers/platform/mips/
 
 MIPS BOSTON DEVELOPMENT BOARD
 M:     Paul Burton <paul.burton@mips.com>
@@ -9215,6 +9216,25 @@ F:       arch/mips/include/asm/mach-loongson32/
 F:     drivers/*/*loongson1*
 F:     drivers/*/*/*loongson1*
 
+MIPS/LOONGSON2 ARCHITECTURE
+M:     Jiaxun Yang <jiaxun.yang@flygoat.com>
+L:     linux-mips@linux-mips.org
+S:     Maintained
+F:     arch/mips/loongson64/*{2e/2f}*
+F:     arch/mips/include/asm/mach-loongson64/
+F:     drivers/*/*loongson2*
+F:     drivers/*/*/*loongson2*
+
+MIPS/LOONGSON3 ARCHITECTURE
+M:     Huacai Chen <chenhc@lemote.com>
+L:     linux-mips@linux-mips.org
+S:     Maintained
+F:     arch/mips/loongson64/
+F:     arch/mips/include/asm/mach-loongson64/
+F:     drivers/platform/mips/cpu_hwmon.c
+F:     drivers/*/*loongson3*
+F:     drivers/*/*/*loongson3*
+
 MIPS RINT INSTRUCTION EMULATION
 M:     Aleksandar Markovic <aleksandar.markovic@mips.com>
 L:     linux-mips@linux-mips.org
@@ -11586,6 +11606,13 @@ S:     Maintained
 F:     Documentation/blockdev/ramdisk.txt
 F:     drivers/block/brd.c
 
+RANCHU VIRTUAL BOARD FOR MIPS
+M:     Miodrag Dinic <miodrag.dinic@mips.com>
+L:     linux-mips@linux-mips.org
+S:     Supported
+F:     arch/mips/generic/board-ranchu.c
+F:     arch/mips/configs/generic/board-ranchu.config
+
 RANDOM NUMBER DRIVER
 M:     "Theodore Ts'o" <tytso@mit.edu>
 S:     Maintained
index ab98569994f0f61cf61d62b6b8c2757f9533c5e3..449397c60b56eae1fdaef29423588c97ee8f0d09 100644 (file)
@@ -7,8 +7,6 @@ config MIPS
        select ARCH_DISCARD_MEMBLOCK
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
-       select ARCH_MIGHT_HAVE_PC_PARPORT
-       select ARCH_MIGHT_HAVE_PC_SERIO
        select ARCH_SUPPORTS_UPROBES
        select ARCH_USE_BUILTIN_BSWAP
        select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
@@ -119,12 +117,12 @@ config MIPS_GENERIC
        select SYS_SUPPORTS_MULTITHREADING
        select SYS_SUPPORTS_RELOCATABLE
        select SYS_SUPPORTS_SMARTMIPS
-       select USB_EHCI_BIG_ENDIAN_DESC if BIG_ENDIAN
-       select USB_EHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN
-       select USB_OHCI_BIG_ENDIAN_DESC if BIG_ENDIAN
-       select USB_OHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN
-       select USB_UHCI_BIG_ENDIAN_DESC if BIG_ENDIAN
-       select USB_UHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN
+       select USB_EHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
+       select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
+       select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
+       select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
+       select USB_UHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
+       select USB_UHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
        select USE_OF
        help
          Select this to build a kernel which aims to support multiple boards,
@@ -253,6 +251,7 @@ config BCM47XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_MIPS16
+       select SYS_SUPPORTS_ZBOOT
        select SYS_HAS_EARLY_PRINTK
        select USE_GENERIC_EARLY_PRINTK_8250
        select GPIOLIB
@@ -341,6 +340,8 @@ config MACH_DECSTATION
 
 config MACH_JAZZ
        bool "Jazz family of machines"
+       select ARCH_MIGHT_HAVE_PC_PARPORT
+       select ARCH_MIGHT_HAVE_PC_SERIO
        select FW_ARC
        select FW_ARC32
        select ARCH_MAY_HAVE_PC_FDC
@@ -476,6 +477,8 @@ config MACH_PISTACHIO
 config MIPS_MALTA
        bool "MIPS Malta board"
        select ARCH_MAY_HAVE_PC_FDC
+       select ARCH_MIGHT_HAVE_PC_PARPORT
+       select ARCH_MIGHT_HAVE_PC_SERIO
        select BOOT_ELF32
        select BOOT_RAW
        select BUILTIN_DTB
@@ -613,6 +616,7 @@ config SGI_IP22
        bool "SGI IP22 (Indy/Indigo2)"
        select FW_ARC
        select FW_ARC32
+       select ARCH_MIGHT_HAVE_PC_SERIO
        select BOOT_ELF32
        select CEVT_R4K
        select CSRC_R4K
@@ -675,6 +679,7 @@ config SGI_IP28
        bool "SGI IP28 (Indigo2 R10k)"
        select FW_ARC
        select FW_ARC64
+       select ARCH_MIGHT_HAVE_PC_SERIO
        select BOOT_ELF64
        select CEVT_R4K
        select CSRC_R4K
@@ -824,6 +829,8 @@ config SNI_RM
        select FW_ARC32 if CPU_LITTLE_ENDIAN
        select FW_SNIPROM if CPU_BIG_ENDIAN
        select ARCH_MAY_HAVE_PC_FDC
+       select ARCH_MIGHT_HAVE_PC_PARPORT
+       select ARCH_MIGHT_HAVE_PC_SERIO
        select BOOT_ELF32
        select CEVT_R4K
        select CSRC_R4K
index 9f6a26d72f9fe66c405b27d62414feaf71e8d2cb..d1ca839c3981e5c7db6d42affe939f2fc0d8dbb0 100644 (file)
@@ -216,6 +216,12 @@ cflags-$(toolchain-msa)                    += -DTOOLCHAIN_SUPPORTS_MSA
 endif
 toolchain-virt                         := $(call cc-option-yn,$(mips-cflags) -mvirt)
 cflags-$(toolchain-virt)               += -DTOOLCHAIN_SUPPORTS_VIRT
+# For -mmicromips, use -Wa,-fatal-warnings to catch unsupported -mxpa which
+# only warns
+xpa-cflags-y                           := $(mips-cflags)
+xpa-cflags-$(micromips-ase)            += -mmicromips -Wa$(comma)-fatal-warnings
+toolchain-xpa                          := $(call cc-option-yn,$(xpa-cflags-y) -mxpa)
+cflags-$(toolchain-xpa)                        += -DTOOLCHAIN_SUPPORTS_XPA
 
 #
 # Firmware support
@@ -228,7 +234,7 @@ libs-y                              += arch/mips/fw/lib/
 #
 # Kernel compression
 #
-ifdef SYS_SUPPORTS_ZBOOT
+ifdef CONFIG_SYS_SUPPORTS_ZBOOT
 COMPRESSION_FNAME              = vmlinuz
 else
 COMPRESSION_FNAME              = vmlinux
index 874b7ca4cd11de1d81d3a39d16bf986a7006d0c2..70783b75fd9df8553fe1d97e648ccd0cd566fd4f 100644 (file)
@@ -5,3 +5,4 @@ platform-$(CONFIG_BCM47XX)      += bcm47xx/
 cflags-$(CONFIG_BCM47XX)       +=                                      \
                -I$(srctree)/arch/mips/include/asm/mach-bcm47xx
 load-$(CONFIG_BCM47XX)         := 0xffffffff80001000
+zload-$(CONFIG_BCM47XX)                += 0xffffffff80400000
index c675eece389a41c036c4ff2e1aeaf89509368a1f..adce180f3ee4264cabfdf85e7032f7c661b6a4c0 100644 (file)
@@ -133,4 +133,8 @@ vmlinuz.srec: vmlinuz
 uzImage.bin: vmlinuz.bin FORCE
        $(call if_changed,uimage,none)
 
-clean-files := $(objtree)/vmlinuz $(objtree)/vmlinuz.{32,ecoff,bin,srec}
+clean-files += $(objtree)/vmlinuz
+clean-files += $(objtree)/vmlinuz.32
+clean-files += $(objtree)/vmlinuz.ecoff
+clean-files += $(objtree)/vmlinuz.bin
+clean-files += $(objtree)/vmlinuz.srec
index 6a31759839b415d008b35e5159b2a81335de92c9..5b1361a89e021c749c7328dbf91a5673dfc0615d 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 dtb-$(CONFIG_JZ4740_QI_LB60)   += qi_lb60.dtb
+dtb-$(CONFIG_JZ4770_GCW0)      += gcw0.dtb
 dtb-$(CONFIG_JZ4780_CI20)      += ci20.dtb
 
 obj-y                          += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
diff --git a/arch/mips/boot/dts/ingenic/gcw0.dts b/arch/mips/boot/dts/ingenic/gcw0.dts
new file mode 100644 (file)
index 0000000..35f0291
--- /dev/null
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+#include "jz4770.dtsi"
+
+/ {
+       compatible = "gcw,zero", "ingenic,jz4770";
+       model = "GCW Zero";
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
+       };
+
+       chosen {
+               stdout-path = "serial2:57600n8";
+       };
+
+       board {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               otg_phy: otg-phy {
+                       compatible = "usb-nop-xceiv";
+                       clocks = <&cgu JZ4770_CLK_OTG_PHY>;
+                       clock-names = "main_clk";
+               };
+       };
+};
+
+&ext {
+       clock-frequency = <12000000>;
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&cgu {
+       /* Put high-speed peripherals under PLL1, such that we can change the
+        * PLL0 frequency on demand without having to suspend peripherals.
+        * We use a rate of 432 MHz, which is the least common multiple of
+        * 27 MHz (required by TV encoder) and 48 MHz (required by USB host).
+        */
+       assigned-clocks =
+               <&cgu JZ4770_CLK_PLL1>,
+               <&cgu JZ4770_CLK_UHC>;
+       assigned-clock-parents =
+               <0>,
+               <&cgu JZ4770_CLK_PLL1>;
+       assigned-clock-rates =
+               <432000000>;
+};
+
+&uhc {
+       /* The WiFi module is connected to the UHC. */
+       status = "okay";
+};
diff --git a/arch/mips/boot/dts/ingenic/jz4770.dtsi b/arch/mips/boot/dts/ingenic/jz4770.dtsi
new file mode 100644 (file)
index 0000000..7c2804f
--- /dev/null
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/clock/jz4770-cgu.h>
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "ingenic,jz4770";
+
+       cpuintc: interrupt-controller {
+               #address-cells = <0>;
+               #interrupt-cells = <1>;
+               interrupt-controller;
+               compatible = "mti,cpu-interrupt-controller";
+       };
+
+       intc: interrupt-controller@10001000 {
+               compatible = "ingenic,jz4770-intc";
+               reg = <0x10001000 0x40>;
+
+               interrupt-controller;
+               #interrupt-cells = <1>;
+
+               interrupt-parent = <&cpuintc>;
+               interrupts = <2>;
+       };
+
+       ext: ext {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+       };
+
+       osc32k: osc32k {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+       };
+
+       cgu: jz4770-cgu@10000000 {
+               compatible = "ingenic,jz4770-cgu";
+               reg = <0x10000000 0x100>;
+
+               clocks = <&ext>, <&osc32k>;
+               clock-names = "ext", "osc32k";
+
+               #clock-cells = <1>;
+       };
+
+       pinctrl: pin-controller@10010000 {
+               compatible = "ingenic,jz4770-pinctrl";
+               reg = <0x10010000 0x600>;
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               gpa: gpio@0 {
+                       compatible = "ingenic,jz4770-gpio";
+                       reg = <0>;
+
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 0 32>;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       interrupt-parent = <&intc>;
+                       interrupts = <17>;
+               };
+
+               gpb: gpio@1 {
+                       compatible = "ingenic,jz4770-gpio";
+                       reg = <1>;
+
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 32 32>;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       interrupt-parent = <&intc>;
+                       interrupts = <16>;
+               };
+
+               gpc: gpio@2 {
+                       compatible = "ingenic,jz4770-gpio";
+                       reg = <2>;
+
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 64 32>;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       interrupt-parent = <&intc>;
+                       interrupts = <15>;
+               };
+
+               gpd: gpio@3 {
+                       compatible = "ingenic,jz4770-gpio";
+                       reg = <3>;
+
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 96 32>;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       interrupt-parent = <&intc>;
+                       interrupts = <14>;
+               };
+
+               gpe: gpio@4 {
+                       compatible = "ingenic,jz4770-gpio";
+                       reg = <4>;
+
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 128 32>;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       interrupt-parent = <&intc>;
+                       interrupts = <13>;
+               };
+
+               gpf: gpio@5 {
+                       compatible = "ingenic,jz4770-gpio";
+                       reg = <5>;
+
+                       gpio-controller;
+                       gpio-ranges = <&pinctrl 0 160 32>;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       interrupt-parent = <&intc>;
+                       interrupts = <12>;
+               };
+       };
+
+       uart0: serial@10030000 {
+               compatible = "ingenic,jz4770-uart";
+               reg = <0x10030000 0x100>;
+
+               clocks = <&ext>, <&cgu JZ4770_CLK_UART0>;
+               clock-names = "baud", "module";
+
+               interrupt-parent = <&intc>;
+               interrupts = <5>;
+
+               status = "disabled";
+       };
+
+       uart1: serial@10031000 {
+               compatible = "ingenic,jz4770-uart";
+               reg = <0x10031000 0x100>;
+
+               clocks = <&ext>, <&cgu JZ4770_CLK_UART1>;
+               clock-names = "baud", "module";
+
+               interrupt-parent = <&intc>;
+               interrupts = <4>;
+
+               status = "disabled";
+       };
+
+       uart2: serial@10032000 {
+               compatible = "ingenic,jz4770-uart";
+               reg = <0x10032000 0x100>;
+
+               clocks = <&ext>, <&cgu JZ4770_CLK_UART2>;
+               clock-names = "baud", "module";
+
+               interrupt-parent = <&intc>;
+               interrupts = <3>;
+
+               status = "disabled";
+       };
+
+       uart3: serial@10033000 {
+               compatible = "ingenic,jz4770-uart";
+               reg = <0x10033000 0x100>;
+
+               clocks = <&ext>, <&cgu JZ4770_CLK_UART3>;
+               clock-names = "baud", "module";
+
+               interrupt-parent = <&intc>;
+               interrupts = <2>;
+
+               status = "disabled";
+       };
+
+       uhc: uhc@13430000 {
+               compatible = "generic-ohci";
+               reg = <0x13430000 0x1000>;
+
+               clocks = <&cgu JZ4770_CLK_UHC>, <&cgu JZ4770_CLK_UHC_PHY>;
+               assigned-clocks = <&cgu JZ4770_CLK_UHC>;
+               assigned-clock-rates = <48000000>;
+
+               interrupt-parent = <&intc>;
+               interrupts = <20>;
+
+               status = "disabled";
+       };
+};
index a55009edbb29a664ddbb3b53cadb80256ae7b351..5e73fe755be6cf151b73c9a73381675345ca3481 100644 (file)
@@ -153,7 +153,6 @@ CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
 # CONFIG_INPUT is not set
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_RAW=m
 # CONFIG_VT is not set
 CONFIG_SERIAL_NONSTANDARD=y
diff --git a/arch/mips/configs/gcw0_defconfig b/arch/mips/configs/gcw0_defconfig
new file mode 100644 (file)
index 0000000..99ac1fa
--- /dev/null
@@ -0,0 +1,27 @@
+CONFIG_MACH_INGENIC=y
+CONFIG_JZ4770_GCW0=y
+CONFIG_HIGHMEM=y
+# CONFIG_BOUNCE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_SECCOMP is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_EMBEDDED=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_USB=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_TMPFS=y
diff --git a/arch/mips/configs/generic/board-ranchu.config b/arch/mips/configs/generic/board-ranchu.config
new file mode 100644 (file)
index 0000000..fee9ad4
--- /dev/null
@@ -0,0 +1,30 @@
+CONFIG_VIRT_BOARD_RANCHU=y
+
+CONFIG_BATTERY_GOLDFISH=y
+CONFIG_FB=y
+CONFIG_FB_GOLDFISH=y
+CONFIG_GOLDFISH=y
+CONFIG_STAGING=y
+CONFIG_GOLDFISH_AUDIO=y
+CONFIG_GOLDFISH_PIC=y
+CONFIG_GOLDFISH_PIPE=y
+CONFIG_GOLDFISH_TTY=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GOLDFISH=y
+
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_GOLDFISH_EVENTS=y
+
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+
+CONFIG_VIRTIO_BLK=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+CONFIG_NETDEVICES=y
+CONFIG_VIRTIO_NET=y
index a0d593248668ff7c6cf40536d4114fbdbb9bd63f..91a9c13e2c820ea26dc42f3769e767a95ba5b58b 100644 (file)
@@ -252,7 +252,6 @@ CONFIG_RT2800PCI=m
 CONFIG_WL12XX=m
 CONFIG_WL1251=m
 # CONFIG_INPUT is not set
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_LIBPS2=m
 CONFIG_SERIO_RAW=m
 CONFIG_SERIO_ALTERA_PS2=m
index 1e26e58b9dc36c37d00c6c3c35d3dba3ee11f47d..ebff297328aed97d6fd8333203a16ddec0b2a94a 100644 (file)
@@ -75,7 +75,6 @@ CONFIG_DE2104X=m
 CONFIG_TULIP=m
 CONFIG_TULIP_MMIO=y
 CONFIG_INPUT_EVDEV=m
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_MACEPS2=y
 CONFIG_SERIO_RAW=y
 # CONFIG_CONSOLE_TRANSLATIONS is not set
index 396408404487e1a248bd331b228bc1d4199dc111..df8a9a15ca83a71ed80a792c7655334601902335 100644 (file)
@@ -312,9 +312,8 @@ CONFIG_HOSTAP_PCI=m
 CONFIG_IPW2100=m
 CONFIG_IPW2100_MONITOR=y
 CONFIG_LIBERTAS=m
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_POWER_RESET=y
index 5691673a332772dedd4af5c80af14c2102e79d88..14df9ef15d408d7b6d9bd2868736c6b9852f4401 100644 (file)
@@ -324,9 +324,7 @@ CONFIG_HOSTAP_PCI=m
 CONFIG_IPW2100=m
 CONFIG_IPW2100_MONITOR=y
 CONFIG_LIBERTAS=m
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
+CONFIG_INPUT_MOUSEDEV=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_POWER_RESET=y
index e9cadb37d684f74321c508abf61e0df2b4951353..25092e344574b8267822311596b8f1306204af19 100644 (file)
@@ -326,9 +326,7 @@ CONFIG_HOSTAP_PCI=m
 CONFIG_IPW2100=m
 CONFIG_IPW2100_MONITOR=y
 CONFIG_LIBERTAS=m
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
+CONFIG_INPUT_MOUSEDEV=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_POWER_RESET=y
index 77145ecaa23bd35deb7b90b49fa220b846cc7e4e..210bf609f7858308548a6f437f69bef772462cc9 100644 (file)
@@ -126,6 +126,7 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV=y
 # CONFIG_VT is not set
 CONFIG_LEGACY_PTY_COUNT=4
 CONFIG_SERIAL_8250=y
index cc2687cfdc135dcd104086e8d98b436313c0e801..e5934aa98397189740359f5ecfe06d23a9e62890 100644 (file)
@@ -126,6 +126,7 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_TOSHIBA is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV=y
 # CONFIG_VT is not set
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
index d8c8f5fb89180f956221cc3f913e7867d703b88a..cb2ca11c17893e2048b0060d6a6fa25993a4d24d 100644 (file)
@@ -127,6 +127,7 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV=y
 # CONFIG_VT is not set
 CONFIG_LEGACY_PTY_COUNT=4
 CONFIG_SERIAL_8250=y
index 04827bc9f87f97dd5aad599cc10fa9eb4fd22720..be29fcec69fcc70e325627bfa60f07e90f307c84 100644 (file)
@@ -130,6 +130,7 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV=y
 # CONFIG_VT is not set
 CONFIG_LEGACY_PTY_COUNT=4
 CONFIG_SERIAL_8250=y
index 7ea7c0ba26664ea5501749efb07423c413d4a524..40462d4c90a0159d563516664011c2bafa51f912 100644 (file)
@@ -125,6 +125,7 @@ CONFIG_PCNET32=y
 # CONFIG_NET_VENDOR_TOSHIBA is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_WLAN is not set
+CONFIG_INPUT_MOUSEDEV=y
 # CONFIG_VT is not set
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
index 2942610e408216d99a9491e8811757866064321a..4e50176cb3df53e65c06fc00355b359ed0216a20 100644 (file)
@@ -321,9 +321,8 @@ CONFIG_HOSTAP_PCI=m
 CONFIG_IPW2100=m
 CONFIG_IPW2100_MONITOR=y
 CONFIG_LIBERTAS=m
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_POWER_RESET=y
index 7357248b3d7aa75df627dfb05f25a87ad64b5c58..e8e1dd8e0e99cd525dff3e5b2f9bd8de413461a4 100644 (file)
@@ -399,7 +399,6 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_SERPORT=m
 CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIO_RAW=m
index 1e18fd7de209bc9be10006589cf03b11870b0c99..c4477a4d40c119b5ad053cdca84de40a9996fc32 100644 (file)
@@ -332,7 +332,6 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_SERPORT=m
 CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIO_RAW=m
index 81b5eb89446c76d02b29f9ea929893f0e98cebc8..e73cdb08fc6ea86a9ec8d27aeadfff700de92f4a 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_INPUT_EVDEV=m
 CONFIG_INPUT_EVBUG=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO_I8042 is not set
 # CONFIG_VT_CONSOLE is not set
 CONFIG_SERIAL_PNX8XXX=y
 CONFIG_SERIAL_PNX8XXX_CONSOLE=y
index c724bdd6a7e615b5a966e2f948519f033f4f4985..1edd8430ad61ed0790f68c7737fb42ee1481fd40 100644 (file)
@@ -65,7 +65,6 @@ CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SB1250_MAC=y
 # CONFIG_INPUT is not set
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_RAW=m
 # CONFIG_VT is not set
 # CONFIG_HW_RANDOM is not set
index 52e0286a161203d5904089c301bb2120a28cd77d..2ff3b17bfab18d829d74a1cb8c0e3fb790789d1b 100644 (file)
@@ -49,4 +49,14 @@ config FIT_IMAGE_FDT_XILFPGA
          Enable this to include the FDT for the MIPSfpga platform
          from Imagination Technologies in the FIT kernel image.
 
+config VIRT_BOARD_RANCHU
+       bool "Support Ranchu platform for Android emulator"
+       help
+         This enables support for the platform used by Android emulator.
+
+         Ranchu platform consists of a set of virtual devices. This platform
+         enables emulation of variety of virtual configurations while using
+         Android emulator. Android emulator is based on Qemu, and contains
+         the support for the same set of virtual devices.
+
 endif
index 874967363dbb20a0c61d6f21b3cbc4d211c7a77d..5c31e0c4697dd69a88cde68eee45c89c331ec0db 100644 (file)
@@ -15,3 +15,4 @@ obj-y += proc.o
 obj-$(CONFIG_YAMON_DT_SHIM)            += yamon-dt.o
 obj-$(CONFIG_LEGACY_BOARD_SEAD3)       += board-sead3.o
 obj-$(CONFIG_KEXEC)                    += kexec.o
+obj-$(CONFIG_VIRT_BOARD_RANCHU)                += board-ranchu.o
diff --git a/arch/mips/generic/board-ranchu.c b/arch/mips/generic/board-ranchu.c
new file mode 100644 (file)
index 0000000..59a8c18
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Support code for virtual Ranchu board for MIPS.
+ *
+ * Author: Miodrag Dinic <miodrag.dinic@mips.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/of_address.h>
+#include <linux/types.h>
+
+#include <asm/machine.h>
+#include <asm/mipsregs.h>
+#include <asm/time.h>
+
+#define GOLDFISH_TIMER_LOW             0x00
+#define GOLDFISH_TIMER_HIGH            0x04
+
+static __init u64 read_rtc_time(void __iomem *base)
+{
+       u32 time_low;
+       u32 time_high;
+
+       /*
+        * Reading the low address latches the high value
+        * as well so there is no fear that we may read
+        * inaccurate high value.
+        */
+       time_low = readl(base + GOLDFISH_TIMER_LOW);
+       time_high = readl(base + GOLDFISH_TIMER_HIGH);
+
+       return ((u64)time_high << 32) | time_low;
+}
+
+static __init unsigned int ranchu_measure_hpt_freq(void)
+{
+       u64 rtc_start, rtc_current, rtc_delta;
+       unsigned int start, count;
+       struct device_node *np;
+       void __iomem *rtc_base;
+
+       np = of_find_compatible_node(NULL, NULL, "google,goldfish-rtc");
+       if (!np)
+               panic("%s(): Failed to find 'google,goldfish-rtc' dt node!",
+                     __func__);
+
+       rtc_base = of_iomap(np, 0);
+       if (!rtc_base)
+               panic("%s(): Failed to ioremap Goldfish RTC base!", __func__);
+
+       /*
+        * Poll the nanosecond resolution RTC for one
+        * second to calibrate the CPU frequency.
+        */
+       rtc_start = read_rtc_time(rtc_base);
+       start = read_c0_count();
+
+       do {
+               rtc_current = read_rtc_time(rtc_base);
+               rtc_delta = rtc_current - rtc_start;
+       } while (rtc_delta < NSEC_PER_SEC);
+
+       count = read_c0_count() - start;
+
+       /*
+        * Make sure the frequency will be a round number.
+        * Without this correction, the returned value may vary
+        * between subsequent emulation executions.
+        *
+        * TODO: Set this value using device tree.
+        */
+       count += 5000;
+       count -= count % 10000;
+
+       iounmap(rtc_base);
+
+       return count;
+}
+
+static const struct of_device_id ranchu_of_match[] __initconst = {
+       {
+               .compatible = "mti,ranchu",
+       },
+       {}
+};
+
+MIPS_MACHINE(ranchu) = {
+       .matches = ranchu_of_match,
+       .measure_hpt_freq = ranchu_measure_hpt_freq,
+};
index 394f8161e4628680e82a79bf81c63160e0752bf8..cb7fdaeef426c88bc4a90a8d980b73a39b5bf824 100644 (file)
@@ -22,10 +22,10 @@ int get_c0_fdc_int(void)
 {
        int mips_cpu_fdc_irq;
 
-       if (cpu_has_veic)
-               panic("Unimplemented!");
-       else if (mips_gic_present())
+       if (mips_gic_present())
                mips_cpu_fdc_irq = gic_get_c0_fdc_int();
+       else if (cpu_has_veic)
+               panic("Unimplemented!");
        else if (cp0_fdc_irq >= 0)
                mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
        else
@@ -38,10 +38,10 @@ int get_c0_perfcount_int(void)
 {
        int mips_cpu_perf_irq;
 
-       if (cpu_has_veic)
-               panic("Unimplemented!");
-       else if (mips_gic_present())
+       if (mips_gic_present())
                mips_cpu_perf_irq = gic_get_c0_perfcount_int();
+       else if (cpu_has_veic)
+               panic("Unimplemented!");
        else if (cp0_perfcount_irq >= 0)
                mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
        else
@@ -54,10 +54,10 @@ unsigned int get_c0_compare_int(void)
 {
        int mips_cpu_timer_irq;
 
-       if (cpu_has_veic)
-               panic("Unimplemented!");
-       else if (mips_gic_present())
+       if (mips_gic_present())
                mips_cpu_timer_irq = gic_get_c0_compare_int();
+       else if (cpu_has_veic)
+               panic("Unimplemented!");
        else
                mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
 
index e26a093bb17a2e34e2079f1e5cda21a66052e843..a301a8f4bc6683b502165f5236fe6bd3dbdd7980 100644 (file)
@@ -79,6 +79,8 @@ enum loongson_machine_type {
  */
 #define  MACH_INGENIC_JZ4730   0       /* JZ4730 SOC           */
 #define  MACH_INGENIC_JZ4740   1       /* JZ4740 SOC           */
+#define  MACH_INGENIC_JZ4770   2       /* JZ4770 SOC           */
+#define  MACH_INGENIC_JZ4780   3       /* JZ4780 SOC           */
 
 extern char *system_type;
 const char *get_system_type(void);
index 77cad232a1c61cde88587230374ba153dd6bc975..e8161e4dfde7039a80cb3875bba7b9415520c67b 100644 (file)
@@ -110,7 +110,7 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst,
  */
 static inline __sum16 csum_fold(__wsum csum)
 {
-       u32 sum = (__force u32)csum;;
+       u32 sum = (__force u32)csum;
 
        sum += (sum << 16);
        csum = (sum < csum);
index 4f69f08717f6efc08bd3db360e8d2e32834ef04e..8c286bedff3e15339ba292f6fed55c7c44df5a81 100644 (file)
@@ -4,7 +4,7 @@
 
 #define SYSTEM_RAM_LOW         1
 #define SYSTEM_RAM_HIGH                2
-#define MEM_RESERVED           3
+#define SYSTEM_RAM_RESERVED    3
 #define PCI_IO                 4
 #define PCI_MEM                        5
 #define LOONGSON_CFG_REG       6
index e0d9b373d415195f95d34c628e94c621a1306462..f83879dadd1e3693023f17c6a707fbd91d2e3a98 100644 (file)
@@ -52,7 +52,7 @@ mips_machine_is_compatible(const struct mips_machine *mach, const void *fdt)
        if (!mach->matches)
                return NULL;
 
-       for (match = mach->matches; match->compatible; match++) {
+       for (match = mach->matches; match->compatible[0]; match++) {
                if (fdt_node_check_compatible(fdt, 0, match->compatible) == 0)
                        return match;
        }
index 6b1f1ad0542c9aa559d203c3d6082c5944c50942..858752dac3373475234063ba8940013bc5f97cae 100644 (file)
@@ -1180,6 +1180,89 @@ static inline int mm_insn_16bit(u16 insn)
 #define _ASM_INSN_IF_MIPS(_enc)
 #endif
 
+/*
+ * parse_r var, r - Helper assembler macro for parsing register names.
+ *
+ * This converts the register name in $n form provided in \r to the
+ * corresponding register number, which is assigned to the variable \var. It is
+ * needed to allow explicit encoding of instructions in inline assembly where
+ * registers are chosen by the compiler in $n form, allowing us to avoid using
+ * fixed register numbers.
+ *
+ * It also allows newer instructions (not implemented by the assembler) to be
+ * transparently implemented using assembler macros, instead of needing separate
+ * cases depending on toolchain support.
+ *
+ * Simple usage example:
+ * __asm__ __volatile__("parse_r __rt, %0\n\t"
+ *                     ".insn\n\t"
+ *                     "# di    %0\n\t"
+ *                     ".word   (0x41606000 | (__rt << 16))"
+ *                     : "=r" (status);
+ */
+
+/* Match an individual register number and assign to \var */
+#define _IFC_REG(n)                            \
+       ".ifc   \\r, $" #n "\n\t"               \
+       "\\var  = " #n "\n\t"                   \
+       ".endif\n\t"
+
+__asm__(".macro        parse_r var r\n\t"
+       "\\var  = -1\n\t"
+       _IFC_REG(0)  _IFC_REG(1)  _IFC_REG(2)  _IFC_REG(3)
+       _IFC_REG(4)  _IFC_REG(5)  _IFC_REG(6)  _IFC_REG(7)
+       _IFC_REG(8)  _IFC_REG(9)  _IFC_REG(10) _IFC_REG(11)
+       _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15)
+       _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19)
+       _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23)
+       _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27)
+       _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31)
+       ".iflt  \\var\n\t"
+       ".error \"Unable to parse register name \\r\"\n\t"
+       ".endif\n\t"
+       ".endm");
+
+#undef _IFC_REG
+
+/*
+ * C macros for generating assembler macros for common instruction formats.
+ *
+ * The names of the operands can be chosen by the caller, and the encoding of
+ * register operand \<Rn> is assigned to __<Rn> where it can be accessed from
+ * the ENC encodings.
+ */
+
+/* Instructions with no operands */
+#define _ASM_MACRO_0(OP, ENC)                                          \
+       __asm__(".macro " #OP "\n\t"                                    \
+               ENC                                                     \
+               ".endm")
+
+/* Instructions with 2 register operands */
+#define _ASM_MACRO_2R(OP, R1, R2, ENC)                                 \
+       __asm__(".macro " #OP " " #R1 ", " #R2 "\n\t"                   \
+               "parse_r __" #R1 ", \\" #R1 "\n\t"                      \
+               "parse_r __" #R2 ", \\" #R2 "\n\t"                      \
+               ENC                                                     \
+               ".endm")
+
+/* Instructions with 3 register operands */
+#define _ASM_MACRO_3R(OP, R1, R2, R3, ENC)                             \
+       __asm__(".macro " #OP " " #R1 ", " #R2 ", " #R3 "\n\t"          \
+               "parse_r __" #R1 ", \\" #R1 "\n\t"                      \
+               "parse_r __" #R2 ", \\" #R2 "\n\t"                      \
+               "parse_r __" #R3 ", \\" #R3 "\n\t"                      \
+               ENC                                                     \
+               ".endm")
+
+/* Instructions with 2 register operands and 1 optional select operand */
+#define _ASM_MACRO_2R_1S(OP, R1, R2, SEL3, ENC)                                \
+       __asm__(".macro " #OP " " #R1 ", " #R2 ", " #SEL3 " = 0\n\t"    \
+               "parse_r __" #R1 ", \\" #R1 "\n\t"                      \
+               "parse_r __" #R2 ", \\" #R2 "\n\t"                      \
+               ENC                                                     \
+               ".endm")
+
 /*
  * TLB Invalidate Flush
  */
@@ -1245,14 +1328,14 @@ do {                                                            \
  * Macros to access the system control coprocessor
  */
 
-#define __read_32bit_c0_register(source, sel)                          \
+#define ___read_32bit_c0_register(source, sel, vol)                    \
 ({ unsigned int __res;                                                 \
        if (sel == 0)                                                   \
-               __asm__ __volatile__(                                   \
+               __asm__ vol(                                            \
                        "mfc0\t%0, " #source "\n\t"                     \
                        : "=r" (__res));                                \
        else                                                            \
-               __asm__ __volatile__(                                   \
+               __asm__ vol(                                            \
                        ".set\tmips32\n\t"                              \
                        "mfc0\t%0, " #source ", " #sel "\n\t"           \
                        ".set\tmips0\n\t"                               \
@@ -1260,18 +1343,18 @@ do {                                                            \
        __res;                                                          \
 })
 
-#define __read_64bit_c0_register(source, sel)                          \
+#define ___read_64bit_c0_register(source, sel, vol)                    \
 ({ unsigned long long __res;                                           \
        if (sizeof(unsigned long) == 4)                                 \
-               __res = __read_64bit_c0_split(source, sel);             \
+               __res = __read_64bit_c0_split(source, sel, vol);        \
        else if (sel == 0)                                              \
-               __asm__ __volatile__(                                   \
+               __asm__ vol(                                            \
                        ".set\tmips3\n\t"                               \
                        "dmfc0\t%0, " #source "\n\t"                    \
                        ".set\tmips0"                                   \
                        : "=r" (__res));                                \
        else                                                            \
-               __asm__ __volatile__(                                   \
+               __asm__ vol(                                            \
                        ".set\tmips64\n\t"                              \
                        "dmfc0\t%0, " #source ", " #sel "\n\t"          \
                        ".set\tmips0"                                   \
@@ -1279,6 +1362,18 @@ do {                                                             \
        __res;                                                          \
 })
 
+#define __read_32bit_c0_register(source, sel)                          \
+       ___read_32bit_c0_register(source, sel, __volatile__)
+
+#define __read_const_32bit_c0_register(source, sel)                    \
+       ___read_32bit_c0_register(source, sel,)
+
+#define __read_64bit_c0_register(source, sel)                          \
+       ___read_64bit_c0_register(source, sel, __volatile__)
+
+#define __read_const_64bit_c0_register(source, sel)                    \
+       ___read_64bit_c0_register(source, sel,)
+
 #define __write_32bit_c0_register(register, sel, value)                        \
 do {                                                                   \
        if (sel == 0)                                                   \
@@ -1316,6 +1411,11 @@ do {                                                                     \
        (unsigned long) __read_32bit_c0_register(reg, sel) :            \
        (unsigned long) __read_64bit_c0_register(reg, sel))
 
+#define __read_const_ulong_c0_register(reg, sel)                       \
+       ((sizeof(unsigned long) == 4) ?                                 \
+       (unsigned long) __read_const_32bit_c0_register(reg, sel) :      \
+       (unsigned long) __read_const_64bit_c0_register(reg, sel))
+
 #define __write_ulong_c0_register(reg, sel, val)                       \
 do {                                                                   \
        if (sizeof(unsigned long) == 4)                                 \
@@ -1346,14 +1446,14 @@ do {                                                                    \
  * These versions are only needed for systems with more than 38 bits of
  * physical address space running the 32-bit kernel.  That's none atm :-)
  */
-#define __read_64bit_c0_split(source, sel)                             \
+#define __read_64bit_c0_split(source, sel, vol)                                \
 ({                                                                     \
        unsigned long long __val;                                       \
        unsigned long __flags;                                          \
                                                                        \
        local_irq_save(__flags);                                        \
        if (sel == 0)                                                   \
-               __asm__ __volatile__(                                   \
+               __asm__ vol(                                            \
                        ".set\tmips64\n\t"                              \
                        "dmfc0\t%L0, " #source "\n\t"                   \
                        "dsra\t%M0, %L0, 32\n\t"                        \
@@ -1361,7 +1461,7 @@ do {                                                                      \
                        ".set\tmips0"                                   \
                        : "=r" (__val));                                \
        else                                                            \
-               __asm__ __volatile__(                                   \
+               __asm__ vol(                                            \
                        ".set\tmips64\n\t"                              \
                        "dmfc0\t%L0, " #source ", " #sel "\n\t"         \
                        "dsra\t%M0, %L0, 32\n\t"                        \
@@ -1404,37 +1504,43 @@ do {                                                                    \
        local_irq_restore(__flags);                                     \
 } while (0)
 
-#define __readx_32bit_c0_register(source)                              \
+#ifndef TOOLCHAIN_SUPPORTS_XPA
+_ASM_MACRO_2R_1S(mfhc0, rt, rs, sel,
+       _ASM_INSN_IF_MIPS(0x40400000 | __rt << 16 | __rs << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x000000f4 | __rt << 21 | __rs << 16 | \\sel << 11));
+_ASM_MACRO_2R_1S(mthc0, rt, rd, sel,
+       _ASM_INSN_IF_MIPS(0x40c00000 | __rt << 16 | __rd << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x000002f4 | __rt << 21 | __rd << 16 | \\sel << 11));
+#define _ASM_SET_XPA ""
+#else  /* !TOOLCHAIN_SUPPORTS_XPA */
+#define _ASM_SET_XPA ".set\txpa\n\t"
+#endif
+
+#define __readx_32bit_c0_register(source, sel)                         \
 ({                                                                     \
        unsigned int __res;                                             \
                                                                        \
        __asm__ __volatile__(                                           \
        "       .set    push                                    \n"     \
-       "       .set    noat                                    \n"     \
        "       .set    mips32r2                                \n"     \
-       "       # mfhc0 $1, %1                                  \n"     \
-       _ASM_INSN_IF_MIPS(0x40410000 | ((%1 & 0x1f) << 11))             \
-       _ASM_INSN32_IF_MM(0x002000f4 | ((%1 & 0x1f) << 16))             \
-       "       move    %0, $1                                  \n"     \
+       _ASM_SET_XPA                                                    \
+       "       mfhc0   %0, " #source ", %1                     \n"     \
        "       .set    pop                                     \n"     \
        : "=r" (__res)                                                  \
-       : "i" (source));                                                \
+       : "i" (sel));                                                   \
        __res;                                                          \
 })
 
-#define __writex_32bit_c0_register(register, value)                    \
+#define __writex_32bit_c0_register(register, sel, value)               \
 do {                                                                   \
        __asm__ __volatile__(                                           \
        "       .set    push                                    \n"     \
-       "       .set    noat                                    \n"     \
        "       .set    mips32r2                                \n"     \
-       "       move    $1, %0                                  \n"     \
-       "       # mthc0 $1, %1                                  \n"     \
-       _ASM_INSN_IF_MIPS(0x40c10000 | ((%1 & 0x1f) << 11))             \
-       _ASM_INSN32_IF_MM(0x002002f4 | ((%1 & 0x1f) << 16))             \
+       _ASM_SET_XPA                                                    \
+       "       mthc0   %z0, " #register ", %1                  \n"     \
        "       .set    pop                                     \n"     \
        :                                                               \
-       : "r" (value), "i" (register));                                 \
+       : "Jr" (value), "i" (sel));                                     \
 } while (0)
 
 #define read_c0_index()                __read_32bit_c0_register($0, 0)
@@ -1446,14 +1552,14 @@ do {                                                                    \
 #define read_c0_entrylo0()     __read_ulong_c0_register($2, 0)
 #define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val)
 
-#define readx_c0_entrylo0()    __readx_32bit_c0_register(2)
-#define writex_c0_entrylo0(val)        __writex_32bit_c0_register(2, val)
+#define readx_c0_entrylo0()    __readx_32bit_c0_register($2, 0)
+#define writex_c0_entrylo0(val)        __writex_32bit_c0_register($2, 0, val)
 
 #define read_c0_entrylo1()     __read_ulong_c0_register($3, 0)
 #define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val)
 
-#define readx_c0_entrylo1()    __readx_32bit_c0_register(3)
-#define writex_c0_entrylo1(val)        __writex_32bit_c0_register(3, val)
+#define readx_c0_entrylo1()    __readx_32bit_c0_register($3, 0)
+#define writex_c0_entrylo1(val)        __writex_32bit_c0_register($3, 0, val)
 
 #define read_c0_conf()         __read_32bit_c0_register($3, 0)
 #define write_c0_conf(val)     __write_32bit_c0_register($3, 0, val)
@@ -1541,7 +1647,7 @@ do {                                                                      \
 #define read_c0_epc()          __read_ulong_c0_register($14, 0)
 #define write_c0_epc(val)      __write_ulong_c0_register($14, 0, val)
 
-#define read_c0_prid()         __read_32bit_c0_register($15, 0)
+#define read_c0_prid()         __read_const_32bit_c0_register($15, 0)
 
 #define read_c0_cmgcrbase()    __read_ulong_c0_register($15, 3)
 
@@ -1830,18 +1936,44 @@ do {                                                                    \
  * Macros to access the guest system control coprocessor
  */
 
-#ifdef TOOLCHAIN_SUPPORTS_VIRT
+#ifndef TOOLCHAIN_SUPPORTS_VIRT
+_ASM_MACRO_2R_1S(mfgc0, rt, rs, sel,
+       _ASM_INSN_IF_MIPS(0x40600000 | __rt << 16 | __rs << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x000004fc | __rt << 21 | __rs << 16 | \\sel << 11));
+_ASM_MACRO_2R_1S(dmfgc0, rt, rs, sel,
+       _ASM_INSN_IF_MIPS(0x40600100 | __rt << 16 | __rs << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x580004fc | __rt << 21 | __rs << 16 | \\sel << 11));
+_ASM_MACRO_2R_1S(mtgc0, rt, rd, sel,
+       _ASM_INSN_IF_MIPS(0x40600200 | __rt << 16 | __rd << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x000006fc | __rt << 21 | __rd << 16 | \\sel << 11));
+_ASM_MACRO_2R_1S(dmtgc0, rt, rd, sel,
+       _ASM_INSN_IF_MIPS(0x40600300 | __rt << 16 | __rd << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x580006fc | __rt << 21 | __rd << 16 | \\sel << 11));
+_ASM_MACRO_0(tlbgp,    _ASM_INSN_IF_MIPS(0x42000010)
+                      _ASM_INSN32_IF_MM(0x0000017c));
+_ASM_MACRO_0(tlbgr,    _ASM_INSN_IF_MIPS(0x42000009)
+                      _ASM_INSN32_IF_MM(0x0000117c));
+_ASM_MACRO_0(tlbgwi,   _ASM_INSN_IF_MIPS(0x4200000a)
+                      _ASM_INSN32_IF_MM(0x0000217c));
+_ASM_MACRO_0(tlbgwr,   _ASM_INSN_IF_MIPS(0x4200000e)
+                      _ASM_INSN32_IF_MM(0x0000317c));
+_ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c)
+                      _ASM_INSN32_IF_MM(0x0000517c));
+#define _ASM_SET_VIRT ""
+#else  /* !TOOLCHAIN_SUPPORTS_VIRT */
+#define _ASM_SET_VIRT ".set\tvirt\n\t"
+#endif
 
 #define __read_32bit_gc0_register(source, sel)                         \
 ({ int __res;                                                          \
        __asm__ __volatile__(                                           \
                ".set\tpush\n\t"                                        \
                ".set\tmips32r2\n\t"                                    \
-               ".set\tvirt\n\t"                                        \
-               "mfgc0\t%0, $%1, %2\n\t"                                \
+               _ASM_SET_VIRT                                           \
+               "mfgc0\t%0, " #source ", %1\n\t"                        \
                ".set\tpop"                                             \
                : "=r" (__res)                                          \
-               : "i" (source), "i" (sel));                             \
+               : "i" (sel));                                           \
        __res;                                                          \
 })
 
@@ -1850,11 +1982,11 @@ do {                                                                    \
        __asm__ __volatile__(                                           \
                ".set\tpush\n\t"                                        \
                ".set\tmips64r2\n\t"                                    \
-               ".set\tvirt\n\t"                                        \
-               "dmfgc0\t%0, $%1, %2\n\t"                       \
+               _ASM_SET_VIRT                                           \
+               "dmfgc0\t%0, " #source ", %1\n\t"                       \
                ".set\tpop"                                             \
                : "=r" (__res)                                          \
-               : "i" (source), "i" (sel));                             \
+               : "i" (sel));                                           \
        __res;                                                          \
 })
 
@@ -1863,11 +1995,11 @@ do {                                                                    \
        __asm__ __volatile__(                                           \
                ".set\tpush\n\t"                                        \
                ".set\tmips32r2\n\t"                                    \
-               ".set\tvirt\n\t"                                        \
-               "mtgc0\t%z0, $%1, %2\n\t"                               \
+               _ASM_SET_VIRT                                           \
+               "mtgc0\t%z0, " #register ", %1\n\t"                     \
                ".set\tpop"                                             \
                : : "Jr" ((unsigned int)(value)),                       \
-                   "i" (register), "i" (sel));                         \
+                   "i" (sel));                                         \
 } while (0)
 
 #define __write_64bit_gc0_register(register, sel, value)               \
@@ -1875,75 +2007,13 @@ do {                                                                    \
        __asm__ __volatile__(                                           \
                ".set\tpush\n\t"                                        \
                ".set\tmips64r2\n\t"                                    \
-               ".set\tvirt\n\t"                                        \
-               "dmtgc0\t%z0, $%1, %2\n\t"                              \
+               _ASM_SET_VIRT                                           \
+               "dmtgc0\t%z0, " #register ", %1\n\t"                    \
                ".set\tpop"                                             \
                : : "Jr" (value),                                       \
-                   "i" (register), "i" (sel));                         \
+                   "i" (sel));                                         \
 } while (0)
 
-#else  /* TOOLCHAIN_SUPPORTS_VIRT */
-
-#define __read_32bit_gc0_register(source, sel)                         \
-({ int __res;                                                          \
-       __asm__ __volatile__(                                           \
-               ".set\tpush\n\t"                                        \
-               ".set\tnoat\n\t"                                        \
-               "# mfgc0\t$1, $%1, %2\n\t"                              \
-               _ASM_INSN_IF_MIPS(0x40610000 | %1 << 11 | %2)           \
-               _ASM_INSN32_IF_MM(0x002004fc | %1 << 16 | %2 << 11)     \
-               "move\t%0, $1\n\t"                                      \
-               ".set\tpop"                                             \
-               : "=r" (__res)                                          \
-               : "i" (source), "i" (sel));                             \
-       __res;                                                          \
-})
-
-#define __read_64bit_gc0_register(source, sel)                         \
-({ unsigned long long __res;                                           \
-       __asm__ __volatile__(                                           \
-               ".set\tpush\n\t"                                        \
-               ".set\tnoat\n\t"                                        \
-               "# dmfgc0\t$1, $%1, %2\n\t"                             \
-               _ASM_INSN_IF_MIPS(0x40610100 | %1 << 11 | %2)           \
-               _ASM_INSN32_IF_MM(0x582004fc | %1 << 16 | %2 << 11)     \
-               "move\t%0, $1\n\t"                                      \
-               ".set\tpop"                                             \
-               : "=r" (__res)                                          \
-               : "i" (source), "i" (sel));                             \
-       __res;                                                          \
-})
-
-#define __write_32bit_gc0_register(register, sel, value)               \
-do {                                                                   \
-       __asm__ __volatile__(                                           \
-               ".set\tpush\n\t"                                        \
-               ".set\tnoat\n\t"                                        \
-               "move\t$1, %z0\n\t"                                     \
-               "# mtgc0\t$1, $%1, %2\n\t"                              \
-               _ASM_INSN_IF_MIPS(0x40610200 | %1 << 11 | %2)           \
-               _ASM_INSN32_IF_MM(0x002006fc | %1 << 16 | %2 << 11)     \
-               ".set\tpop"                                             \
-               : : "Jr" ((unsigned int)(value)),                       \
-                   "i" (register), "i" (sel));                         \
-} while (0)
-
-#define __write_64bit_gc0_register(register, sel, value)               \
-do {                                                                   \
-       __asm__ __volatile__(                                           \
-               ".set\tpush\n\t"                                        \
-               ".set\tnoat\n\t"                                        \
-               "move\t$1, %z0\n\t"                                     \
-               "# dmtgc0\t$1, $%1, %2\n\t"                             \
-               _ASM_INSN_IF_MIPS(0x40610300 | %1 << 11 | %2)           \
-               _ASM_INSN32_IF_MM(0x582006fc | %1 << 16 | %2 << 11)     \
-               ".set\tpop"                                             \
-               : : "Jr" (value),                                       \
-                   "i" (register), "i" (sel));                         \
-} while (0)
-
-#endif /* !TOOLCHAIN_SUPPORTS_VIRT */
-
 #define __read_ulong_gc0_register(reg, sel)                            \
        ((sizeof(unsigned long) == 4) ?                                 \
        (unsigned long) __read_32bit_gc0_register(reg, sel) :           \
@@ -1957,207 +2027,207 @@ do {                                                                  \
                __write_64bit_gc0_register(reg, sel, val);              \
 } while (0)
 
-#define read_gc0_index()               __read_32bit_gc0_register(0, 0)
-#define write_gc0_index(val)           __write_32bit_gc0_register(0, 0, val)
+#define read_gc0_index()               __read_32bit_gc0_register($0, 0)
+#define write_gc0_index(val)           __write_32bit_gc0_register($0, 0, val)
 
-#define read_gc0_entrylo0()            __read_ulong_gc0_register(2, 0)
-#define write_gc0_entrylo0(val)                __write_ulong_gc0_register(2, 0, val)
+#define read_gc0_entrylo0()            __read_ulong_gc0_register($2, 0)
+#define write_gc0_entrylo0(val)                __write_ulong_gc0_register($2, 0, val)
 
-#define read_gc0_entrylo1()            __read_ulong_gc0_register(3, 0)
-#define write_gc0_entrylo1(val)                __write_ulong_gc0_register(3, 0, val)
+#define read_gc0_entrylo1()            __read_ulong_gc0_register($3, 0)
+#define write_gc0_entrylo1(val)                __write_ulong_gc0_register($3, 0, val)
 
-#define read_gc0_context()             __read_ulong_gc0_register(4, 0)
-#define write_gc0_context(val)         __write_ulong_gc0_register(4, 0, val)
+#define read_gc0_context()             __read_ulong_gc0_register($4, 0)
+#define write_gc0_context(val)         __write_ulong_gc0_register($4, 0, val)
 
-#define read_gc0_contextconfig()       __read_32bit_gc0_register(4, 1)
-#define write_gc0_contextconfig(val)   __write_32bit_gc0_register(4, 1, val)
+#define read_gc0_contextconfig()       __read_32bit_gc0_register($4, 1)
+#define write_gc0_contextconfig(val)   __write_32bit_gc0_register($4, 1, val)
 
-#define read_gc0_userlocal()           __read_ulong_gc0_register(4, 2)
-#define write_gc0_userlocal(val)       __write_ulong_gc0_register(4, 2, val)
+#define read_gc0_userlocal()           __read_ulong_gc0_register($4, 2)
+#define write_gc0_userlocal(val)       __write_ulong_gc0_register($4, 2, val)
 
-#define read_gc0_xcontextconfig()      __read_ulong_gc0_register(4, 3)
-#define write_gc0_xcontextconfig(val)  __write_ulong_gc0_register(4, 3, val)
+#define read_gc0_xcontextconfig()      __read_ulong_gc0_register($4, 3)
+#define write_gc0_xcontextconfig(val)  __write_ulong_gc0_register($4, 3, val)
 
-#define read_gc0_pagemask()            __read_32bit_gc0_register(5, 0)
-#define write_gc0_pagemask(val)                __write_32bit_gc0_register(5, 0, val)
+#define read_gc0_pagemask()            __read_32bit_gc0_register($5, 0)
+#define write_gc0_pagemask(val)                __write_32bit_gc0_register($5, 0, val)
 
-#define read_gc0_pagegrain()           __read_32bit_gc0_register(5, 1)
-#define write_gc0_pagegrain(val)       __write_32bit_gc0_register(5, 1, val)
+#define read_gc0_pagegrain()           __read_32bit_gc0_register($5, 1)
+#define write_gc0_pagegrain(val)       __write_32bit_gc0_register($5, 1, val)
 
-#define read_gc0_segctl0()             __read_ulong_gc0_register(5, 2)
-#define write_gc0_segctl0(val)         __write_ulong_gc0_register(5, 2, val)
+#define read_gc0_segctl0()             __read_ulong_gc0_register($5, 2)
+#define write_gc0_segctl0(val)         __write_ulong_gc0_register($5, 2, val)
 
-#define read_gc0_segctl1()             __read_ulong_gc0_register(5, 3)
-#define write_gc0_segctl1(val)         __write_ulong_gc0_register(5, 3, val)
+#define read_gc0_segctl1()             __read_ulong_gc0_register($5, 3)
+#define write_gc0_segctl1(val)         __write_ulong_gc0_register($5, 3, val)
 
-#define read_gc0_segctl2()             __read_ulong_gc0_register(5, 4)
-#define write_gc0_segctl2(val)         __write_ulong_gc0_register(5, 4, val)
+#define read_gc0_segctl2()             __read_ulong_gc0_register($5, 4)
+#define write_gc0_segctl2(val)         __write_ulong_gc0_register($5, 4, val)
 
-#define read_gc0_pwbase()              __read_ulong_gc0_register(5, 5)
-#define write_gc0_pwbase(val)          __write_ulong_gc0_register(5, 5, val)
+#define read_gc0_pwbase()              __read_ulong_gc0_register($5, 5)
+#define write_gc0_pwbase(val)          __write_ulong_gc0_register($5, 5, val)
 
-#define read_gc0_pwfield()             __read_ulong_gc0_register(5, 6)
-#define write_gc0_pwfield(val)         __write_ulong_gc0_register(5, 6, val)
+#define read_gc0_pwfield()             __read_ulong_gc0_register($5, 6)
+#define write_gc0_pwfield(val)         __write_ulong_gc0_register($5, 6, val)
 
-#define read_gc0_pwsize()              __read_ulong_gc0_register(5, 7)
-#define write_gc0_pwsize(val)          __write_ulong_gc0_register(5, 7, val)
+#define read_gc0_pwsize()              __read_ulong_gc0_register($5, 7)
+#define write_gc0_pwsize(val)          __write_ulong_gc0_register($5, 7, val)
 
-#define read_gc0_wired()               __read_32bit_gc0_register(6, 0)
-#define write_gc0_wired(val)           __write_32bit_gc0_register(6, 0, val)
+#define read_gc0_wired()               __read_32bit_gc0_register($6, 0)
+#define write_gc0_wired(val)           __write_32bit_gc0_register($6, 0, val)
 
-#define read_gc0_pwctl()               __read_32bit_gc0_register(6, 6)
-#define write_gc0_pwctl(val)           __write_32bit_gc0_register(6, 6, val)
-
-#define read_gc0_hwrena()              __read_32bit_gc0_register(7, 0)
-#define write_gc0_hwrena(val)          __write_32bit_gc0_register(7, 0, val)
-
-#define read_gc0_badvaddr()            __read_ulong_gc0_register(8, 0)
-#define write_gc0_badvaddr(val)                __write_ulong_gc0_register(8, 0, val)
-
-#define read_gc0_badinstr()            __read_32bit_gc0_register(8, 1)
-#define write_gc0_badinstr(val)                __write_32bit_gc0_register(8, 1, val)
-
-#define read_gc0_badinstrp()           __read_32bit_gc0_register(8, 2)
-#define write_gc0_badinstrp(val)       __write_32bit_gc0_register(8, 2, val)
-
-#define read_gc0_count()               __read_32bit_gc0_register(9, 0)
-
-#define read_gc0_entryhi()             __read_ulong_gc0_register(10, 0)
-#define write_gc0_entryhi(val)         __write_ulong_gc0_register(10, 0, val)
-
-#define read_gc0_compare()             __read_32bit_gc0_register(11, 0)
-#define write_gc0_compare(val)         __write_32bit_gc0_register(11, 0, val)
-
-#define read_gc0_status()              __read_32bit_gc0_register(12, 0)
-#define write_gc0_status(val)          __write_32bit_gc0_register(12, 0, val)
-
-#define read_gc0_intctl()              __read_32bit_gc0_register(12, 1)
-#define write_gc0_intctl(val)          __write_32bit_gc0_register(12, 1, val)
-
-#define read_gc0_cause()               __read_32bit_gc0_register(13, 0)
-#define write_gc0_cause(val)           __write_32bit_gc0_register(13, 0, val)
-
-#define read_gc0_epc()                 __read_ulong_gc0_register(14, 0)
-#define write_gc0_epc(val)             __write_ulong_gc0_register(14, 0, val)
-
-#define read_gc0_prid()                        __read_32bit_gc0_register(15, 0)
-
-#define read_gc0_ebase()               __read_32bit_gc0_register(15, 1)
-#define write_gc0_ebase(val)           __write_32bit_gc0_register(15, 1, val)
-
-#define read_gc0_ebase_64()            __read_64bit_gc0_register(15, 1)
-#define write_gc0_ebase_64(val)                __write_64bit_gc0_register(15, 1, val)
-
-#define read_gc0_config()              __read_32bit_gc0_register(16, 0)
-#define read_gc0_config1()             __read_32bit_gc0_register(16, 1)
-#define read_gc0_config2()             __read_32bit_gc0_register(16, 2)
-#define read_gc0_config3()             __read_32bit_gc0_register(16, 3)
-#define read_gc0_config4()             __read_32bit_gc0_register(16, 4)
-#define read_gc0_config5()             __read_32bit_gc0_register(16, 5)
-#define read_gc0_config6()             __read_32bit_gc0_register(16, 6)
-#define read_gc0_config7()             __read_32bit_gc0_register(16, 7)
-#define write_gc0_config(val)          __write_32bit_gc0_register(16, 0, val)
-#define write_gc0_config1(val)         __write_32bit_gc0_register(16, 1, val)
-#define write_gc0_config2(val)         __write_32bit_gc0_register(16, 2, val)
-#define write_gc0_config3(val)         __write_32bit_gc0_register(16, 3, val)
-#define write_gc0_config4(val)         __write_32bit_gc0_register(16, 4, val)
-#define write_gc0_config5(val)         __write_32bit_gc0_register(16, 5, val)
-#define write_gc0_config6(val)         __write_32bit_gc0_register(16, 6, val)
-#define write_gc0_config7(val)         __write_32bit_gc0_register(16, 7, val)
-
-#define read_gc0_lladdr()              __read_ulong_gc0_register(17, 0)
-#define write_gc0_lladdr(val)          __write_ulong_gc0_register(17, 0, val)
-
-#define read_gc0_watchlo0()            __read_ulong_gc0_register(18, 0)
-#define read_gc0_watchlo1()            __read_ulong_gc0_register(18, 1)
-#define read_gc0_watchlo2()            __read_ulong_gc0_register(18, 2)
-#define read_gc0_watchlo3()            __read_ulong_gc0_register(18, 3)
-#define read_gc0_watchlo4()            __read_ulong_gc0_register(18, 4)
-#define read_gc0_watchlo5()            __read_ulong_gc0_register(18, 5)
-#define read_gc0_watchlo6()            __read_ulong_gc0_register(18, 6)
-#define read_gc0_watchlo7()            __read_ulong_gc0_register(18, 7)
-#define write_gc0_watchlo0(val)                __write_ulong_gc0_register(18, 0, val)
-#define write_gc0_watchlo1(val)                __write_ulong_gc0_register(18, 1, val)
-#define write_gc0_watchlo2(val)                __write_ulong_gc0_register(18, 2, val)
-#define write_gc0_watchlo3(val)                __write_ulong_gc0_register(18, 3, val)
-#define write_gc0_watchlo4(val)                __write_ulong_gc0_register(18, 4, val)
-#define write_gc0_watchlo5(val)                __write_ulong_gc0_register(18, 5, val)
-#define write_gc0_watchlo6(val)                __write_ulong_gc0_register(18, 6, val)
-#define write_gc0_watchlo7(val)                __write_ulong_gc0_register(18, 7, val)
-
-#define read_gc0_watchhi0()            __read_32bit_gc0_register(19, 0)
-#define read_gc0_watchhi1()            __read_32bit_gc0_register(19, 1)
-#define read_gc0_watchhi2()            __read_32bit_gc0_register(19, 2)
-#define read_gc0_watchhi3()            __read_32bit_gc0_register(19, 3)
-#define read_gc0_watchhi4()            __read_32bit_gc0_register(19, 4)
-#define read_gc0_watchhi5()            __read_32bit_gc0_register(19, 5)
-#define read_gc0_watchhi6()            __read_32bit_gc0_register(19, 6)
-#define read_gc0_watchhi7()            __read_32bit_gc0_register(19, 7)
-#define write_gc0_watchhi0(val)                __write_32bit_gc0_register(19, 0, val)
-#define write_gc0_watchhi1(val)                __write_32bit_gc0_register(19, 1, val)
-#define write_gc0_watchhi2(val)                __write_32bit_gc0_register(19, 2, val)
-#define write_gc0_watchhi3(val)                __write_32bit_gc0_register(19, 3, val)
-#define write_gc0_watchhi4(val)                __write_32bit_gc0_register(19, 4, val)
-#define write_gc0_watchhi5(val)                __write_32bit_gc0_register(19, 5, val)
-#define write_gc0_watchhi6(val)                __write_32bit_gc0_register(19, 6, val)
-#define write_gc0_watchhi7(val)                __write_32bit_gc0_register(19, 7, val)
-
-#define read_gc0_xcontext()            __read_ulong_gc0_register(20, 0)
-#define write_gc0_xcontext(val)                __write_ulong_gc0_register(20, 0, val)
-
-#define read_gc0_perfctrl0()           __read_32bit_gc0_register(25, 0)
-#define write_gc0_perfctrl0(val)       __write_32bit_gc0_register(25, 0, val)
-#define read_gc0_perfcntr0()           __read_32bit_gc0_register(25, 1)
-#define write_gc0_perfcntr0(val)       __write_32bit_gc0_register(25, 1, val)
-#define read_gc0_perfcntr0_64()                __read_64bit_gc0_register(25, 1)
-#define write_gc0_perfcntr0_64(val)    __write_64bit_gc0_register(25, 1, val)
-#define read_gc0_perfctrl1()           __read_32bit_gc0_register(25, 2)
-#define write_gc0_perfctrl1(val)       __write_32bit_gc0_register(25, 2, val)
-#define read_gc0_perfcntr1()           __read_32bit_gc0_register(25, 3)
-#define write_gc0_perfcntr1(val)       __write_32bit_gc0_register(25, 3, val)
-#define read_gc0_perfcntr1_64()                __read_64bit_gc0_register(25, 3)
-#define write_gc0_perfcntr1_64(val)    __write_64bit_gc0_register(25, 3, val)
-#define read_gc0_perfctrl2()           __read_32bit_gc0_register(25, 4)
-#define write_gc0_perfctrl2(val)       __write_32bit_gc0_register(25, 4, val)
-#define read_gc0_perfcntr2()           __read_32bit_gc0_register(25, 5)
-#define write_gc0_perfcntr2(val)       __write_32bit_gc0_register(25, 5, val)
-#define read_gc0_perfcntr2_64()                __read_64bit_gc0_register(25, 5)
-#define write_gc0_perfcntr2_64(val)    __write_64bit_gc0_register(25, 5, val)
-#define read_gc0_perfctrl3()           __read_32bit_gc0_register(25, 6)
-#define write_gc0_perfctrl3(val)       __write_32bit_gc0_register(25, 6, val)
-#define read_gc0_perfcntr3()           __read_32bit_gc0_register(25, 7)
-#define write_gc0_perfcntr3(val)       __write_32bit_gc0_register(25, 7, val)
-#define read_gc0_perfcntr3_64()                __read_64bit_gc0_register(25, 7)
-#define write_gc0_perfcntr3_64(val)    __write_64bit_gc0_register(25, 7, val)
-
-#define read_gc0_errorepc()            __read_ulong_gc0_register(30, 0)
-#define write_gc0_errorepc(val)                __write_ulong_gc0_register(30, 0, val)
-
-#define read_gc0_kscratch1()           __read_ulong_gc0_register(31, 2)
-#define read_gc0_kscratch2()           __read_ulong_gc0_register(31, 3)
-#define read_gc0_kscratch3()           __read_ulong_gc0_register(31, 4)
-#define read_gc0_kscratch4()           __read_ulong_gc0_register(31, 5)
-#define read_gc0_kscratch5()           __read_ulong_gc0_register(31, 6)
-#define read_gc0_kscratch6()           __read_ulong_gc0_register(31, 7)
-#define write_gc0_kscratch1(val)       __write_ulong_gc0_register(31, 2, val)
-#define write_gc0_kscratch2(val)       __write_ulong_gc0_register(31, 3, val)
-#define write_gc0_kscratch3(val)       __write_ulong_gc0_register(31, 4, val)
-#define write_gc0_kscratch4(val)       __write_ulong_gc0_register(31, 5, val)
-#define write_gc0_kscratch5(val)       __write_ulong_gc0_register(31, 6, val)
-#define write_gc0_kscratch6(val)       __write_ulong_gc0_register(31, 7, val)
+#define read_gc0_pwctl()               __read_32bit_gc0_register($6, 6)
+#define write_gc0_pwctl(val)           __write_32bit_gc0_register($6, 6, val)
+
+#define read_gc0_hwrena()              __read_32bit_gc0_register($7, 0)
+#define write_gc0_hwrena(val)          __write_32bit_gc0_register($7, 0, val)
+
+#define read_gc0_badvaddr()            __read_ulong_gc0_register($8, 0)
+#define write_gc0_badvaddr(val)                __write_ulong_gc0_register($8, 0, val)
+
+#define read_gc0_badinstr()            __read_32bit_gc0_register($8, 1)
+#define write_gc0_badinstr(val)                __write_32bit_gc0_register($8, 1, val)
+
+#define read_gc0_badinstrp()           __read_32bit_gc0_register($8, 2)
+#define write_gc0_badinstrp(val)       __write_32bit_gc0_register($8, 2, val)
+
+#define read_gc0_count()               __read_32bit_gc0_register($9, 0)
+
+#define read_gc0_entryhi()             __read_ulong_gc0_register($10, 0)
+#define write_gc0_entryhi(val)         __write_ulong_gc0_register($10, 0, val)
+
+#define read_gc0_compare()             __read_32bit_gc0_register($11, 0)
+#define write_gc0_compare(val)         __write_32bit_gc0_register($11, 0, val)
+
+#define read_gc0_status()              __read_32bit_gc0_register($12, 0)
+#define write_gc0_status(val)          __write_32bit_gc0_register($12, 0, val)
+
+#define read_gc0_intctl()              __read_32bit_gc0_register($12, 1)
+#define write_gc0_intctl(val)          __write_32bit_gc0_register($12, 1, val)
+
+#define read_gc0_cause()               __read_32bit_gc0_register($13, 0)
+#define write_gc0_cause(val)           __write_32bit_gc0_register($13, 0, val)
+
+#define read_gc0_epc()                 __read_ulong_gc0_register($14, 0)
+#define write_gc0_epc(val)             __write_ulong_gc0_register($14, 0, val)
+
+#define read_gc0_prid()                        __read_32bit_gc0_register($15, 0)
+
+#define read_gc0_ebase()               __read_32bit_gc0_register($15, 1)
+#define write_gc0_ebase(val)           __write_32bit_gc0_register($15, 1, val)
+
+#define read_gc0_ebase_64()            __read_64bit_gc0_register($15, 1)
+#define write_gc0_ebase_64(val)                __write_64bit_gc0_register($15, 1, val)
+
+#define read_gc0_config()              __read_32bit_gc0_register($16, 0)
+#define read_gc0_config1()             __read_32bit_gc0_register($16, 1)
+#define read_gc0_config2()             __read_32bit_gc0_register($16, 2)
+#define read_gc0_config3()             __read_32bit_gc0_register($16, 3)
+#define read_gc0_config4()             __read_32bit_gc0_register($16, 4)
+#define read_gc0_config5()             __read_32bit_gc0_register($16, 5)
+#define read_gc0_config6()             __read_32bit_gc0_register($16, 6)
+#define read_gc0_config7()             __read_32bit_gc0_register($16, 7)
+#define write_gc0_config(val)          __write_32bit_gc0_register($16, 0, val)
+#define write_gc0_config1(val)         __write_32bit_gc0_register($16, 1, val)
+#define write_gc0_config2(val)         __write_32bit_gc0_register($16, 2, val)
+#define write_gc0_config3(val)         __write_32bit_gc0_register($16, 3, val)
+#define write_gc0_config4(val)         __write_32bit_gc0_register($16, 4, val)
+#define write_gc0_config5(val)         __write_32bit_gc0_register($16, 5, val)
+#define write_gc0_config6(val)         __write_32bit_gc0_register($16, 6, val)
+#define write_gc0_config7(val)         __write_32bit_gc0_register($16, 7, val)
+
+#define read_gc0_lladdr()              __read_ulong_gc0_register($17, 0)
+#define write_gc0_lladdr(val)          __write_ulong_gc0_register($17, 0, val)
+
+#define read_gc0_watchlo0()            __read_ulong_gc0_register($18, 0)
+#define read_gc0_watchlo1()            __read_ulong_gc0_register($18, 1)
+#define read_gc0_watchlo2()            __read_ulong_gc0_register($18, 2)
+#define read_gc0_watchlo3()            __read_ulong_gc0_register($18, 3)
+#define read_gc0_watchlo4()            __read_ulong_gc0_register($18, 4)
+#define read_gc0_watchlo5()            __read_ulong_gc0_register($18, 5)
+#define read_gc0_watchlo6()            __read_ulong_gc0_register($18, 6)
+#define read_gc0_watchlo7()            __read_ulong_gc0_register($18, 7)
+#define write_gc0_watchlo0(val)                __write_ulong_gc0_register($18, 0, val)
+#define write_gc0_watchlo1(val)                __write_ulong_gc0_register($18, 1, val)
+#define write_gc0_watchlo2(val)                __write_ulong_gc0_register($18, 2, val)
+#define write_gc0_watchlo3(val)                __write_ulong_gc0_register($18, 3, val)
+#define write_gc0_watchlo4(val)                __write_ulong_gc0_register($18, 4, val)
+#define write_gc0_watchlo5(val)                __write_ulong_gc0_register($18, 5, val)
+#define write_gc0_watchlo6(val)                __write_ulong_gc0_register($18, 6, val)
+#define write_gc0_watchlo7(val)                __write_ulong_gc0_register($18, 7, val)
+
+#define read_gc0_watchhi0()            __read_32bit_gc0_register($19, 0)
+#define read_gc0_watchhi1()            __read_32bit_gc0_register($19, 1)
+#define read_gc0_watchhi2()            __read_32bit_gc0_register($19, 2)
+#define read_gc0_watchhi3()            __read_32bit_gc0_register($19, 3)
+#define read_gc0_watchhi4()            __read_32bit_gc0_register($19, 4)
+#define read_gc0_watchhi5()            __read_32bit_gc0_register($19, 5)
+#define read_gc0_watchhi6()            __read_32bit_gc0_register($19, 6)
+#define read_gc0_watchhi7()            __read_32bit_gc0_register($19, 7)
+#define write_gc0_watchhi0(val)                __write_32bit_gc0_register($19, 0, val)
+#define write_gc0_watchhi1(val)                __write_32bit_gc0_register($19, 1, val)
+#define write_gc0_watchhi2(val)                __write_32bit_gc0_register($19, 2, val)
+#define write_gc0_watchhi3(val)                __write_32bit_gc0_register($19, 3, val)
+#define write_gc0_watchhi4(val)                __write_32bit_gc0_register($19, 4, val)
+#define write_gc0_watchhi5(val)                __write_32bit_gc0_register($19, 5, val)
+#define write_gc0_watchhi6(val)                __write_32bit_gc0_register($19, 6, val)
+#define write_gc0_watchhi7(val)                __write_32bit_gc0_register($19, 7, val)
+
+#define read_gc0_xcontext()            __read_ulong_gc0_register($20, 0)
+#define write_gc0_xcontext(val)                __write_ulong_gc0_register($20, 0, val)
+
+#define read_gc0_perfctrl0()           __read_32bit_gc0_register($25, 0)
+#define write_gc0_perfctrl0(val)       __write_32bit_gc0_register($25, 0, val)
+#define read_gc0_perfcntr0()           __read_32bit_gc0_register($25, 1)
+#define write_gc0_perfcntr0(val)       __write_32bit_gc0_register($25, 1, val)
+#define read_gc0_perfcntr0_64()                __read_64bit_gc0_register($25, 1)
+#define write_gc0_perfcntr0_64(val)    __write_64bit_gc0_register($25, 1, val)
+#define read_gc0_perfctrl1()           __read_32bit_gc0_register($25, 2)
+#define write_gc0_perfctrl1(val)       __write_32bit_gc0_register($25, 2, val)
+#define read_gc0_perfcntr1()           __read_32bit_gc0_register($25, 3)
+#define write_gc0_perfcntr1(val)       __write_32bit_gc0_register($25, 3, val)
+#define read_gc0_perfcntr1_64()                __read_64bit_gc0_register($25, 3)
+#define write_gc0_perfcntr1_64(val)    __write_64bit_gc0_register($25, 3, val)
+#define read_gc0_perfctrl2()           __read_32bit_gc0_register($25, 4)
+#define write_gc0_perfctrl2(val)       __write_32bit_gc0_register($25, 4, val)
+#define read_gc0_perfcntr2()           __read_32bit_gc0_register($25, 5)
+#define write_gc0_perfcntr2(val)       __write_32bit_gc0_register($25, 5, val)
+#define read_gc0_perfcntr2_64()                __read_64bit_gc0_register($25, 5)
+#define write_gc0_perfcntr2_64(val)    __write_64bit_gc0_register($25, 5, val)
+#define read_gc0_perfctrl3()           __read_32bit_gc0_register($25, 6)
+#define write_gc0_perfctrl3(val)       __write_32bit_gc0_register($25, 6, val)
+#define read_gc0_perfcntr3()           __read_32bit_gc0_register($25, 7)
+#define write_gc0_perfcntr3(val)       __write_32bit_gc0_register($25, 7, val)
+#define read_gc0_perfcntr3_64()                __read_64bit_gc0_register($25, 7)
+#define write_gc0_perfcntr3_64(val)    __write_64bit_gc0_register($25, 7, val)
+
+#define read_gc0_errorepc()            __read_ulong_gc0_register($30, 0)
+#define write_gc0_errorepc(val)                __write_ulong_gc0_register($30, 0, val)
+
+#define read_gc0_kscratch1()           __read_ulong_gc0_register($31, 2)
+#define read_gc0_kscratch2()           __read_ulong_gc0_register($31, 3)
+#define read_gc0_kscratch3()           __read_ulong_gc0_register($31, 4)
+#define read_gc0_kscratch4()           __read_ulong_gc0_register($31, 5)
+#define read_gc0_kscratch5()           __read_ulong_gc0_register($31, 6)
+#define read_gc0_kscratch6()           __read_ulong_gc0_register($31, 7)
+#define write_gc0_kscratch1(val)       __write_ulong_gc0_register($31, 2, val)
+#define write_gc0_kscratch2(val)       __write_ulong_gc0_register($31, 3, val)
+#define write_gc0_kscratch3(val)       __write_ulong_gc0_register($31, 4, val)
+#define write_gc0_kscratch4(val)       __write_ulong_gc0_register($31, 5, val)
+#define write_gc0_kscratch5(val)       __write_ulong_gc0_register($31, 6, val)
+#define write_gc0_kscratch6(val)       __write_ulong_gc0_register($31, 7, val)
 
 /* Cavium OCTEON (cnMIPS) */
-#define read_gc0_cvmcount()            __read_ulong_gc0_register(9, 6)
-#define write_gc0_cvmcount(val)                __write_ulong_gc0_register(9, 6, val)
+#define read_gc0_cvmcount()            __read_ulong_gc0_register($9, 6)
+#define write_gc0_cvmcount(val)                __write_ulong_gc0_register($9, 6, val)
 
-#define read_gc0_cvmctl()              __read_64bit_gc0_register(9, 7)
-#define write_gc0_cvmctl(val)          __write_64bit_gc0_register(9, 7, val)
+#define read_gc0_cvmctl()              __read_64bit_gc0_register($9, 7)
+#define write_gc0_cvmctl(val)          __write_64bit_gc0_register($9, 7, val)
 
-#define read_gc0_cvmmemctl()           __read_64bit_gc0_register(11, 7)
-#define write_gc0_cvmmemctl(val)       __write_64bit_gc0_register(11, 7, val)
+#define read_gc0_cvmmemctl()           __read_64bit_gc0_register($11, 7)
+#define write_gc0_cvmmemctl(val)       __write_64bit_gc0_register($11, 7, val)
 
-#define read_gc0_cvmmemctl2()          __read_64bit_gc0_register(16, 6)
-#define write_gc0_cvmmemctl2(val)      __write_64bit_gc0_register(16, 6, val)
+#define read_gc0_cvmmemctl2()          __read_64bit_gc0_register($16, 6)
+#define write_gc0_cvmmemctl2(val)      __write_64bit_gc0_register($16, 6, val)
 
 /*
  * Macros to access the floating point coprocessor control registers
@@ -2581,8 +2651,6 @@ static inline void tlb_write_random(void)
                ".set reorder");
 }
 
-#ifdef TOOLCHAIN_SUPPORTS_VIRT
-
 /*
  * Guest TLB operations.
  *
@@ -2593,7 +2661,7 @@ static inline void guest_tlb_probe(void)
        __asm__ __volatile__(
                ".set push\n\t"
                ".set noreorder\n\t"
-               ".set virt\n\t"
+               _ASM_SET_VIRT
                "tlbgp\n\t"
                ".set pop");
 }
@@ -2603,7 +2671,7 @@ static inline void guest_tlb_read(void)
        __asm__ __volatile__(
                ".set push\n\t"
                ".set noreorder\n\t"
-               ".set virt\n\t"
+               _ASM_SET_VIRT
                "tlbgr\n\t"
                ".set pop");
 }
@@ -2613,7 +2681,7 @@ static inline void guest_tlb_write_indexed(void)
        __asm__ __volatile__(
                ".set push\n\t"
                ".set noreorder\n\t"
-               ".set virt\n\t"
+               _ASM_SET_VIRT
                "tlbgwi\n\t"
                ".set pop");
 }
@@ -2623,7 +2691,7 @@ static inline void guest_tlb_write_random(void)
        __asm__ __volatile__(
                ".set push\n\t"
                ".set noreorder\n\t"
-               ".set virt\n\t"
+               _ASM_SET_VIRT
                "tlbgwr\n\t"
                ".set pop");
 }
@@ -2636,63 +2704,11 @@ static inline void guest_tlbinvf(void)
        __asm__ __volatile__(
                ".set push\n\t"
                ".set noreorder\n\t"
-               ".set virt\n\t"
+               _ASM_SET_VIRT
                "tlbginvf\n\t"
                ".set pop");
 }
 
-#else  /* TOOLCHAIN_SUPPORTS_VIRT */
-
-/*
- * Guest TLB operations.
- *
- * It is responsibility of the caller to take care of any TLB hazards.
- */
-static inline void guest_tlb_probe(void)
-{
-       __asm__ __volatile__(
-               "# tlbgp\n\t"
-               _ASM_INSN_IF_MIPS(0x42000010)
-               _ASM_INSN32_IF_MM(0x0000017c));
-}
-
-static inline void guest_tlb_read(void)
-{
-       __asm__ __volatile__(
-               "# tlbgr\n\t"
-               _ASM_INSN_IF_MIPS(0x42000009)
-               _ASM_INSN32_IF_MM(0x0000117c));
-}
-
-static inline void guest_tlb_write_indexed(void)
-{
-       __asm__ __volatile__(
-               "# tlbgwi\n\t"
-               _ASM_INSN_IF_MIPS(0x4200000a)
-               _ASM_INSN32_IF_MM(0x0000217c));
-}
-
-static inline void guest_tlb_write_random(void)
-{
-       __asm__ __volatile__(
-               "# tlbgwr\n\t"
-               _ASM_INSN_IF_MIPS(0x4200000e)
-               _ASM_INSN32_IF_MM(0x0000317c));
-}
-
-/*
- * Guest TLB Invalidate Flush
- */
-static inline void guest_tlbinvf(void)
-{
-       __asm__ __volatile__(
-               "# tlbginvf\n\t"
-               _ASM_INSN_IF_MIPS(0x4200000c)
-               _ASM_INSN32_IF_MM(0x0000517c));
-}
-
-#endif /* !TOOLCHAIN_SUPPORTS_VIRT */
-
 /*
  * Manipulate bits in a register.
  */
index b1845102f8f9d28f7ae424f9b10904a7eef9b13f..b4f9577ed96a66656d5a940a8e7656811573c2c5 100644 (file)
@@ -160,7 +160,23 @@ static inline void init_msa_upper(void)
        _init_msa_upper();
 }
 
-#ifdef TOOLCHAIN_SUPPORTS_MSA
+#ifndef TOOLCHAIN_SUPPORTS_MSA
+/*
+ * Define assembler macros using .word for the c[ft]cmsa instructions in order
+ * to allow compilation with toolchains that do not support MSA. Once all
+ * toolchains in use support MSA these can be removed.
+ */
+_ASM_MACRO_2R(cfcmsa, rd, cs,
+       _ASM_INSN_IF_MIPS(0x787e0019 | __cs << 11 | __rd << 6)
+       _ASM_INSN32_IF_MM(0x587e0016 | __cs << 11 | __rd << 6));
+_ASM_MACRO_2R(ctcmsa, cd, rs,
+       _ASM_INSN_IF_MIPS(0x783e0019 | __rs << 11 | __cd << 6)
+       _ASM_INSN32_IF_MM(0x583e0016 | __rs << 11 | __cd << 6));
+#define _ASM_SET_MSA ""
+#else /* TOOLCHAIN_SUPPORTS_MSA */
+#define _ASM_SET_MSA ".set\tfp=64\n\t"                         \
+                    ".set\tmsa\n\t"
+#endif
 
 #define __BUILD_MSA_CTL_REG(name, cs)                          \
 static inline unsigned int read_msa_##name(void)               \
@@ -168,8 +184,7 @@ static inline unsigned int read_msa_##name(void)            \
        unsigned int reg;                                       \
        __asm__ __volatile__(                                   \
        "       .set    push\n"                                 \
-       "       .set    fp=64\n"                                \
-       "       .set    msa\n"                                  \
+       _ASM_SET_MSA                                            \
        "       cfcmsa  %0, $" #cs "\n"                         \
        "       .set    pop\n"                                  \
        : "=r"(reg));                                           \
@@ -180,52 +195,12 @@ static inline void write_msa_##name(unsigned int val)             \
 {                                                              \
        __asm__ __volatile__(                                   \
        "       .set    push\n"                                 \
-       "       .set    fp=64\n"                                \
-       "       .set    msa\n"                                  \
+       _ASM_SET_MSA                                            \
        "       ctcmsa  $" #cs ", %0\n"                         \
        "       .set    pop\n"                                  \
        : : "r"(val));                                          \
 }
 
-#else /* !TOOLCHAIN_SUPPORTS_MSA */
-
-/*
- * Define functions using .word for the c[ft]cmsa instructions in order to
- * allow compilation with toolchains that do not support MSA. Once all
- * toolchains in use support MSA these can be removed.
- */
-
-#define __BUILD_MSA_CTL_REG(name, cs)                          \
-static inline unsigned int read_msa_##name(void)               \
-{                                                              \
-       unsigned int reg;                                       \
-       __asm__ __volatile__(                                   \
-       "       .set    push\n"                                 \
-       "       .set    noat\n"                                 \
-       "       # cfcmsa $1, $%1\n"                             \
-       _ASM_INSN_IF_MIPS(0x787e0059 | %1 << 11)                \
-       _ASM_INSN32_IF_MM(0x587e0056 | %1 << 11)                \
-       "       move    %0, $1\n"                               \
-       "       .set    pop\n"                                  \
-       : "=r"(reg) : "i"(cs));                                 \
-       return reg;                                             \
-}                                                              \
-                                                               \
-static inline void write_msa_##name(unsigned int val)          \
-{                                                              \
-       __asm__ __volatile__(                                   \
-       "       .set    push\n"                                 \
-       "       .set    noat\n"                                 \
-       "       move    $1, %0\n"                               \
-       "       # ctcmsa $%1, $1\n"                             \
-       _ASM_INSN_IF_MIPS(0x783e0819 | %1 << 6)                 \
-       _ASM_INSN32_IF_MM(0x583e0816 | %1 << 6)                 \
-       "       .set    pop\n"                                  \
-       : : "r"(val), "i"(cs));                                 \
-}
-
-#endif /* !TOOLCHAIN_SUPPORTS_MSA */
-
 __BUILD_MSA_CTL_REG(ir, 0)
 __BUILD_MSA_CTL_REG(csr, 1)
 __BUILD_MSA_CTL_REG(access, 2)
index 643af2012e143cf30e6f3d9bec4fc42c3f0780fb..4dd0c446ecec71d37678e273ea2bc9618f680a80 100644 (file)
@@ -8,6 +8,10 @@ config JZ4740_QI_LB60
        bool "Qi Hardware Ben NanoNote"
        select MACH_JZ4740
 
+config JZ4770_GCW0
+       bool "Game Consoles Worldwide GCW Zero"
+       select MACH_JZ4770
+
 config JZ4780_CI20
        bool "MIPS Creator CI20"
        select MACH_JZ4780
@@ -18,6 +22,12 @@ config MACH_JZ4740
        bool
        select SYS_HAS_CPU_MIPS32_R1
 
+config MACH_JZ4770
+       bool
+       select MIPS_CPU_SCACHE
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_SUPPORTS_HIGHMEM
+
 config MACH_JZ4780
        bool
        select MIPS_CPU_SCACHE
index 47e857194ce66aaa5e1b8428c14871d630745fac..eb9f2f97bedb66132037ea9231261671c3ac865f 100644 (file)
 #include <linux/serial_reg.h>
 
 #include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
 #include <asm/mach-jz4740/base.h>
 
-static __init void jz4740_init_cmdline(int argc, char *argv[])
-{
-       unsigned int count = COMMAND_LINE_SIZE - 1;
-       int i;
-       char *dst = &(arcs_cmdline[0]);
-       char *src;
-
-       for (i = 1; i < argc && count; ++i) {
-               src = argv[i];
-               while (*src && count) {
-                       *dst++ = *src++;
-                       --count;
-               }
-               *dst++ = ' ';
-       }
-       if (i > 1)
-               --dst;
-
-       *dst = 0;
-}
-
 void __init prom_init(void)
 {
-       jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1);
-       mips_machtype = MACH_INGENIC_JZ4740;
+       fw_init_cmdline();
 }
 
 void __init prom_free_prom_memory(void)
index 6d0152321819b823200b8082bed7e757078f47fd..afb40f8bce961200cdf1d1eaa694129acaec9a7d 100644 (file)
@@ -53,6 +53,16 @@ static void __init jz4740_detect_mem(void)
        add_memory_region(0, size, BOOT_MEM_RAM);
 }
 
+static unsigned long __init get_board_mach_type(const void *fdt)
+{
+       if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4780"))
+               return MACH_INGENIC_JZ4780;
+       if (!fdt_node_check_compatible(fdt, 0, "ingenic,jz4770"))
+               return MACH_INGENIC_JZ4770;
+
+       return MACH_INGENIC_JZ4740;
+}
+
 void __init plat_mem_setup(void)
 {
        int offset;
@@ -63,6 +73,8 @@ void __init plat_mem_setup(void)
        offset = fdt_path_offset(__dtb_start, "/memory");
        if (offset < 0)
                jz4740_detect_mem();
+
+       mips_machtype = get_board_mach_type(__dtb_start);
 }
 
 void __init device_tree_init(void)
@@ -75,10 +87,14 @@ void __init device_tree_init(void)
 
 const char *get_system_type(void)
 {
-       if (IS_ENABLED(CONFIG_MACH_JZ4780))
+       switch (mips_machtype) {
+       case MACH_INGENIC_JZ4780:
                return "JZ4780";
-
-       return "JZ4740";
+       case MACH_INGENIC_JZ4770:
+               return "JZ4770";
+       default:
+               return "JZ4740";
+       }
 }
 
 void __init arch_init_irq(void)
index bb1ad5119da4e90f35b1bdfba16fdcbf118bb61c..2ca9160f642a23ba8b62d1149b8ef0dab5964514 100644 (file)
@@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
 #ifdef CONFIG_MACH_JZ4740
        .irq = JZ4740_IRQ_TCU0,
 #endif
-#ifdef CONFIG_MACH_JZ4780
+#if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
        .irq = JZ4780_IRQ_TCU2,
 #endif
 };
index b79ed9af98860f09e7b9691bd1ccd9b0ec95546b..e48f6c0a9e4a39522f5925cb9716065232cc2de0 100644 (file)
@@ -399,7 +399,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
  *
  * @regs:      Pointer to pt_regs
  * @insn:      branch instruction to decode
- * @returns:   -EFAULT on error and forces SIGILL, and on success
+ * Return:     -EFAULT on error and forces SIGILL, and on success
  *             returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
  *             evaluating the branch.
  *
index 99285be0e0884c9f6d5d6b9506b7b2b221b4b918..7f3dfdbc3657e6705b6a797c6e1dfa565fa3bff9 100644 (file)
@@ -361,7 +361,7 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
         * If fails when getting the stack address of the non-leaf function's
         * ra, stop function graph tracer and return
         */
-       if (parent_ra_addr == 0)
+       if (parent_ra_addr == NULL)
                goto out;
 #endif
        /* *parent_ra_addr = return_hooker; */
index 702c678de1166bd7cbef012cb2c00d556f85666c..85bc601e9a0d43ffd89669eac4b359de99566083 100644 (file)
@@ -826,25 +826,6 @@ static void __init arch_mem_init(char **cmdline_p)
        struct memblock_region *reg;
        extern void plat_mem_setup(void);
 
-       /* call board setup routine */
-       plat_mem_setup();
-
-       /*
-        * Make sure all kernel memory is in the maps.  The "UP" and
-        * "DOWN" are opposite for initdata since if it crosses over
-        * into another memory section you don't want that to be
-        * freed when the initdata is freed.
-        */
-       arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
-                        PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
-                        BOOT_MEM_RAM);
-       arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
-                        PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
-                        BOOT_MEM_INIT_RAM);
-
-       pr_info("Determined physical RAM map:\n");
-       print_memory_map();
-
 #if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
        strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
 #else
@@ -872,6 +853,26 @@ static void __init arch_mem_init(char **cmdline_p)
        }
 #endif
 #endif
+
+       /* call board setup routine */
+       plat_mem_setup();
+
+       /*
+        * Make sure all kernel memory is in the maps.  The "UP" and
+        * "DOWN" are opposite for initdata since if it crosses over
+        * into another memory section you don't want that to be
+        * freed when the initdata is freed.
+        */
+       arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
+                        PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
+                        BOOT_MEM_RAM);
+       arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
+                        PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
+                        BOOT_MEM_INIT_RAM);
+
+       pr_info("Determined physical RAM map:\n");
+       print_memory_map();
+
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 
        *cmdline_p = command_line;
index ecc1a853f48d4225b72ea0dd7299c64e450653c1..03f1026ad14841f902f40aa61c8bbcbd1af46eb9 100644 (file)
@@ -439,8 +439,6 @@ void play_dead(void)
        pr_debug("CPU%d going offline\n", cpu);
 
        if (cpu_has_mipsmt || cpu_has_vp) {
-               core = cpu_core(&cpu_data[cpu]);
-
                /* Look for another online VPE within the core */
                for_each_online_cpu(cpu_death_sibling) {
                        if (!cpus_are_siblings(cpu, cpu_death_sibling))
index 19fcab7348b16d9ab8538fdc8b83c342ac7a8486..0e61a5b7647f2d18cbb88558d3319f729f0699b2 100644 (file)
 void mips_install_watch_registers(struct task_struct *t)
 {
        struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264;
+       unsigned int watchhi = MIPS_WATCHHI_G |         /* Trap all ASIDs */
+                              MIPS_WATCHHI_IRW;        /* Clear result bits */
+
        switch (current_cpu_data.watch_reg_use_cnt) {
        default:
                BUG();
        case 4:
                write_c0_watchlo3(watches->watchlo[3]);
-               /* Write 1 to the I, R, and W bits to clear them, and
-                  1 to G so all ASIDs are trapped. */
-               write_c0_watchhi3(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
-                                 watches->watchhi[3]);
+               write_c0_watchhi3(watchhi | watches->watchhi[3]);
        case 3:
                write_c0_watchlo2(watches->watchlo[2]);
-               write_c0_watchhi2(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
-                                 watches->watchhi[2]);
+               write_c0_watchhi2(watchhi | watches->watchhi[2]);
        case 2:
                write_c0_watchlo1(watches->watchlo[1]);
-               write_c0_watchhi1(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
-                                 watches->watchhi[1]);
+               write_c0_watchhi1(watchhi | watches->watchhi[1]);
        case 1:
                write_c0_watchlo0(watches->watchlo[0]);
-               write_c0_watchhi0(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
-                                 watches->watchhi[0]);
+               write_c0_watchhi0(watchhi | watches->watchhi[0]);
        }
 }
 
@@ -51,21 +48,19 @@ void mips_read_watch_registers(void)
 {
        struct mips3264_watch_reg_state *watches =
                &current->thread.watch.mips3264;
+       unsigned int watchhi_mask = MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW;
+
        switch (current_cpu_data.watch_reg_use_cnt) {
        default:
                BUG();
        case 4:
-               watches->watchhi[3] = (read_c0_watchhi3() &
-                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
+               watches->watchhi[3] = (read_c0_watchhi3() & watchhi_mask);
        case 3:
-               watches->watchhi[2] = (read_c0_watchhi2() &
-                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
+               watches->watchhi[2] = (read_c0_watchhi2() & watchhi_mask);
        case 2:
-               watches->watchhi[1] = (read_c0_watchhi1() &
-                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
+               watches->watchhi[1] = (read_c0_watchhi1() & watchhi_mask);
        case 1:
-               watches->watchhi[0] = (read_c0_watchhi0() &
-                                      (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
+               watches->watchhi[0] = (read_c0_watchhi0() & watchhi_mask);
        }
        if (current_cpu_data.watch_reg_use_cnt == 1 &&
            (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) {
index 6f109bb54cdbd843ec03fb6d59b4328edd7c01fe..bc2fdbfa8223c343e6ed455f44bf6393d8d43d0a 100644 (file)
@@ -17,7 +17,6 @@ config LEMOTE_FULOONG2E
        select I8259
        select ISA
        select IRQ_MIPS_CPU
-       select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_HIGHMEM
@@ -49,7 +48,6 @@ config LEMOTE_MACH2F
        select ISA
        select SYS_HAS_CPU_LOONGSON2F
        select SYS_HAS_EARLY_PRINTK
-       select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_HIGHMEM
        select SYS_SUPPORTS_LITTLE_ENDIAN
index b01d52473da81450d9486cf8da36f8b48cee082e..c549e525fc11f80124753a296a46fac025fc1894 100644 (file)
@@ -79,7 +79,7 @@ void __init prom_init_memory(void)
                                        (u64)loongson_memmap->map[i].mem_size << 20,
                                        BOOT_MEM_RAM);
                                break;
-                       case MEM_RESERVED:
+                       case SYSTEM_RAM_RESERVED:
                                add_memory_region(loongson_memmap->map[i].mem_start,
                                        (u64)loongson_memmap->map[i].mem_size << 20,
                                        BOOT_MEM_RESERVED);
index f17ef520799aef0d827b15b0e0530f65013b9212..9717106de4a5a33c32f2261c0e21a2eb1f7fd87a 100644 (file)
@@ -166,7 +166,7 @@ static void __init szmem(unsigned int node)
                        memblock_add_node(PFN_PHYS(start_pfn),
                                PFN_PHYS(end_pfn - start_pfn), node);
                        break;
-               case MEM_RESERVED:
+               case SYSTEM_RAM_RESERVED:
                        pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
                                (u32)node_id, mem_type, mem_start, mem_size);
                        add_memory_region((node_id << 44) + mem_start,
index da6c1c0c30c11685e3251e5fd1f7aa673714a0cb..62deb025970bdd5391f1288a554fa24d14070bf5 100644 (file)
@@ -451,7 +451,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                                        regs->cp0_epc + dec_insn.pc_inc +
                                        dec_insn.next_pc_inc;
                        }
-                       /* Fall through */
+                       /* fall through */
                case jr_op:
                        /* For R6, JR already emulated in jalr_op */
                        if (NO_R6EMU && insn.r_format.func == jr_op)
@@ -471,10 +471,11 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                        regs->regs[31] = regs->cp0_epc +
                                dec_insn.pc_inc +
                                dec_insn.next_pc_inc;
-                       /* Fall through */
+                       /* fall through */
                case bltzl_op:
                        if (NO_R6EMU)
                                break;
+                       /* fall through */
                case bltz_op:
                        if ((long)regs->regs[insn.i_format.rs] < 0)
                                *contpc = regs->cp0_epc +
@@ -494,10 +495,11 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                        regs->regs[31] = regs->cp0_epc +
                                dec_insn.pc_inc +
                                dec_insn.next_pc_inc;
-                       /* Fall through */
+                       /* fall through */
                case bgezl_op:
                        if (NO_R6EMU)
                                break;
+                       /* fall through */
                case bgez_op:
                        if ((long)regs->regs[insn.i_format.rs] >= 0)
                                *contpc = regs->cp0_epc +
@@ -512,11 +514,12 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                break;
        case jalx_op:
                set_isa16_mode(bit);
+               /* fall through */
        case jal_op:
                regs->regs[31] = regs->cp0_epc +
                        dec_insn.pc_inc +
                        dec_insn.next_pc_inc;
-               /* Fall through */
+               /* fall through */
        case j_op:
                *contpc = regs->cp0_epc + dec_insn.pc_inc;
                *contpc >>= 28;
@@ -528,6 +531,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
        case beql_op:
                if (NO_R6EMU)
                        break;
+               /* fall through */
        case beq_op:
                if (regs->regs[insn.i_format.rs] ==
                    regs->regs[insn.i_format.rt])
@@ -542,6 +546,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
        case bnel_op:
                if (NO_R6EMU)
                        break;
+               /* fall through */
        case bne_op:
                if (regs->regs[insn.i_format.rs] !=
                    regs->regs[insn.i_format.rt])
@@ -556,6 +561,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
        case blezl_op:
                if (!insn.i_format.rt && NO_R6EMU)
                        break;
+               /* fall through */
        case blez_op:
 
                /*
@@ -593,6 +599,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
        case bgtzl_op:
                if (!insn.i_format.rt && NO_R6EMU)
                        break;
+               /* fall through */
        case bgtz_op:
                /*
                 * Compact branches for R6 for the
@@ -729,7 +736,8 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 
                        return 1;
                }
-               /* R2/R6 compatible cop1 instruction. Fall through */
+               /* R2/R6 compatible cop1 instruction */
+               /* fall through */
        case cop2_op:
        case cop1x_op:
                if (insn.i_format.rs == bc_op) {
@@ -1190,7 +1198,8 @@ emul:
                        if (!cpu_has_mips_r6 || delay_slot(xcp))
                                return SIGILL;
 
-                       cond = likely = 0;
+                       likely = 0;
+                       cond = 0;
                        fpr = &current->thread.fpu.fpr[MIPSInst_RT(ir)];
                        bit0 = get_fpr32(fpr, 0) & 0x1;
                        switch (MIPSInst_RS(ir)) {
@@ -1220,14 +1229,14 @@ emul:
                        case bcfl_op:
                                if (cpu_has_mips_2_3_4_5_r)
                                        likely = 1;
-                               /* Fall through */
+                               /* fall through */
                        case bcf_op:
                                cond = !cond;
                                break;
                        case bctl_op:
                                if (cpu_has_mips_2_3_4_5_r)
                                        likely = 1;
-                               /* Fall through */
+                               /* fall through */
                        case bct_op:
                                break;
                        }
@@ -1353,7 +1362,8 @@ branch_common:
                                return SIGILL;
 
                        /* a real fpu computation instruction */
-                       if ((sig = fpu_emu(xcp, ctx, ir)))
+                       sig = fpu_emu(xcp, ctx, ir);
+                       if (sig)
                                return sig;
                }
                break;
index 8954ef031f843fe41b3feca15852985c2b1251d9..678de20e4cb16d84be6ee4d43e84b6644bd7093c 100644 (file)
@@ -104,8 +104,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
-
-               /* FALL THROUGH */
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                DPDNORMY;
index f4746f7c5f63b1f686d51b5a59fd6d5dcd85d0be..3063ae3ab3b9a0c94ce08fa007e34cd924bedf47 100644 (file)
@@ -103,6 +103,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                DPDNORMY;
index 5bec64f2884eb14103e53726e42a6e29563ff6b5..d1f984b40344e35719b667f63a0e5ec6d74159d3 100644 (file)
@@ -96,6 +96,7 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                DPDNORMY;
@@ -224,6 +225,7 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                DPDNORMY;
index a287b23818d82ed0cf59f9066032619dea8f991a..f98b96135c8dd41adaf961cf0b15501103b18c1a 100644 (file)
@@ -96,6 +96,7 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                DPDNORMY;
@@ -224,6 +225,7 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                DPDNORMY;
index 7ad79ed411f5b3a94695e0d85f55f511c2abf270..7ea2f82220267ad45198ce8ec7ccf3fc829fe89f 100644 (file)
@@ -16,7 +16,7 @@
 
 
 /* 128 bits shift right logical with rounding. */
-void srl128(u64 *hptr, u64 *lptr, int count)
+static void srl128(u64 *hptr, u64 *lptr, int count)
 {
        u64 low;
 
@@ -157,6 +157,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                if (zc == IEEE754_CLASS_INF)
@@ -173,7 +174,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
                if (zc == IEEE754_CLASS_INF)
                        return ieee754dp_inf(zs);
-               /* fall through to real computations */
+               /* continue to real computations */
        }
 
        /* Finally get to do some computation */
@@ -201,9 +202,6 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
         * Multiply 64 bits xm and ym to give 128 bits result in hrm:lrm.
         */
 
-       /* 32 * 32 => 64 */
-#define DPXMULT(x, y)  ((u64)(x) * (u64)y)
-
        lxm = xm;
        hxm = xm >> 32;
        lym = ym;
index 60c8bfe409473409653a5f6775cc59af039fc0ed..c34a6cdf1b253b59050a9a64c5e736bd1c491c4f 100644 (file)
@@ -101,6 +101,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                DPDNORMY;
@@ -128,9 +129,6 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)
         * Multiply 64 bits xm, ym to give high 64 bits rm with stickness.
         */
 
-       /* 32 * 32 => 64 */
-#define DPXMULT(x, y)  ((u64)(x) * (u64)y)
-
        lxm = xm;
        hxm = xm >> 32;
        lym = ym;
index cea907b83146018486c6910d9c2c39319d2fca10..1d26c92e529574dce37b7bdfebe7f3bf3139f9aa 100644 (file)
@@ -91,7 +91,8 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x)
                scalx -= 256;
        }
 
-       y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+       x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+       y = x;
 
        /* magic initial approximation to almost 8 sig. bits */
        yh = y.bits >> 32;
@@ -108,7 +109,8 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x)
 
        /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
        /* t=y*y; z=t;  pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
-       z = t = ieee754dp_mul(y, y);
+       t = ieee754dp_mul(y, y);
+       z = t;
        t.bexp += 0x001;
        t = ieee754dp_add(t, z);
        z = ieee754dp_mul(ieee754dp_sub(x, z), y);
@@ -140,7 +142,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x)
                switch (oldcsr.rm) {
                case FPU_CSR_RU:
                        y.bits += 1;
-                       /* drop through */
+                       /* fall through */
                case FPU_CSR_RN:
                        t.bits += 1;
                        break;
index fc17a781b9ae868890303f57b08eb6f7b7d72cd3..3cc48b86519bd505a46616177df0d828052e0f35 100644 (file)
@@ -106,7 +106,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                DPDNORMX;
-               /* FALL THROUGH */
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                /* normalize ym,ye */
index 9ba023004eb6ff7f03a796a3acae8b609e3faea6..a56707b75282a7fbdcf56f5cbf7b410b334275d6 100644 (file)
@@ -55,6 +55,9 @@ static inline int ieee754dp_finite(union ieee754dp x)
 #define XDPSRS1(v)     \
        (((v) >> 1) | ((v) & 1))
 
+/* 32bit * 32bit => 64bit unsigned integer multiplication */
+#define DPXMULT(x, y)  ((u64)(x) * (u64)y)
+
 /* convert denormal to normalized with extended exponent */
 #define DPDNORMx(m,e) \
        while ((m >> DP_FBITS) == 0) { m <<= 1; e--; }
index c55c0c00bca803b989825397aedb915f28359402..51dced9fbdaf56b1177bfd20e9f3edc6318e961e 100644 (file)
@@ -104,8 +104,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
-
-               /* FALL THROUGH */
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
index 23587b31ca8788f2d8cea79249887c9a5e345527..5d2904960eb895266eb20338b16e75c6dccf59b6 100644 (file)
@@ -103,6 +103,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
index 5060e8fdcb0b8817c5f6836e0a20273f08a79b52..36a50f9082d12419b6f3718d8efa2e236c68a0cf 100644 (file)
@@ -46,7 +46,8 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x)
        case IEEE754_CLASS_SNAN:
                x = ieee754dp_nanxcpt(x);
                EXPLODEXDP;
-               /* Fall through.  */
+               /* fall through */
+
        case IEEE754_CLASS_QNAN:
                y = ieee754sp_nan_fdp(xs, xm);
                if (!ieee754_csr.nan2008) {
index 74a5a00d2f22b87917cae25c02f9b4f568569dd0..22019ed691df10541c35b94535835f38c619a7b9 100644 (file)
@@ -96,6 +96,7 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
@@ -224,6 +225,7 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
index c51385f46b09968611764d26db082cbf680e8744..feaec3985ccacf16ad4dc8c35505719c5051c5ba 100644 (file)
@@ -96,6 +96,7 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
@@ -224,6 +225,7 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
index f823338dbb65d6f416fdc02f37cfd1d6a6664de2..07ba675401e24172ea762ec3e62b6c65702a822b 100644 (file)
@@ -126,6 +126,7 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                if (zc == IEEE754_CLASS_INF)
@@ -142,7 +143,7 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
                if (zc == IEEE754_CLASS_INF)
                        return ieee754sp_inf(zs);
-               /* fall through to real computations */
+               /* continue to real computations */
        }
 
        /* Finally get to do some computation */
index 4015101fbc37e3e2ca72dee3ebea8e57a525c21f..fde71e293ec466bb0e4ecdc87beed1e6cfea0569 100644 (file)
@@ -101,6 +101,7 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
index 67059c33a250a9e45bcdb4c18e84ad295fb9de6a..9cc83f012342ceea6cffdd70b7050152ff4ec854 100644 (file)
@@ -82,7 +82,8 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x)
 
        /* generate sqrt(x) bit by bit */
        ix += ix;
-       q = s = 0;              /* q = sqrt(x) */
+       s = 0;
+       q = 0;                  /* q = sqrt(x) */
        r = 0x01000000;         /* r = moving bit from right to left */
 
        while (r != 0) {
index dc998ed47295d677ccab8c1a1ea49c3aa09e9795..9f2ff72c3d6ba18659361353d5277c7a39d274bc 100644 (file)
@@ -106,6 +106,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
 
        case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
                SPDNORMX;
+               /* fall through */
 
        case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
                SPDNORMY;
index a2450c7e452a672fdeba96bba5a7c262c1b6e876..bca5ac9958010b6cf55afc0a8cfee7614a2ebe35 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include "ieee754sp.h"
-#include "ieee754dp.h"
 
 s64 ieee754sp_tlong(union ieee754sp x)
 {
index 237532e899194a029ccc7278a8e744fefcbadff5..dcafa43613b602a0130c2b82e379323872978bd8 100644 (file)
@@ -370,11 +370,6 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
        }
 }
 
-static int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-       return 0;
-}
-
 static int mips_dma_supported(struct device *dev, u64 mask)
 {
        return plat_dma_supported(dev, mask);
@@ -401,7 +396,6 @@ static const struct dma_map_ops mips_default_dma_map_ops = {
        .sync_single_for_device = mips_dma_sync_single_for_device,
        .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu,
        .sync_sg_for_device = mips_dma_sync_sg_for_device,
-       .mapping_error = mips_dma_mapping_error,
        .dma_supported = mips_dma_supported,
        .cache_sync = mips_dma_cache_sync,
 };
index 548acb7f85571ed14ad4fc538b083fdbee185237..394673991babccda251ad674b23a66609e12d08c 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/mmu_context.h>
 #include <asm/r4kcache.h>
 #include <asm/mips-cps.h>
+#include <asm/bootinfo.h>
 
 /*
  * MIPS32/MIPS64 L2 cache handling
@@ -220,6 +221,14 @@ static inline int __init mips_sc_probe(void)
        else
                return 0;
 
+       /*
+        * According to config2 it would be 5-ways, but that is contradicted
+        * by all documentation.
+        */
+       if (current_cpu_type() == CPU_JZRISC &&
+                               mips_machtype == MACH_INGENIC_JZ4770)
+               c->scache.ways = 4;
+
        c->scache.waysize = c->scache.sets * c->scache.linesz;
        c->scache.waybit = __ffs(c->scache.waysize);
 
index cd47b0664c2b93d648c9320fb19a2d32127f91cc..1456e4cdb5622faf68bc7a4f331e433057c5d0f4 100644 (file)
@@ -1,3 +1,4 @@
 obj-y                          += cgu.o
 obj-$(CONFIG_MACH_JZ4740)      += jz4740-cgu.o
+obj-$(CONFIG_MACH_JZ4770)      += jz4770-cgu.o
 obj-$(CONFIG_MACH_JZ4780)      += jz4780-cgu.o
index ab393637f7b0f80791657fa88f458df9b3e7b609..56a712c9075f367cacd0ff12904f3b4fd7e6c8bc 100644 (file)
@@ -100,15 +100,13 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        n += pll_info->n_offset;
        od_enc = ctl >> pll_info->od_shift;
        od_enc &= GENMASK(pll_info->od_bits - 1, 0);
-       bypass = !!(ctl & BIT(pll_info->bypass_bit));
+       bypass = !pll_info->no_bypass_bit &&
+                !!(ctl & BIT(pll_info->bypass_bit));
        enable = !!(ctl & BIT(pll_info->enable_bit));
 
        if (bypass)
                return parent_rate;
 
-       if (!enable)
-               return 0;
-
        for (od = 0; od < pll_info->od_max; od++) {
                if (pll_info->od_encoding[od] == od_enc)
                        break;
@@ -152,17 +150,25 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
        return div_u64((u64)parent_rate * m, n * od);
 }
 
-static long
-ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
-                      unsigned long *prate)
+static inline const struct ingenic_cgu_clk_info *to_clk_info(
+               struct ingenic_clk *ingenic_clk)
 {
-       struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
        struct ingenic_cgu *cgu = ingenic_clk->cgu;
        const struct ingenic_cgu_clk_info *clk_info;
 
        clk_info = &cgu->clock_info[ingenic_clk->idx];
        BUG_ON(clk_info->type != CGU_CLK_PLL);
 
+       return clk_info;
+}
+
+static long
+ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
+                      unsigned long *prate)
+{
+       struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+       const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+
        return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
 }
 
@@ -170,19 +176,14 @@ static int
 ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
                     unsigned long parent_rate)
 {
-       const unsigned timeout = 100;
        struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
        struct ingenic_cgu *cgu = ingenic_clk->cgu;
-       const struct ingenic_cgu_clk_info *clk_info;
-       const struct ingenic_cgu_pll_info *pll_info;
+       const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+       const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
        unsigned long rate, flags;
-       unsigned m, n, od, i;
+       unsigned int m, n, od;
        u32 ctl;
 
-       clk_info = &cgu->clock_info[ingenic_clk->idx];
-       BUG_ON(clk_info->type != CGU_CLK_PLL);
-       pll_info = &clk_info->pll;
-
        rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
                               &m, &n, &od);
        if (rate != req_rate)
@@ -201,6 +202,26 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
        ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
        ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
 
+       writel(ctl, cgu->base + pll_info->reg);
+       spin_unlock_irqrestore(&cgu->lock, flags);
+
+       return 0;
+}
+
+static int ingenic_pll_enable(struct clk_hw *hw)
+{
+       struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+       struct ingenic_cgu *cgu = ingenic_clk->cgu;
+       const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+       const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+       const unsigned int timeout = 100;
+       unsigned long flags;
+       unsigned int i;
+       u32 ctl;
+
+       spin_lock_irqsave(&cgu->lock, flags);
+       ctl = readl(cgu->base + pll_info->reg);
+
        ctl &= ~BIT(pll_info->bypass_bit);
        ctl |= BIT(pll_info->enable_bit);
 
@@ -222,10 +243,48 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
        return 0;
 }
 
+static void ingenic_pll_disable(struct clk_hw *hw)
+{
+       struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+       struct ingenic_cgu *cgu = ingenic_clk->cgu;
+       const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+       const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+       unsigned long flags;
+       u32 ctl;
+
+       spin_lock_irqsave(&cgu->lock, flags);
+       ctl = readl(cgu->base + pll_info->reg);
+
+       ctl &= ~BIT(pll_info->enable_bit);
+
+       writel(ctl, cgu->base + pll_info->reg);
+       spin_unlock_irqrestore(&cgu->lock, flags);
+}
+
+static int ingenic_pll_is_enabled(struct clk_hw *hw)
+{
+       struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+       struct ingenic_cgu *cgu = ingenic_clk->cgu;
+       const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
+       const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
+       unsigned long flags;
+       u32 ctl;
+
+       spin_lock_irqsave(&cgu->lock, flags);
+       ctl = readl(cgu->base + pll_info->reg);
+       spin_unlock_irqrestore(&cgu->lock, flags);
+
+       return !!(ctl & BIT(pll_info->enable_bit));
+}
+
 static const struct clk_ops ingenic_pll_ops = {
        .recalc_rate = ingenic_pll_recalc_rate,
        .round_rate = ingenic_pll_round_rate,
        .set_rate = ingenic_pll_set_rate,
+
+       .enable = ingenic_pll_enable,
+       .disable = ingenic_pll_disable,
+       .is_enabled = ingenic_pll_is_enabled,
 };
 
 /*
@@ -328,6 +387,8 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
                div *= clk_info->div.div;
 
                rate /= div;
+       } else if (clk_info->type & CGU_CLK_FIXDIV) {
+               rate /= clk_info->fixdiv.div;
        }
 
        return rate;
@@ -598,6 +659,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
                }
        } else if (caps & CGU_CLK_PLL) {
                clk_init.ops = &ingenic_pll_ops;
+               clk_init.flags |= CLK_SET_RATE_GATE;
 
                caps &= ~CGU_CLK_PLL;
 
index e78b586536ea3291523ad8da3d6da0d171b506da..9da34910bd800f8d11954a6c58ef5a7e4256c06a 100644 (file)
@@ -48,6 +48,7 @@
  * @bypass_bit: the index of the bypass bit in the PLL control register
  * @enable_bit: the index of the enable bit in the PLL control register
  * @stable_bit: the index of the stable bit in the PLL control register
+ * @no_bypass_bit: if set, the PLL has no bypass functionality
  */
 struct ingenic_cgu_pll_info {
        unsigned reg;
@@ -58,6 +59,7 @@ struct ingenic_cgu_pll_info {
        u8 bypass_bit;
        u8 enable_bit;
        u8 stable_bit;
+       bool no_bypass_bit;
 };
 
 /**
@@ -120,7 +122,7 @@ struct ingenic_cgu_gate_info {
  * @clk_ops: custom clock operation callbacks
  */
 struct ingenic_cgu_custom_info {
-       struct clk_ops *clk_ops;
+       const struct clk_ops *clk_ops;
 };
 
 /**
diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c
new file mode 100644 (file)
index 0000000..c78d369
--- /dev/null
@@ -0,0 +1,483 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * JZ4770 SoC CGU driver
+ * Copyright 2018, Paul Cercueil <paul@crapouillou.net>
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/jz4770-cgu.h>
+#include "cgu.h"
+
+/*
+ * CPM registers offset address definition
+ */
+#define CGU_REG_CPCCR          0x00
+#define CGU_REG_LCR            0x04
+#define CGU_REG_CPPCR0         0x10
+#define CGU_REG_CLKGR0         0x20
+#define CGU_REG_OPCR           0x24
+#define CGU_REG_CLKGR1         0x28
+#define CGU_REG_CPPCR1         0x30
+#define CGU_REG_USBPCR1                0x48
+#define CGU_REG_USBCDR         0x50
+#define CGU_REG_I2SCDR         0x60
+#define CGU_REG_LPCDR          0x64
+#define CGU_REG_MSC0CDR                0x68
+#define CGU_REG_UHCCDR         0x6c
+#define CGU_REG_SSICDR         0x74
+#define CGU_REG_CIMCDR         0x7c
+#define CGU_REG_GPSCDR         0x80
+#define CGU_REG_PCMCDR         0x84
+#define CGU_REG_GPUCDR         0x88
+#define CGU_REG_MSC1CDR                0xA4
+#define CGU_REG_MSC2CDR                0xA8
+#define CGU_REG_BCHCDR         0xAC
+
+/* bits within the LCR register */
+#define LCR_LPM                        BIT(0)          /* Low Power Mode */
+
+/* bits within the OPCR register */
+#define OPCR_SPENDH            BIT(5)          /* UHC PHY suspend */
+#define OPCR_SPENDN            BIT(7)          /* OTG PHY suspend */
+
+/* bits within the USBPCR1 register */
+#define USBPCR1_UHC_POWER      BIT(5)          /* UHC PHY power down */
+
+static struct ingenic_cgu *cgu;
+
+static int jz4770_uhc_phy_enable(struct clk_hw *hw)
+{
+       void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
+       void __iomem *reg_usbpcr1       = cgu->base + CGU_REG_USBPCR1;
+
+       writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
+       writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
+       return 0;
+}
+
+static void jz4770_uhc_phy_disable(struct clk_hw *hw)
+{
+       void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
+       void __iomem *reg_usbpcr1       = cgu->base + CGU_REG_USBPCR1;
+
+       writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
+       writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
+}
+
+static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
+{
+       void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
+       void __iomem *reg_usbpcr1       = cgu->base + CGU_REG_USBPCR1;
+
+       return !(readl(reg_opcr) & OPCR_SPENDH) &&
+               (readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
+}
+
+static const struct clk_ops jz4770_uhc_phy_ops = {
+       .enable = jz4770_uhc_phy_enable,
+       .disable = jz4770_uhc_phy_disable,
+       .is_enabled = jz4770_uhc_phy_is_enabled,
+};
+
+static int jz4770_otg_phy_enable(struct clk_hw *hw)
+{
+       void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
+
+       writel(readl(reg_opcr) | OPCR_SPENDN, reg_opcr);
+
+       /* Wait for the clock to be stable */
+       udelay(50);
+       return 0;
+}
+
+static void jz4770_otg_phy_disable(struct clk_hw *hw)
+{
+       void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
+
+       writel(readl(reg_opcr) & ~OPCR_SPENDN, reg_opcr);
+}
+
+static int jz4770_otg_phy_is_enabled(struct clk_hw *hw)
+{
+       void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
+
+       return !!(readl(reg_opcr) & OPCR_SPENDN);
+}
+
+static const struct clk_ops jz4770_otg_phy_ops = {
+       .enable = jz4770_otg_phy_enable,
+       .disable = jz4770_otg_phy_disable,
+       .is_enabled = jz4770_otg_phy_is_enabled,
+};
+
+static const s8 pll_od_encoding[8] = {
+       0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
+};
+
+static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
+
+       /* External clocks */
+
+       [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
+       [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
+
+       /* PLLs */
+
+       [JZ4770_CLK_PLL0] = {
+               "pll0", CGU_CLK_PLL,
+               .parents = { JZ4770_CLK_EXT },
+               .pll = {
+                       .reg = CGU_REG_CPPCR0,
+                       .m_shift = 24,
+                       .m_bits = 7,
+                       .m_offset = 1,
+                       .n_shift = 18,
+                       .n_bits = 5,
+                       .n_offset = 1,
+                       .od_shift = 16,
+                       .od_bits = 2,
+                       .od_max = 8,
+                       .od_encoding = pll_od_encoding,
+                       .bypass_bit = 9,
+                       .enable_bit = 8,
+                       .stable_bit = 10,
+               },
+       },
+
+       [JZ4770_CLK_PLL1] = {
+               /* TODO: PLL1 can depend on PLL0 */
+               "pll1", CGU_CLK_PLL,
+               .parents = { JZ4770_CLK_EXT },
+               .pll = {
+                       .reg = CGU_REG_CPPCR1,
+                       .m_shift = 24,
+                       .m_bits = 7,
+                       .m_offset = 1,
+                       .n_shift = 18,
+                       .n_bits = 5,
+                       .n_offset = 1,
+                       .od_shift = 16,
+                       .od_bits = 2,
+                       .od_max = 8,
+                       .od_encoding = pll_od_encoding,
+                       .enable_bit = 7,
+                       .stable_bit = 6,
+                       .no_bypass_bit = true,
+               },
+       },
+
+       /* Main clocks */
+
+       [JZ4770_CLK_CCLK] = {
+               "cclk", CGU_CLK_DIV,
+               .parents = { JZ4770_CLK_PLL0, },
+               .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
+       },
+       [JZ4770_CLK_H0CLK] = {
+               "h0clk", CGU_CLK_DIV,
+               .parents = { JZ4770_CLK_PLL0, },
+               .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
+       },
+       [JZ4770_CLK_H1CLK] = {
+               "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_PLL0, },
+               .div = { CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1 },
+               .gate = { CGU_REG_LCR, 30 },
+       },
+       [JZ4770_CLK_H2CLK] = {
+               "h2clk", CGU_CLK_DIV,
+               .parents = { JZ4770_CLK_PLL0, },
+               .div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 },
+       },
+       [JZ4770_CLK_C1CLK] = {
+               "c1clk", CGU_CLK_DIV,
+               .parents = { JZ4770_CLK_PLL0, },
+               .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
+       },
+       [JZ4770_CLK_PCLK] = {
+               "pclk", CGU_CLK_DIV,
+               .parents = { JZ4770_CLK_PLL0, },
+               .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
+       },
+
+       /* Those divided clocks can connect to PLL0 or PLL1 */
+
+       [JZ4770_CLK_MMC0_MUX] = {
+               "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_MSC0CDR, 30, 1 },
+               .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
+               .gate = { CGU_REG_MSC0CDR, 31 },
+       },
+       [JZ4770_CLK_MMC1_MUX] = {
+               "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_MSC1CDR, 30, 1 },
+               .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
+               .gate = { CGU_REG_MSC1CDR, 31 },
+       },
+       [JZ4770_CLK_MMC2_MUX] = {
+               "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_MSC2CDR, 30, 1 },
+               .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
+               .gate = { CGU_REG_MSC2CDR, 31 },
+       },
+       [JZ4770_CLK_CIM] = {
+               "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_CIMCDR, 31, 1 },
+               .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR0, 26 },
+       },
+       [JZ4770_CLK_UHC] = {
+               "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_UHCCDR, 29, 1 },
+               .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR0, 24 },
+       },
+       [JZ4770_CLK_GPU] = {
+               "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
+               .mux = { CGU_REG_GPUCDR, 31, 1 },
+               .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR1, 9 },
+       },
+       [JZ4770_CLK_BCH] = {
+               "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_BCHCDR, 31, 1 },
+               .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR0, 1 },
+       },
+       [JZ4770_CLK_LPCLK_MUX] = {
+               "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_LPCDR, 29, 1 },
+               .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR0, 28 },
+       },
+       [JZ4770_CLK_GPS] = {
+               "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
+               .mux = { CGU_REG_GPSCDR, 31, 1 },
+               .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR0, 22 },
+       },
+
+       /* Those divided clocks can connect to EXT, PLL0 or PLL1 */
+
+       [JZ4770_CLK_SSI_MUX] = {
+               "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_EXT, -1,
+                       JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+               .mux = { CGU_REG_SSICDR, 30, 2 },
+               .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
+       },
+       [JZ4770_CLK_PCM_MUX] = {
+               "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_EXT, -1,
+                       JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+               .mux = { CGU_REG_PCMCDR, 30, 2 },
+               .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
+       },
+       [JZ4770_CLK_I2S] = {
+               "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_EXT, -1,
+                       JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+               .mux = { CGU_REG_I2SCDR, 30, 2 },
+               .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR1, 13 },
+       },
+       [JZ4770_CLK_OTG] = {
+               "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_EXT, -1,
+                       JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
+               .mux = { CGU_REG_USBCDR, 30, 2 },
+               .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
+               .gate = { CGU_REG_CLKGR0, 2 },
+       },
+
+       /* Gate-only clocks */
+
+       [JZ4770_CLK_SSI0] = {
+               "ssi0", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_SSI_MUX, },
+               .gate = { CGU_REG_CLKGR0, 4 },
+       },
+       [JZ4770_CLK_SSI1] = {
+               "ssi1", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_SSI_MUX, },
+               .gate = { CGU_REG_CLKGR0, 19 },
+       },
+       [JZ4770_CLK_SSI2] = {
+               "ssi2", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_SSI_MUX, },
+               .gate = { CGU_REG_CLKGR0, 20 },
+       },
+       [JZ4770_CLK_PCM0] = {
+               "pcm0", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_PCM_MUX, },
+               .gate = { CGU_REG_CLKGR1, 8 },
+       },
+       [JZ4770_CLK_PCM1] = {
+               "pcm1", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_PCM_MUX, },
+               .gate = { CGU_REG_CLKGR1, 10 },
+       },
+       [JZ4770_CLK_DMA] = {
+               "dma", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_H2CLK, },
+               .gate = { CGU_REG_CLKGR0, 21 },
+       },
+       [JZ4770_CLK_I2C0] = {
+               "i2c0", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 5 },
+       },
+       [JZ4770_CLK_I2C1] = {
+               "i2c1", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 6 },
+       },
+       [JZ4770_CLK_I2C2] = {
+               "i2c2", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR1, 15 },
+       },
+       [JZ4770_CLK_UART0] = {
+               "uart0", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 15 },
+       },
+       [JZ4770_CLK_UART1] = {
+               "uart1", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 16 },
+       },
+       [JZ4770_CLK_UART2] = {
+               "uart2", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 17 },
+       },
+       [JZ4770_CLK_UART3] = {
+               "uart3", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 18 },
+       },
+       [JZ4770_CLK_IPU] = {
+               "ipu", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_H0CLK, },
+               .gate = { CGU_REG_CLKGR0, 29 },
+       },
+       [JZ4770_CLK_ADC] = {
+               "adc", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 14 },
+       },
+       [JZ4770_CLK_AIC] = {
+               "aic", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_EXT, },
+               .gate = { CGU_REG_CLKGR0, 8 },
+       },
+       [JZ4770_CLK_AUX] = {
+               "aux", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_C1CLK, },
+               .gate = { CGU_REG_CLKGR1, 14 },
+       },
+       [JZ4770_CLK_VPU] = {
+               "vpu", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_H1CLK, },
+               .gate = { CGU_REG_CLKGR1, 7 },
+       },
+       [JZ4770_CLK_MMC0] = {
+               "mmc0", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_MMC0_MUX, },
+               .gate = { CGU_REG_CLKGR0, 3 },
+       },
+       [JZ4770_CLK_MMC1] = {
+               "mmc1", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_MMC1_MUX, },
+               .gate = { CGU_REG_CLKGR0, 11 },
+       },
+       [JZ4770_CLK_MMC2] = {
+               "mmc2", CGU_CLK_GATE,
+               .parents = { JZ4770_CLK_MMC2_MUX, },
+               .gate = { CGU_REG_CLKGR0, 12 },
+       },
+
+       /* Custom clocks */
+
+       [JZ4770_CLK_UHC_PHY] = {
+               "uhc_phy", CGU_CLK_CUSTOM,
+               .parents = { JZ4770_CLK_UHC, -1, -1, -1 },
+               .custom = { &jz4770_uhc_phy_ops },
+       },
+       [JZ4770_CLK_OTG_PHY] = {
+               "usb_phy", CGU_CLK_CUSTOM,
+               .parents = { JZ4770_CLK_OTG, -1, -1, -1 },
+               .custom = { &jz4770_otg_phy_ops },
+       },
+
+       [JZ4770_CLK_EXT512] = {
+               "ext/512", CGU_CLK_FIXDIV,
+               .parents = { JZ4770_CLK_EXT },
+               .fixdiv = { 512 },
+       },
+
+       [JZ4770_CLK_RTC] = {
+               "rtc", CGU_CLK_MUX,
+               .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
+               .mux = { CGU_REG_OPCR, 2, 1},
+       },
+};
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+static int jz4770_cgu_pm_suspend(void)
+{
+       u32 val;
+
+       val = readl(cgu->base + CGU_REG_LCR);
+       writel(val | LCR_LPM, cgu->base + CGU_REG_LCR);
+       return 0;
+}
+
+static void jz4770_cgu_pm_resume(void)
+{
+       u32 val;
+
+       val = readl(cgu->base + CGU_REG_LCR);
+       writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR);
+}
+
+static struct syscore_ops jz4770_cgu_pm_ops = {
+       .suspend = jz4770_cgu_pm_suspend,
+       .resume = jz4770_cgu_pm_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static void __init jz4770_cgu_init(struct device_node *np)
+{
+       int retval;
+
+       cgu = ingenic_cgu_new(jz4770_cgu_clocks,
+                             ARRAY_SIZE(jz4770_cgu_clocks), np);
+       if (!cgu)
+               pr_err("%s: failed to initialise CGU\n", __func__);
+
+       retval = ingenic_cgu_register_clocks(cgu);
+       if (retval)
+               pr_err("%s: failed to register CGU Clocks\n", __func__);
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+       register_syscore_ops(&jz4770_cgu_pm_ops);
+#endif
+}
+
+/* We only probe via devicetree, no need for a platform driver */
+CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);
index ac3585ed82286ed978377662b34df3dab304da2e..6427be117ff117fce04b5c6b2d2d5b807f1ceb17 100644 (file)
@@ -203,7 +203,7 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
        return 0;
 }
 
-static struct clk_ops jz4780_otg_phy_ops = {
+static const struct clk_ops jz4780_otg_phy_ops = {
        .get_parent = jz4780_otg_phy_get_parent,
        .set_parent = jz4780_otg_phy_set_parent,
 
diff --git a/include/dt-bindings/clock/jz4770-cgu.h b/include/dt-bindings/clock/jz4770-cgu.h
new file mode 100644 (file)
index 0000000..d68a769
--- /dev/null
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides clock numbers for the ingenic,jz4770-cgu DT binding.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4770_CGU_H__
+
+#define JZ4770_CLK_EXT         0
+#define JZ4770_CLK_OSC32K      1
+#define JZ4770_CLK_PLL0                2
+#define JZ4770_CLK_PLL1                3
+#define JZ4770_CLK_CCLK                4
+#define JZ4770_CLK_H0CLK       5
+#define JZ4770_CLK_H1CLK       6
+#define JZ4770_CLK_H2CLK       7
+#define JZ4770_CLK_C1CLK       8
+#define JZ4770_CLK_PCLK                9
+#define JZ4770_CLK_MMC0_MUX    10
+#define JZ4770_CLK_MMC0                11
+#define JZ4770_CLK_MMC1_MUX    12
+#define JZ4770_CLK_MMC1                13
+#define JZ4770_CLK_MMC2_MUX    14
+#define JZ4770_CLK_MMC2                15
+#define JZ4770_CLK_CIM         16
+#define JZ4770_CLK_UHC         17
+#define JZ4770_CLK_GPU         18
+#define JZ4770_CLK_BCH         19
+#define JZ4770_CLK_LPCLK_MUX   20
+#define JZ4770_CLK_GPS         21
+#define JZ4770_CLK_SSI_MUX     22
+#define JZ4770_CLK_PCM_MUX     23
+#define JZ4770_CLK_I2S         24
+#define JZ4770_CLK_OTG         25
+#define JZ4770_CLK_SSI0                26
+#define JZ4770_CLK_SSI1                27
+#define JZ4770_CLK_SSI2                28
+#define JZ4770_CLK_PCM0                29
+#define JZ4770_CLK_PCM1                30
+#define JZ4770_CLK_DMA         31
+#define JZ4770_CLK_I2C0                32
+#define JZ4770_CLK_I2C1                33
+#define JZ4770_CLK_I2C2                34
+#define JZ4770_CLK_UART0       35
+#define JZ4770_CLK_UART1       36
+#define JZ4770_CLK_UART2       37
+#define JZ4770_CLK_UART3       38
+#define JZ4770_CLK_IPU         39
+#define JZ4770_CLK_ADC         40
+#define JZ4770_CLK_AIC         41
+#define JZ4770_CLK_AUX         42
+#define JZ4770_CLK_VPU         43
+#define JZ4770_CLK_UHC_PHY     44
+#define JZ4770_CLK_OTG_PHY     45
+#define JZ4770_CLK_EXT512      46
+#define JZ4770_CLK_RTC         47
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4770_CGU_H__ */