MIPS changes for 4.16

These are the main MIPS changes for 4.16. Rough overview:
  - Basic support for the Ingenic JZ4770 based GCW Zero open-source
    handheld video game console
  - Support for the Ranchu board (used by Android emulator)
  - Various cleanups and misc improvements
 
 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"
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEd80NauSabkiESfLYbAtpk944dnoFAlp64ZUACgkQbAtpk944
 dnrXrg//UPWeZMye/uHw0eEeJJjybyA0IWpJ6M94gbHxpduhQsjYU3CR9U4ZBmhs
 feY53dahh0RCR0k28EF8DEPkoUbGFKmyYCnvqAuatq1XOjAZtlgS9+VVzbK+Iswm
 XkZD1MBoZ49o0meyjQrH/2Ri/t6tHuzo0G2WtRJ8FnVruN9ymG6D5pR4Y31gDucb
 6JkTXjNfRJIKd0qJgP+c3HdlKE7jlnCTJnzHdA+5FbZVwKbm2/6KxbQo5Gc1BXJX
 4j7I4nJ0FIz0cB6fHbcccFSW9w3lPa9bQ4XpYPJYE6a36QldFvMWHRxvI6rxrACN
 5mPqIB9uqvtW8sdUbJtNRXFlNnm8XZzvsNqP6WxGQPW70+q2camni9W/gC1ifQsF
 +uVV54yj3Ky8xQNbbpfbDp/tFXRuLtj3DV4/a3dwA5J0YGEuMn1zzV5WTTzymFVn
 3NKl62LDUlzBNw0d1lUPMY6P1oKcNnRhLxBq0cxaB7AdOLF0jlCQ/wYUhXPpblj6
 CQB4cupR4IMvL7FZ1RS98e1RHaF8mXpaZBnGXT251DxZEre9OXCJxDdzqemedTVi
 SaCcvQqApCQD8OihL+wHZLew8Vp4EvwGAa++Evu/Ot4rWjY/9MGLtewYk8jkOEf6
 qk30dDn86ou29HNwpzfWadIq5Zew+QftifGOzTcuzgrJXXt+jH8=
 =7iwT
 -----END PGP SIGNATURE-----

Merge tag 'mips_4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/mips

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
  ...
This commit is contained in:
Linus Torvalds 2018-02-07 11:22:44 -08:00
commit 8578953687
77 changed files with 1627 additions and 531 deletions

View File

@ -125,6 +125,7 @@ focaltech FocalTech Systems Co.,Ltd
friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd
fsl Freescale Semiconductor fsl Freescale Semiconductor
fujitsu Fujitsu Ltd. fujitsu Fujitsu Ltd.
gcw Game Consoles Worldwide
ge General Electric Company ge General Electric Company
geekbuying GeekBuying geekbuying GeekBuying
gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc.

View File

@ -9188,6 +9188,7 @@ S: Supported
F: Documentation/devicetree/bindings/mips/ F: Documentation/devicetree/bindings/mips/
F: Documentation/mips/ F: Documentation/mips/
F: arch/mips/ F: arch/mips/
F: drivers/platform/mips/
MIPS BOSTON DEVELOPMENT BOARD MIPS BOSTON DEVELOPMENT BOARD
M: Paul Burton <paul.burton@mips.com> M: Paul Burton <paul.burton@mips.com>
@ -9215,6 +9216,25 @@ F: arch/mips/include/asm/mach-loongson32/
F: drivers/*/*loongson1* F: drivers/*/*loongson1*
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 MIPS RINT INSTRUCTION EMULATION
M: Aleksandar Markovic <aleksandar.markovic@mips.com> M: Aleksandar Markovic <aleksandar.markovic@mips.com>
L: linux-mips@linux-mips.org L: linux-mips@linux-mips.org
@ -11586,6 +11606,13 @@ S: Maintained
F: Documentation/blockdev/ramdisk.txt F: Documentation/blockdev/ramdisk.txt
F: drivers/block/brd.c 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 RANDOM NUMBER DRIVER
M: "Theodore Ts'o" <tytso@mit.edu> M: "Theodore Ts'o" <tytso@mit.edu>
S: Maintained S: Maintained

View File

@ -7,8 +7,6 @@ config MIPS
select ARCH_DISCARD_MEMBLOCK select ARCH_DISCARD_MEMBLOCK
select ARCH_HAS_ELF_RANDOMIZE select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST 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_SUPPORTS_UPROBES
select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if 64BIT select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
@ -119,12 +117,12 @@ config MIPS_GENERIC
select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_RELOCATABLE select SYS_SUPPORTS_RELOCATABLE
select SYS_SUPPORTS_SMARTMIPS select SYS_SUPPORTS_SMARTMIPS
select USB_EHCI_BIG_ENDIAN_DESC if BIG_ENDIAN select USB_EHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
select USB_EHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select USB_OHCI_BIG_ENDIAN_DESC if BIG_ENDIAN select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
select USB_OHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select USB_UHCI_BIG_ENDIAN_DESC if BIG_ENDIAN select USB_UHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
select USB_UHCI_BIG_ENDIAN_MMIO if BIG_ENDIAN select USB_UHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select USE_OF select USE_OF
help help
Select this to build a kernel which aims to support multiple boards, 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_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_MIPS16 select SYS_SUPPORTS_MIPS16
select SYS_SUPPORTS_ZBOOT
select SYS_HAS_EARLY_PRINTK select SYS_HAS_EARLY_PRINTK
select USE_GENERIC_EARLY_PRINTK_8250 select USE_GENERIC_EARLY_PRINTK_8250
select GPIOLIB select GPIOLIB
@ -341,6 +340,8 @@ config MACH_DECSTATION
config MACH_JAZZ config MACH_JAZZ
bool "Jazz family of machines" bool "Jazz family of machines"
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
select FW_ARC select FW_ARC
select FW_ARC32 select FW_ARC32
select ARCH_MAY_HAVE_PC_FDC select ARCH_MAY_HAVE_PC_FDC
@ -476,6 +477,8 @@ config MACH_PISTACHIO
config MIPS_MALTA config MIPS_MALTA
bool "MIPS Malta board" bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC select ARCH_MAY_HAVE_PC_FDC
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
select BOOT_ELF32 select BOOT_ELF32
select BOOT_RAW select BOOT_RAW
select BUILTIN_DTB select BUILTIN_DTB
@ -613,6 +616,7 @@ config SGI_IP22
bool "SGI IP22 (Indy/Indigo2)" bool "SGI IP22 (Indy/Indigo2)"
select FW_ARC select FW_ARC
select FW_ARC32 select FW_ARC32
select ARCH_MIGHT_HAVE_PC_SERIO
select BOOT_ELF32 select BOOT_ELF32
select CEVT_R4K select CEVT_R4K
select CSRC_R4K select CSRC_R4K
@ -675,6 +679,7 @@ config SGI_IP28
bool "SGI IP28 (Indigo2 R10k)" bool "SGI IP28 (Indigo2 R10k)"
select FW_ARC select FW_ARC
select FW_ARC64 select FW_ARC64
select ARCH_MIGHT_HAVE_PC_SERIO
select BOOT_ELF64 select BOOT_ELF64
select CEVT_R4K select CEVT_R4K
select CSRC_R4K select CSRC_R4K
@ -824,6 +829,8 @@ config SNI_RM
select FW_ARC32 if CPU_LITTLE_ENDIAN select FW_ARC32 if CPU_LITTLE_ENDIAN
select FW_SNIPROM if CPU_BIG_ENDIAN select FW_SNIPROM if CPU_BIG_ENDIAN
select ARCH_MAY_HAVE_PC_FDC select ARCH_MAY_HAVE_PC_FDC
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
select BOOT_ELF32 select BOOT_ELF32
select CEVT_R4K select CEVT_R4K
select CSRC_R4K select CSRC_R4K

View File

@ -216,6 +216,12 @@ cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA
endif endif
toolchain-virt := $(call cc-option-yn,$(mips-cflags) -mvirt) toolchain-virt := $(call cc-option-yn,$(mips-cflags) -mvirt)
cflags-$(toolchain-virt) += -DTOOLCHAIN_SUPPORTS_VIRT 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 # Firmware support
@ -228,7 +234,7 @@ libs-y += arch/mips/fw/lib/
# #
# Kernel compression # Kernel compression
# #
ifdef SYS_SUPPORTS_ZBOOT ifdef CONFIG_SYS_SUPPORTS_ZBOOT
COMPRESSION_FNAME = vmlinuz COMPRESSION_FNAME = vmlinuz
else else
COMPRESSION_FNAME = vmlinux COMPRESSION_FNAME = vmlinux

View File

@ -5,3 +5,4 @@ platform-$(CONFIG_BCM47XX) += bcm47xx/
cflags-$(CONFIG_BCM47XX) += \ cflags-$(CONFIG_BCM47XX) += \
-I$(srctree)/arch/mips/include/asm/mach-bcm47xx -I$(srctree)/arch/mips/include/asm/mach-bcm47xx
load-$(CONFIG_BCM47XX) := 0xffffffff80001000 load-$(CONFIG_BCM47XX) := 0xffffffff80001000
zload-$(CONFIG_BCM47XX) += 0xffffffff80400000

View File

@ -133,4 +133,8 @@ vmlinuz.srec: vmlinuz
uzImage.bin: vmlinuz.bin FORCE uzImage.bin: vmlinuz.bin FORCE
$(call if_changed,uimage,none) $(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

View File

@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb
dtb-$(CONFIG_JZ4770_GCW0) += gcw0.dtb
dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb
obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y)) obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))

View File

@ -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";
};

View File

@ -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";
};
};

View File

@ -153,7 +153,6 @@ CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_SMART=y CONFIG_SLIP_SMART=y
CONFIG_SLIP_MODE_SLIP6=y CONFIG_SLIP_MODE_SLIP6=y
# CONFIG_INPUT is not set # CONFIG_INPUT is not set
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_RAW=m CONFIG_SERIO_RAW=m
# CONFIG_VT is not set # CONFIG_VT is not set
CONFIG_SERIAL_NONSTANDARD=y CONFIG_SERIAL_NONSTANDARD=y

View File

@ -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

View File

@ -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

View File

@ -252,7 +252,6 @@ CONFIG_RT2800PCI=m
CONFIG_WL12XX=m CONFIG_WL12XX=m
CONFIG_WL1251=m CONFIG_WL1251=m
# CONFIG_INPUT is not set # CONFIG_INPUT is not set
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_LIBPS2=m CONFIG_SERIO_LIBPS2=m
CONFIG_SERIO_RAW=m CONFIG_SERIO_RAW=m
CONFIG_SERIO_ALTERA_PS2=m CONFIG_SERIO_ALTERA_PS2=m

View File

@ -75,7 +75,6 @@ CONFIG_DE2104X=m
CONFIG_TULIP=m CONFIG_TULIP=m
CONFIG_TULIP_MMIO=y CONFIG_TULIP_MMIO=y
CONFIG_INPUT_EVDEV=m CONFIG_INPUT_EVDEV=m
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_MACEPS2=y CONFIG_SERIO_MACEPS2=y
CONFIG_SERIO_RAW=y CONFIG_SERIO_RAW=y
# CONFIG_CONSOLE_TRANSLATIONS is not set # CONFIG_CONSOLE_TRANSLATIONS is not set

View File

@ -312,9 +312,8 @@ CONFIG_HOSTAP_PCI=m
CONFIG_IPW2100=m CONFIG_IPW2100=m
CONFIG_IPW2100_MONITOR=y CONFIG_IPW2100_MONITOR=y
CONFIG_LIBERTAS=m CONFIG_LIBERTAS=m
# CONFIG_INPUT_KEYBOARD is not set CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSE is not set CONFIG_MOUSE_PS2_ELANTECH=y
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_POWER_RESET=y CONFIG_POWER_RESET=y

View File

@ -324,9 +324,7 @@ CONFIG_HOSTAP_PCI=m
CONFIG_IPW2100=m CONFIG_IPW2100=m
CONFIG_IPW2100_MONITOR=y CONFIG_IPW2100_MONITOR=y
CONFIG_LIBERTAS=m CONFIG_LIBERTAS=m
# CONFIG_INPUT_KEYBOARD is not set CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_POWER_RESET=y CONFIG_POWER_RESET=y

View File

@ -326,9 +326,7 @@ CONFIG_HOSTAP_PCI=m
CONFIG_IPW2100=m CONFIG_IPW2100=m
CONFIG_IPW2100_MONITOR=y CONFIG_IPW2100_MONITOR=y
CONFIG_LIBERTAS=m CONFIG_LIBERTAS=m
# CONFIG_INPUT_KEYBOARD is not set CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_POWER_RESET=y CONFIG_POWER_RESET=y

View File

@ -126,6 +126,7 @@ CONFIG_PCNET32=y
# CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_WLAN is not set # CONFIG_WLAN is not set
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_VT is not set # CONFIG_VT is not set
CONFIG_LEGACY_PTY_COUNT=4 CONFIG_LEGACY_PTY_COUNT=4
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y

View File

@ -126,6 +126,7 @@ CONFIG_PCNET32=y
# CONFIG_NET_VENDOR_TOSHIBA is not set # CONFIG_NET_VENDOR_TOSHIBA is not set
# CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_VIA is not set
# CONFIG_WLAN is not set # CONFIG_WLAN is not set
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_VT is not set # CONFIG_VT is not set
CONFIG_LEGACY_PTY_COUNT=16 CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y

View File

@ -127,6 +127,7 @@ CONFIG_PCNET32=y
# CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_WLAN is not set # CONFIG_WLAN is not set
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_VT is not set # CONFIG_VT is not set
CONFIG_LEGACY_PTY_COUNT=4 CONFIG_LEGACY_PTY_COUNT=4
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y

View File

@ -130,6 +130,7 @@ CONFIG_PCNET32=y
# CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_WLAN is not set # CONFIG_WLAN is not set
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_VT is not set # CONFIG_VT is not set
CONFIG_LEGACY_PTY_COUNT=4 CONFIG_LEGACY_PTY_COUNT=4
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y

View File

@ -125,6 +125,7 @@ CONFIG_PCNET32=y
# CONFIG_NET_VENDOR_TOSHIBA is not set # CONFIG_NET_VENDOR_TOSHIBA is not set
# CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_VIA is not set
# CONFIG_WLAN is not set # CONFIG_WLAN is not set
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_VT is not set # CONFIG_VT is not set
CONFIG_LEGACY_PTY_COUNT=16 CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y

View File

@ -321,9 +321,8 @@ CONFIG_HOSTAP_PCI=m
CONFIG_IPW2100=m CONFIG_IPW2100=m
CONFIG_IPW2100_MONITOR=y CONFIG_IPW2100_MONITOR=y
CONFIG_LIBERTAS=m CONFIG_LIBERTAS=m
# CONFIG_INPUT_KEYBOARD is not set CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSE is not set CONFIG_MOUSE_PS2_ELANTECH=y
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_POWER_RESET=y CONFIG_POWER_RESET=y

View File

@ -399,7 +399,6 @@ CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m CONFIG_INPUT_EVBUG=m
# CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=m CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=y CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=m CONFIG_SERIO_RAW=m

View File

@ -332,7 +332,6 @@ CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m CONFIG_INPUT_EVBUG=m
# CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=m CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=y CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=m CONFIG_SERIO_RAW=m

View File

@ -49,7 +49,6 @@ CONFIG_INPUT_EVDEV=m
CONFIG_INPUT_EVBUG=m CONFIG_INPUT_EVBUG=m
# CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_I8042 is not set
# CONFIG_VT_CONSOLE is not set # CONFIG_VT_CONSOLE is not set
CONFIG_SERIAL_PNX8XXX=y CONFIG_SERIAL_PNX8XXX=y
CONFIG_SERIAL_PNX8XXX_CONSOLE=y CONFIG_SERIAL_PNX8XXX_CONSOLE=y

View File

@ -65,7 +65,6 @@ CONFIG_NET_ETHERNET=y
CONFIG_MII=y CONFIG_MII=y
CONFIG_SB1250_MAC=y CONFIG_SB1250_MAC=y
# CONFIG_INPUT is not set # CONFIG_INPUT is not set
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_RAW=m CONFIG_SERIO_RAW=m
# CONFIG_VT is not set # CONFIG_VT is not set
# CONFIG_HW_RANDOM is not set # CONFIG_HW_RANDOM is not set

View File

@ -49,4 +49,14 @@ config FIT_IMAGE_FDT_XILFPGA
Enable this to include the FDT for the MIPSfpga platform Enable this to include the FDT for the MIPSfpga platform
from Imagination Technologies in the FIT kernel image. 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 endif

View File

@ -15,3 +15,4 @@ obj-y += proc.o
obj-$(CONFIG_YAMON_DT_SHIM) += yamon-dt.o obj-$(CONFIG_YAMON_DT_SHIM) += yamon-dt.o
obj-$(CONFIG_LEGACY_BOARD_SEAD3) += board-sead3.o obj-$(CONFIG_LEGACY_BOARD_SEAD3) += board-sead3.o
obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_VIRT_BOARD_RANCHU) += board-ranchu.o

View File

@ -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,
};

View File

@ -22,10 +22,10 @@ int get_c0_fdc_int(void)
{ {
int mips_cpu_fdc_irq; int mips_cpu_fdc_irq;
if (cpu_has_veic) if (mips_gic_present())
panic("Unimplemented!");
else if (mips_gic_present())
mips_cpu_fdc_irq = gic_get_c0_fdc_int(); mips_cpu_fdc_irq = gic_get_c0_fdc_int();
else if (cpu_has_veic)
panic("Unimplemented!");
else if (cp0_fdc_irq >= 0) else if (cp0_fdc_irq >= 0)
mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq; mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq;
else else
@ -38,10 +38,10 @@ int get_c0_perfcount_int(void)
{ {
int mips_cpu_perf_irq; int mips_cpu_perf_irq;
if (cpu_has_veic) if (mips_gic_present())
panic("Unimplemented!");
else if (mips_gic_present())
mips_cpu_perf_irq = gic_get_c0_perfcount_int(); mips_cpu_perf_irq = gic_get_c0_perfcount_int();
else if (cpu_has_veic)
panic("Unimplemented!");
else if (cp0_perfcount_irq >= 0) else if (cp0_perfcount_irq >= 0)
mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
else else
@ -54,10 +54,10 @@ unsigned int get_c0_compare_int(void)
{ {
int mips_cpu_timer_irq; int mips_cpu_timer_irq;
if (cpu_has_veic) if (mips_gic_present())
panic("Unimplemented!");
else if (mips_gic_present())
mips_cpu_timer_irq = gic_get_c0_compare_int(); mips_cpu_timer_irq = gic_get_c0_compare_int();
else if (cpu_has_veic)
panic("Unimplemented!");
else else
mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;

View File

@ -79,6 +79,8 @@ enum loongson_machine_type {
*/ */
#define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */ #define MACH_INGENIC_JZ4730 0 /* JZ4730 SOC */
#define MACH_INGENIC_JZ4740 1 /* JZ4740 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; extern char *system_type;
const char *get_system_type(void); const char *get_system_type(void);

View File

@ -110,7 +110,7 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst,
*/ */
static inline __sum16 csum_fold(__wsum csum) static inline __sum16 csum_fold(__wsum csum)
{ {
u32 sum = (__force u32)csum;; u32 sum = (__force u32)csum;
sum += (sum << 16); sum += (sum << 16);
csum = (sum < csum); csum = (sum < csum);

View File

@ -4,7 +4,7 @@
#define SYSTEM_RAM_LOW 1 #define SYSTEM_RAM_LOW 1
#define SYSTEM_RAM_HIGH 2 #define SYSTEM_RAM_HIGH 2
#define MEM_RESERVED 3 #define SYSTEM_RAM_RESERVED 3
#define PCI_IO 4 #define PCI_IO 4
#define PCI_MEM 5 #define PCI_MEM 5
#define LOONGSON_CFG_REG 6 #define LOONGSON_CFG_REG 6

View File

@ -52,7 +52,7 @@ mips_machine_is_compatible(const struct mips_machine *mach, const void *fdt)
if (!mach->matches) if (!mach->matches)
return NULL; 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) if (fdt_node_check_compatible(fdt, 0, match->compatible) == 0)
return match; return match;
} }

View File

@ -1180,6 +1180,89 @@ static inline int mm_insn_16bit(u16 insn)
#define _ASM_INSN_IF_MIPS(_enc) #define _ASM_INSN_IF_MIPS(_enc)
#endif #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 * TLB Invalidate Flush
*/ */
@ -1245,14 +1328,14 @@ do { \
* Macros to access the system control coprocessor * 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; \ ({ unsigned int __res; \
if (sel == 0) \ if (sel == 0) \
__asm__ __volatile__( \ __asm__ vol( \
"mfc0\t%0, " #source "\n\t" \ "mfc0\t%0, " #source "\n\t" \
: "=r" (__res)); \ : "=r" (__res)); \
else \ else \
__asm__ __volatile__( \ __asm__ vol( \
".set\tmips32\n\t" \ ".set\tmips32\n\t" \
"mfc0\t%0, " #source ", " #sel "\n\t" \ "mfc0\t%0, " #source ", " #sel "\n\t" \
".set\tmips0\n\t" \ ".set\tmips0\n\t" \
@ -1260,18 +1343,18 @@ do { \
__res; \ __res; \
}) })
#define __read_64bit_c0_register(source, sel) \ #define ___read_64bit_c0_register(source, sel, vol) \
({ unsigned long long __res; \ ({ unsigned long long __res; \
if (sizeof(unsigned long) == 4) \ if (sizeof(unsigned long) == 4) \
__res = __read_64bit_c0_split(source, sel); \ __res = __read_64bit_c0_split(source, sel, vol); \
else if (sel == 0) \ else if (sel == 0) \
__asm__ __volatile__( \ __asm__ vol( \
".set\tmips3\n\t" \ ".set\tmips3\n\t" \
"dmfc0\t%0, " #source "\n\t" \ "dmfc0\t%0, " #source "\n\t" \
".set\tmips0" \ ".set\tmips0" \
: "=r" (__res)); \ : "=r" (__res)); \
else \ else \
__asm__ __volatile__( \ __asm__ vol( \
".set\tmips64\n\t" \ ".set\tmips64\n\t" \
"dmfc0\t%0, " #source ", " #sel "\n\t" \ "dmfc0\t%0, " #source ", " #sel "\n\t" \
".set\tmips0" \ ".set\tmips0" \
@ -1279,6 +1362,18 @@ do { \
__res; \ __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) \ #define __write_32bit_c0_register(register, sel, value) \
do { \ do { \
if (sel == 0) \ if (sel == 0) \
@ -1316,6 +1411,11 @@ do { \
(unsigned long) __read_32bit_c0_register(reg, sel) : \ (unsigned long) __read_32bit_c0_register(reg, sel) : \
(unsigned long) __read_64bit_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) \ #define __write_ulong_c0_register(reg, sel, val) \
do { \ do { \
if (sizeof(unsigned long) == 4) \ if (sizeof(unsigned long) == 4) \
@ -1346,14 +1446,14 @@ do { \
* These versions are only needed for systems with more than 38 bits of * 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 :-) * 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 long __val; \
unsigned long __flags; \ unsigned long __flags; \
\ \
local_irq_save(__flags); \ local_irq_save(__flags); \
if (sel == 0) \ if (sel == 0) \
__asm__ __volatile__( \ __asm__ vol( \
".set\tmips64\n\t" \ ".set\tmips64\n\t" \
"dmfc0\t%L0, " #source "\n\t" \ "dmfc0\t%L0, " #source "\n\t" \
"dsra\t%M0, %L0, 32\n\t" \ "dsra\t%M0, %L0, 32\n\t" \
@ -1361,7 +1461,7 @@ do { \
".set\tmips0" \ ".set\tmips0" \
: "=r" (__val)); \ : "=r" (__val)); \
else \ else \
__asm__ __volatile__( \ __asm__ vol( \
".set\tmips64\n\t" \ ".set\tmips64\n\t" \
"dmfc0\t%L0, " #source ", " #sel "\n\t" \ "dmfc0\t%L0, " #source ", " #sel "\n\t" \
"dsra\t%M0, %L0, 32\n\t" \ "dsra\t%M0, %L0, 32\n\t" \
@ -1404,37 +1504,43 @@ do { \
local_irq_restore(__flags); \ local_irq_restore(__flags); \
} while (0) } 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; \ unsigned int __res; \
\ \
__asm__ __volatile__( \ __asm__ __volatile__( \
" .set push \n" \ " .set push \n" \
" .set noat \n" \
" .set mips32r2 \n" \ " .set mips32r2 \n" \
" # mfhc0 $1, %1 \n" \ _ASM_SET_XPA \
_ASM_INSN_IF_MIPS(0x40410000 | ((%1 & 0x1f) << 11)) \ " mfhc0 %0, " #source ", %1 \n" \
_ASM_INSN32_IF_MM(0x002000f4 | ((%1 & 0x1f) << 16)) \
" move %0, $1 \n" \
" .set pop \n" \ " .set pop \n" \
: "=r" (__res) \ : "=r" (__res) \
: "i" (source)); \ : "i" (sel)); \
__res; \ __res; \
}) })
#define __writex_32bit_c0_register(register, value) \ #define __writex_32bit_c0_register(register, sel, value) \
do { \ do { \
__asm__ __volatile__( \ __asm__ __volatile__( \
" .set push \n" \ " .set push \n" \
" .set noat \n" \
" .set mips32r2 \n" \ " .set mips32r2 \n" \
" move $1, %0 \n" \ _ASM_SET_XPA \
" # mthc0 $1, %1 \n" \ " mthc0 %z0, " #register ", %1 \n" \
_ASM_INSN_IF_MIPS(0x40c10000 | ((%1 & 0x1f) << 11)) \
_ASM_INSN32_IF_MM(0x002002f4 | ((%1 & 0x1f) << 16)) \
" .set pop \n" \ " .set pop \n" \
: \ : \
: "r" (value), "i" (register)); \ : "Jr" (value), "i" (sel)); \
} while (0) } while (0)
#define read_c0_index() __read_32bit_c0_register($0, 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 read_c0_entrylo0() __read_ulong_c0_register($2, 0)
#define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val) #define write_c0_entrylo0(val) __write_ulong_c0_register($2, 0, val)
#define readx_c0_entrylo0() __readx_32bit_c0_register(2) #define readx_c0_entrylo0() __readx_32bit_c0_register($2, 0)
#define writex_c0_entrylo0(val) __writex_32bit_c0_register(2, val) #define writex_c0_entrylo0(val) __writex_32bit_c0_register($2, 0, val)
#define read_c0_entrylo1() __read_ulong_c0_register($3, 0) #define read_c0_entrylo1() __read_ulong_c0_register($3, 0)
#define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val) #define write_c0_entrylo1(val) __write_ulong_c0_register($3, 0, val)
#define readx_c0_entrylo1() __readx_32bit_c0_register(3) #define readx_c0_entrylo1() __readx_32bit_c0_register($3, 0)
#define writex_c0_entrylo1(val) __writex_32bit_c0_register(3, val) #define writex_c0_entrylo1(val) __writex_32bit_c0_register($3, 0, val)
#define read_c0_conf() __read_32bit_c0_register($3, 0) #define read_c0_conf() __read_32bit_c0_register($3, 0)
#define write_c0_conf(val) __write_32bit_c0_register($3, 0, val) #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 read_c0_epc() __read_ulong_c0_register($14, 0)
#define write_c0_epc(val) __write_ulong_c0_register($14, 0, val) #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) #define read_c0_cmgcrbase() __read_ulong_c0_register($15, 3)
@ -1830,18 +1936,44 @@ do { \
* Macros to access the guest system control coprocessor * 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) \ #define __read_32bit_gc0_register(source, sel) \
({ int __res; \ ({ int __res; \
__asm__ __volatile__( \ __asm__ __volatile__( \
".set\tpush\n\t" \ ".set\tpush\n\t" \
".set\tmips32r2\n\t" \ ".set\tmips32r2\n\t" \
".set\tvirt\n\t" \ _ASM_SET_VIRT \
"mfgc0\t%0, $%1, %2\n\t" \ "mfgc0\t%0, " #source ", %1\n\t" \
".set\tpop" \ ".set\tpop" \
: "=r" (__res) \ : "=r" (__res) \
: "i" (source), "i" (sel)); \ : "i" (sel)); \
__res; \ __res; \
}) })
@ -1850,11 +1982,11 @@ do { \
__asm__ __volatile__( \ __asm__ __volatile__( \
".set\tpush\n\t" \ ".set\tpush\n\t" \
".set\tmips64r2\n\t" \ ".set\tmips64r2\n\t" \
".set\tvirt\n\t" \ _ASM_SET_VIRT \
"dmfgc0\t%0, $%1, %2\n\t" \ "dmfgc0\t%0, " #source ", %1\n\t" \
".set\tpop" \ ".set\tpop" \
: "=r" (__res) \ : "=r" (__res) \
: "i" (source), "i" (sel)); \ : "i" (sel)); \
__res; \ __res; \
}) })
@ -1863,11 +1995,11 @@ do { \
__asm__ __volatile__( \ __asm__ __volatile__( \
".set\tpush\n\t" \ ".set\tpush\n\t" \
".set\tmips32r2\n\t" \ ".set\tmips32r2\n\t" \
".set\tvirt\n\t" \ _ASM_SET_VIRT \
"mtgc0\t%z0, $%1, %2\n\t" \ "mtgc0\t%z0, " #register ", %1\n\t" \
".set\tpop" \ ".set\tpop" \
: : "Jr" ((unsigned int)(value)), \ : : "Jr" ((unsigned int)(value)), \
"i" (register), "i" (sel)); \ "i" (sel)); \
} while (0) } while (0)
#define __write_64bit_gc0_register(register, sel, value) \ #define __write_64bit_gc0_register(register, sel, value) \
@ -1875,75 +2007,13 @@ do { \
__asm__ __volatile__( \ __asm__ __volatile__( \
".set\tpush\n\t" \ ".set\tpush\n\t" \
".set\tmips64r2\n\t" \ ".set\tmips64r2\n\t" \
".set\tvirt\n\t" \ _ASM_SET_VIRT \
"dmtgc0\t%z0, $%1, %2\n\t" \ "dmtgc0\t%z0, " #register ", %1\n\t" \
".set\tpop" \ ".set\tpop" \
: : "Jr" (value), \ : : "Jr" (value), \
"i" (register), "i" (sel)); \ "i" (sel)); \
} while (0) } 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) \ #define __read_ulong_gc0_register(reg, sel) \
((sizeof(unsigned long) == 4) ? \ ((sizeof(unsigned long) == 4) ? \
(unsigned long) __read_32bit_gc0_register(reg, sel) : \ (unsigned long) __read_32bit_gc0_register(reg, sel) : \
@ -1957,207 +2027,207 @@ do { \
__write_64bit_gc0_register(reg, sel, val); \ __write_64bit_gc0_register(reg, sel, val); \
} while (0) } while (0)
#define read_gc0_index() __read_32bit_gc0_register(0, 0) #define read_gc0_index() __read_32bit_gc0_register($0, 0)
#define write_gc0_index(val) __write_32bit_gc0_register(0, 0, val) #define write_gc0_index(val) __write_32bit_gc0_register($0, 0, val)
#define read_gc0_entrylo0() __read_ulong_gc0_register(2, 0) #define read_gc0_entrylo0() __read_ulong_gc0_register($2, 0)
#define write_gc0_entrylo0(val) __write_ulong_gc0_register(2, 0, val) #define write_gc0_entrylo0(val) __write_ulong_gc0_register($2, 0, val)
#define read_gc0_entrylo1() __read_ulong_gc0_register(3, 0) #define read_gc0_entrylo1() __read_ulong_gc0_register($3, 0)
#define write_gc0_entrylo1(val) __write_ulong_gc0_register(3, 0, val) #define write_gc0_entrylo1(val) __write_ulong_gc0_register($3, 0, val)
#define read_gc0_context() __read_ulong_gc0_register(4, 0) #define read_gc0_context() __read_ulong_gc0_register($4, 0)
#define write_gc0_context(val) __write_ulong_gc0_register(4, 0, val) #define write_gc0_context(val) __write_ulong_gc0_register($4, 0, val)
#define read_gc0_contextconfig() __read_32bit_gc0_register(4, 1) #define read_gc0_contextconfig() __read_32bit_gc0_register($4, 1)
#define write_gc0_contextconfig(val) __write_32bit_gc0_register(4, 1, val) #define write_gc0_contextconfig(val) __write_32bit_gc0_register($4, 1, val)
#define read_gc0_userlocal() __read_ulong_gc0_register(4, 2) #define read_gc0_userlocal() __read_ulong_gc0_register($4, 2)
#define write_gc0_userlocal(val) __write_ulong_gc0_register(4, 2, val) #define write_gc0_userlocal(val) __write_ulong_gc0_register($4, 2, val)
#define read_gc0_xcontextconfig() __read_ulong_gc0_register(4, 3) #define read_gc0_xcontextconfig() __read_ulong_gc0_register($4, 3)
#define write_gc0_xcontextconfig(val) __write_ulong_gc0_register(4, 3, val) #define write_gc0_xcontextconfig(val) __write_ulong_gc0_register($4, 3, val)
#define read_gc0_pagemask() __read_32bit_gc0_register(5, 0) #define read_gc0_pagemask() __read_32bit_gc0_register($5, 0)
#define write_gc0_pagemask(val) __write_32bit_gc0_register(5, 0, val) #define write_gc0_pagemask(val) __write_32bit_gc0_register($5, 0, val)
#define read_gc0_pagegrain() __read_32bit_gc0_register(5, 1) #define read_gc0_pagegrain() __read_32bit_gc0_register($5, 1)
#define write_gc0_pagegrain(val) __write_32bit_gc0_register(5, 1, val) #define write_gc0_pagegrain(val) __write_32bit_gc0_register($5, 1, val)
#define read_gc0_segctl0() __read_ulong_gc0_register(5, 2) #define read_gc0_segctl0() __read_ulong_gc0_register($5, 2)
#define write_gc0_segctl0(val) __write_ulong_gc0_register(5, 2, val) #define write_gc0_segctl0(val) __write_ulong_gc0_register($5, 2, val)
#define read_gc0_segctl1() __read_ulong_gc0_register(5, 3) #define read_gc0_segctl1() __read_ulong_gc0_register($5, 3)
#define write_gc0_segctl1(val) __write_ulong_gc0_register(5, 3, val) #define write_gc0_segctl1(val) __write_ulong_gc0_register($5, 3, val)
#define read_gc0_segctl2() __read_ulong_gc0_register(5, 4) #define read_gc0_segctl2() __read_ulong_gc0_register($5, 4)
#define write_gc0_segctl2(val) __write_ulong_gc0_register(5, 4, val) #define write_gc0_segctl2(val) __write_ulong_gc0_register($5, 4, val)
#define read_gc0_pwbase() __read_ulong_gc0_register(5, 5) #define read_gc0_pwbase() __read_ulong_gc0_register($5, 5)
#define write_gc0_pwbase(val) __write_ulong_gc0_register(5, 5, val) #define write_gc0_pwbase(val) __write_ulong_gc0_register($5, 5, val)
#define read_gc0_pwfield() __read_ulong_gc0_register(5, 6) #define read_gc0_pwfield() __read_ulong_gc0_register($5, 6)
#define write_gc0_pwfield(val) __write_ulong_gc0_register(5, 6, val) #define write_gc0_pwfield(val) __write_ulong_gc0_register($5, 6, val)
#define read_gc0_pwsize() __read_ulong_gc0_register(5, 7) #define read_gc0_pwsize() __read_ulong_gc0_register($5, 7)
#define write_gc0_pwsize(val) __write_ulong_gc0_register(5, 7, val) #define write_gc0_pwsize(val) __write_ulong_gc0_register($5, 7, val)
#define read_gc0_wired() __read_32bit_gc0_register(6, 0) #define read_gc0_wired() __read_32bit_gc0_register($6, 0)
#define write_gc0_wired(val) __write_32bit_gc0_register(6, 0, val) #define write_gc0_wired(val) __write_32bit_gc0_register($6, 0, val)
#define read_gc0_pwctl() __read_32bit_gc0_register(6, 6) #define read_gc0_pwctl() __read_32bit_gc0_register($6, 6)
#define write_gc0_pwctl(val) __write_32bit_gc0_register(6, 6, val) #define write_gc0_pwctl(val) __write_32bit_gc0_register($6, 6, val)
#define read_gc0_hwrena() __read_32bit_gc0_register(7, 0) #define read_gc0_hwrena() __read_32bit_gc0_register($7, 0)
#define write_gc0_hwrena(val) __write_32bit_gc0_register(7, 0, val) #define write_gc0_hwrena(val) __write_32bit_gc0_register($7, 0, val)
#define read_gc0_badvaddr() __read_ulong_gc0_register(8, 0) #define read_gc0_badvaddr() __read_ulong_gc0_register($8, 0)
#define write_gc0_badvaddr(val) __write_ulong_gc0_register(8, 0, val) #define write_gc0_badvaddr(val) __write_ulong_gc0_register($8, 0, val)
#define read_gc0_badinstr() __read_32bit_gc0_register(8, 1) #define read_gc0_badinstr() __read_32bit_gc0_register($8, 1)
#define write_gc0_badinstr(val) __write_32bit_gc0_register(8, 1, val) #define write_gc0_badinstr(val) __write_32bit_gc0_register($8, 1, val)
#define read_gc0_badinstrp() __read_32bit_gc0_register(8, 2) #define read_gc0_badinstrp() __read_32bit_gc0_register($8, 2)
#define write_gc0_badinstrp(val) __write_32bit_gc0_register(8, 2, val) #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_count() __read_32bit_gc0_register($9, 0)
#define read_gc0_entryhi() __read_ulong_gc0_register(10, 0) #define read_gc0_entryhi() __read_ulong_gc0_register($10, 0)
#define write_gc0_entryhi(val) __write_ulong_gc0_register(10, 0, val) #define write_gc0_entryhi(val) __write_ulong_gc0_register($10, 0, val)
#define read_gc0_compare() __read_32bit_gc0_register(11, 0) #define read_gc0_compare() __read_32bit_gc0_register($11, 0)
#define write_gc0_compare(val) __write_32bit_gc0_register(11, 0, val) #define write_gc0_compare(val) __write_32bit_gc0_register($11, 0, val)
#define read_gc0_status() __read_32bit_gc0_register(12, 0) #define read_gc0_status() __read_32bit_gc0_register($12, 0)
#define write_gc0_status(val) __write_32bit_gc0_register(12, 0, val) #define write_gc0_status(val) __write_32bit_gc0_register($12, 0, val)
#define read_gc0_intctl() __read_32bit_gc0_register(12, 1) #define read_gc0_intctl() __read_32bit_gc0_register($12, 1)
#define write_gc0_intctl(val) __write_32bit_gc0_register(12, 1, val) #define write_gc0_intctl(val) __write_32bit_gc0_register($12, 1, val)
#define read_gc0_cause() __read_32bit_gc0_register(13, 0) #define read_gc0_cause() __read_32bit_gc0_register($13, 0)
#define write_gc0_cause(val) __write_32bit_gc0_register(13, 0, val) #define write_gc0_cause(val) __write_32bit_gc0_register($13, 0, val)
#define read_gc0_epc() __read_ulong_gc0_register(14, 0) #define read_gc0_epc() __read_ulong_gc0_register($14, 0)
#define write_gc0_epc(val) __write_ulong_gc0_register(14, 0, val) #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_prid() __read_32bit_gc0_register($15, 0)
#define read_gc0_ebase() __read_32bit_gc0_register(15, 1) #define read_gc0_ebase() __read_32bit_gc0_register($15, 1)
#define write_gc0_ebase(val) __write_32bit_gc0_register(15, 1, val) #define write_gc0_ebase(val) __write_32bit_gc0_register($15, 1, val)
#define read_gc0_ebase_64() __read_64bit_gc0_register(15, 1) #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 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_config() __read_32bit_gc0_register($16, 0)
#define read_gc0_config1() __read_32bit_gc0_register(16, 1) #define read_gc0_config1() __read_32bit_gc0_register($16, 1)
#define read_gc0_config2() __read_32bit_gc0_register(16, 2) #define read_gc0_config2() __read_32bit_gc0_register($16, 2)
#define read_gc0_config3() __read_32bit_gc0_register(16, 3) #define read_gc0_config3() __read_32bit_gc0_register($16, 3)
#define read_gc0_config4() __read_32bit_gc0_register(16, 4) #define read_gc0_config4() __read_32bit_gc0_register($16, 4)
#define read_gc0_config5() __read_32bit_gc0_register(16, 5) #define read_gc0_config5() __read_32bit_gc0_register($16, 5)
#define read_gc0_config6() __read_32bit_gc0_register(16, 6) #define read_gc0_config6() __read_32bit_gc0_register($16, 6)
#define read_gc0_config7() __read_32bit_gc0_register(16, 7) #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_config(val) __write_32bit_gc0_register($16, 0, val)
#define write_gc0_config1(val) __write_32bit_gc0_register(16, 1, 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_config2(val) __write_32bit_gc0_register($16, 2, val)
#define write_gc0_config3(val) __write_32bit_gc0_register(16, 3, 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_config4(val) __write_32bit_gc0_register($16, 4, val)
#define write_gc0_config5(val) __write_32bit_gc0_register(16, 5, 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_config6(val) __write_32bit_gc0_register($16, 6, val)
#define write_gc0_config7(val) __write_32bit_gc0_register(16, 7, val) #define write_gc0_config7(val) __write_32bit_gc0_register($16, 7, val)
#define read_gc0_lladdr() __read_ulong_gc0_register(17, 0) #define read_gc0_lladdr() __read_ulong_gc0_register($17, 0)
#define write_gc0_lladdr(val) __write_ulong_gc0_register(17, 0, val) #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_watchlo0() __read_ulong_gc0_register($18, 0)
#define read_gc0_watchlo1() __read_ulong_gc0_register(18, 1) #define read_gc0_watchlo1() __read_ulong_gc0_register($18, 1)
#define read_gc0_watchlo2() __read_ulong_gc0_register(18, 2) #define read_gc0_watchlo2() __read_ulong_gc0_register($18, 2)
#define read_gc0_watchlo3() __read_ulong_gc0_register(18, 3) #define read_gc0_watchlo3() __read_ulong_gc0_register($18, 3)
#define read_gc0_watchlo4() __read_ulong_gc0_register(18, 4) #define read_gc0_watchlo4() __read_ulong_gc0_register($18, 4)
#define read_gc0_watchlo5() __read_ulong_gc0_register(18, 5) #define read_gc0_watchlo5() __read_ulong_gc0_register($18, 5)
#define read_gc0_watchlo6() __read_ulong_gc0_register(18, 6) #define read_gc0_watchlo6() __read_ulong_gc0_register($18, 6)
#define read_gc0_watchlo7() __read_ulong_gc0_register(18, 7) #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_watchlo0(val) __write_ulong_gc0_register($18, 0, val)
#define write_gc0_watchlo1(val) __write_ulong_gc0_register(18, 1, 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_watchlo2(val) __write_ulong_gc0_register($18, 2, val)
#define write_gc0_watchlo3(val) __write_ulong_gc0_register(18, 3, 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_watchlo4(val) __write_ulong_gc0_register($18, 4, val)
#define write_gc0_watchlo5(val) __write_ulong_gc0_register(18, 5, 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_watchlo6(val) __write_ulong_gc0_register($18, 6, val)
#define write_gc0_watchlo7(val) __write_ulong_gc0_register(18, 7, 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_watchhi0() __read_32bit_gc0_register($19, 0)
#define read_gc0_watchhi1() __read_32bit_gc0_register(19, 1) #define read_gc0_watchhi1() __read_32bit_gc0_register($19, 1)
#define read_gc0_watchhi2() __read_32bit_gc0_register(19, 2) #define read_gc0_watchhi2() __read_32bit_gc0_register($19, 2)
#define read_gc0_watchhi3() __read_32bit_gc0_register(19, 3) #define read_gc0_watchhi3() __read_32bit_gc0_register($19, 3)
#define read_gc0_watchhi4() __read_32bit_gc0_register(19, 4) #define read_gc0_watchhi4() __read_32bit_gc0_register($19, 4)
#define read_gc0_watchhi5() __read_32bit_gc0_register(19, 5) #define read_gc0_watchhi5() __read_32bit_gc0_register($19, 5)
#define read_gc0_watchhi6() __read_32bit_gc0_register(19, 6) #define read_gc0_watchhi6() __read_32bit_gc0_register($19, 6)
#define read_gc0_watchhi7() __read_32bit_gc0_register(19, 7) #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_watchhi0(val) __write_32bit_gc0_register($19, 0, val)
#define write_gc0_watchhi1(val) __write_32bit_gc0_register(19, 1, 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_watchhi2(val) __write_32bit_gc0_register($19, 2, val)
#define write_gc0_watchhi3(val) __write_32bit_gc0_register(19, 3, 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_watchhi4(val) __write_32bit_gc0_register($19, 4, val)
#define write_gc0_watchhi5(val) __write_32bit_gc0_register(19, 5, 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_watchhi6(val) __write_32bit_gc0_register($19, 6, val)
#define write_gc0_watchhi7(val) __write_32bit_gc0_register(19, 7, val) #define write_gc0_watchhi7(val) __write_32bit_gc0_register($19, 7, val)
#define read_gc0_xcontext() __read_ulong_gc0_register(20, 0) #define read_gc0_xcontext() __read_ulong_gc0_register($20, 0)
#define write_gc0_xcontext(val) __write_ulong_gc0_register(20, 0, val) #define write_gc0_xcontext(val) __write_ulong_gc0_register($20, 0, val)
#define read_gc0_perfctrl0() __read_32bit_gc0_register(25, 0) #define read_gc0_perfctrl0() __read_32bit_gc0_register($25, 0)
#define write_gc0_perfctrl0(val) __write_32bit_gc0_register(25, 0, val) #define write_gc0_perfctrl0(val) __write_32bit_gc0_register($25, 0, val)
#define read_gc0_perfcntr0() __read_32bit_gc0_register(25, 1) #define read_gc0_perfcntr0() __read_32bit_gc0_register($25, 1)
#define write_gc0_perfcntr0(val) __write_32bit_gc0_register(25, 1, val) #define write_gc0_perfcntr0(val) __write_32bit_gc0_register($25, 1, val)
#define read_gc0_perfcntr0_64() __read_64bit_gc0_register(25, 1) #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 write_gc0_perfcntr0_64(val) __write_64bit_gc0_register($25, 1, val)
#define read_gc0_perfctrl1() __read_32bit_gc0_register(25, 2) #define read_gc0_perfctrl1() __read_32bit_gc0_register($25, 2)
#define write_gc0_perfctrl1(val) __write_32bit_gc0_register(25, 2, val) #define write_gc0_perfctrl1(val) __write_32bit_gc0_register($25, 2, val)
#define read_gc0_perfcntr1() __read_32bit_gc0_register(25, 3) #define read_gc0_perfcntr1() __read_32bit_gc0_register($25, 3)
#define write_gc0_perfcntr1(val) __write_32bit_gc0_register(25, 3, val) #define write_gc0_perfcntr1(val) __write_32bit_gc0_register($25, 3, val)
#define read_gc0_perfcntr1_64() __read_64bit_gc0_register(25, 3) #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 write_gc0_perfcntr1_64(val) __write_64bit_gc0_register($25, 3, val)
#define read_gc0_perfctrl2() __read_32bit_gc0_register(25, 4) #define read_gc0_perfctrl2() __read_32bit_gc0_register($25, 4)
#define write_gc0_perfctrl2(val) __write_32bit_gc0_register(25, 4, val) #define write_gc0_perfctrl2(val) __write_32bit_gc0_register($25, 4, val)
#define read_gc0_perfcntr2() __read_32bit_gc0_register(25, 5) #define read_gc0_perfcntr2() __read_32bit_gc0_register($25, 5)
#define write_gc0_perfcntr2(val) __write_32bit_gc0_register(25, 5, val) #define write_gc0_perfcntr2(val) __write_32bit_gc0_register($25, 5, val)
#define read_gc0_perfcntr2_64() __read_64bit_gc0_register(25, 5) #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 write_gc0_perfcntr2_64(val) __write_64bit_gc0_register($25, 5, val)
#define read_gc0_perfctrl3() __read_32bit_gc0_register(25, 6) #define read_gc0_perfctrl3() __read_32bit_gc0_register($25, 6)
#define write_gc0_perfctrl3(val) __write_32bit_gc0_register(25, 6, val) #define write_gc0_perfctrl3(val) __write_32bit_gc0_register($25, 6, val)
#define read_gc0_perfcntr3() __read_32bit_gc0_register(25, 7) #define read_gc0_perfcntr3() __read_32bit_gc0_register($25, 7)
#define write_gc0_perfcntr3(val) __write_32bit_gc0_register(25, 7, val) #define write_gc0_perfcntr3(val) __write_32bit_gc0_register($25, 7, val)
#define read_gc0_perfcntr3_64() __read_64bit_gc0_register(25, 7) #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 write_gc0_perfcntr3_64(val) __write_64bit_gc0_register($25, 7, val)
#define read_gc0_errorepc() __read_ulong_gc0_register(30, 0) #define read_gc0_errorepc() __read_ulong_gc0_register($30, 0)
#define write_gc0_errorepc(val) __write_ulong_gc0_register(30, 0, val) #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_kscratch1() __read_ulong_gc0_register($31, 2)
#define read_gc0_kscratch2() __read_ulong_gc0_register(31, 3) #define read_gc0_kscratch2() __read_ulong_gc0_register($31, 3)
#define read_gc0_kscratch3() __read_ulong_gc0_register(31, 4) #define read_gc0_kscratch3() __read_ulong_gc0_register($31, 4)
#define read_gc0_kscratch4() __read_ulong_gc0_register(31, 5) #define read_gc0_kscratch4() __read_ulong_gc0_register($31, 5)
#define read_gc0_kscratch5() __read_ulong_gc0_register(31, 6) #define read_gc0_kscratch5() __read_ulong_gc0_register($31, 6)
#define read_gc0_kscratch6() __read_ulong_gc0_register(31, 7) #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_kscratch1(val) __write_ulong_gc0_register($31, 2, val)
#define write_gc0_kscratch2(val) __write_ulong_gc0_register(31, 3, 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_kscratch3(val) __write_ulong_gc0_register($31, 4, val)
#define write_gc0_kscratch4(val) __write_ulong_gc0_register(31, 5, 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_kscratch5(val) __write_ulong_gc0_register($31, 6, val)
#define write_gc0_kscratch6(val) __write_ulong_gc0_register(31, 7, val) #define write_gc0_kscratch6(val) __write_ulong_gc0_register($31, 7, val)
/* Cavium OCTEON (cnMIPS) */ /* Cavium OCTEON (cnMIPS) */
#define read_gc0_cvmcount() __read_ulong_gc0_register(9, 6) #define read_gc0_cvmcount() __read_ulong_gc0_register($9, 6)
#define write_gc0_cvmcount(val) __write_ulong_gc0_register(9, 6, val) #define write_gc0_cvmcount(val) __write_ulong_gc0_register($9, 6, val)
#define read_gc0_cvmctl() __read_64bit_gc0_register(9, 7) #define read_gc0_cvmctl() __read_64bit_gc0_register($9, 7)
#define write_gc0_cvmctl(val) __write_64bit_gc0_register(9, 7, val) #define write_gc0_cvmctl(val) __write_64bit_gc0_register($9, 7, val)
#define read_gc0_cvmmemctl() __read_64bit_gc0_register(11, 7) #define read_gc0_cvmmemctl() __read_64bit_gc0_register($11, 7)
#define write_gc0_cvmmemctl(val) __write_64bit_gc0_register(11, 7, val) #define write_gc0_cvmmemctl(val) __write_64bit_gc0_register($11, 7, val)
#define read_gc0_cvmmemctl2() __read_64bit_gc0_register(16, 6) #define read_gc0_cvmmemctl2() __read_64bit_gc0_register($16, 6)
#define write_gc0_cvmmemctl2(val) __write_64bit_gc0_register(16, 6, val) #define write_gc0_cvmmemctl2(val) __write_64bit_gc0_register($16, 6, val)
/* /*
* Macros to access the floating point coprocessor control registers * Macros to access the floating point coprocessor control registers
@ -2581,8 +2651,6 @@ static inline void tlb_write_random(void)
".set reorder"); ".set reorder");
} }
#ifdef TOOLCHAIN_SUPPORTS_VIRT
/* /*
* Guest TLB operations. * Guest TLB operations.
* *
@ -2593,7 +2661,7 @@ static inline void guest_tlb_probe(void)
__asm__ __volatile__( __asm__ __volatile__(
".set push\n\t" ".set push\n\t"
".set noreorder\n\t" ".set noreorder\n\t"
".set virt\n\t" _ASM_SET_VIRT
"tlbgp\n\t" "tlbgp\n\t"
".set pop"); ".set pop");
} }
@ -2603,7 +2671,7 @@ static inline void guest_tlb_read(void)
__asm__ __volatile__( __asm__ __volatile__(
".set push\n\t" ".set push\n\t"
".set noreorder\n\t" ".set noreorder\n\t"
".set virt\n\t" _ASM_SET_VIRT
"tlbgr\n\t" "tlbgr\n\t"
".set pop"); ".set pop");
} }
@ -2613,7 +2681,7 @@ static inline void guest_tlb_write_indexed(void)
__asm__ __volatile__( __asm__ __volatile__(
".set push\n\t" ".set push\n\t"
".set noreorder\n\t" ".set noreorder\n\t"
".set virt\n\t" _ASM_SET_VIRT
"tlbgwi\n\t" "tlbgwi\n\t"
".set pop"); ".set pop");
} }
@ -2623,7 +2691,7 @@ static inline void guest_tlb_write_random(void)
__asm__ __volatile__( __asm__ __volatile__(
".set push\n\t" ".set push\n\t"
".set noreorder\n\t" ".set noreorder\n\t"
".set virt\n\t" _ASM_SET_VIRT
"tlbgwr\n\t" "tlbgwr\n\t"
".set pop"); ".set pop");
} }
@ -2636,63 +2704,11 @@ static inline void guest_tlbinvf(void)
__asm__ __volatile__( __asm__ __volatile__(
".set push\n\t" ".set push\n\t"
".set noreorder\n\t" ".set noreorder\n\t"
".set virt\n\t" _ASM_SET_VIRT
"tlbginvf\n\t" "tlbginvf\n\t"
".set pop"); ".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. * Manipulate bits in a register.
*/ */

View File

@ -160,7 +160,23 @@ static inline void init_msa_upper(void)
_init_msa_upper(); _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) \ #define __BUILD_MSA_CTL_REG(name, cs) \
static inline unsigned int read_msa_##name(void) \ static inline unsigned int read_msa_##name(void) \
@ -168,8 +184,7 @@ static inline unsigned int read_msa_##name(void) \
unsigned int reg; \ unsigned int reg; \
__asm__ __volatile__( \ __asm__ __volatile__( \
" .set push\n" \ " .set push\n" \
" .set fp=64\n" \ _ASM_SET_MSA \
" .set msa\n" \
" cfcmsa %0, $" #cs "\n" \ " cfcmsa %0, $" #cs "\n" \
" .set pop\n" \ " .set pop\n" \
: "=r"(reg)); \ : "=r"(reg)); \
@ -180,52 +195,12 @@ static inline void write_msa_##name(unsigned int val) \
{ \ { \
__asm__ __volatile__( \ __asm__ __volatile__( \
" .set push\n" \ " .set push\n" \
" .set fp=64\n" \ _ASM_SET_MSA \
" .set msa\n" \
" ctcmsa $" #cs ", %0\n" \ " ctcmsa $" #cs ", %0\n" \
" .set pop\n" \ " .set pop\n" \
: : "r"(val)); \ : : "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(ir, 0)
__BUILD_MSA_CTL_REG(csr, 1) __BUILD_MSA_CTL_REG(csr, 1)
__BUILD_MSA_CTL_REG(access, 2) __BUILD_MSA_CTL_REG(access, 2)

View File

@ -8,6 +8,10 @@ config JZ4740_QI_LB60
bool "Qi Hardware Ben NanoNote" bool "Qi Hardware Ben NanoNote"
select MACH_JZ4740 select MACH_JZ4740
config JZ4770_GCW0
bool "Game Consoles Worldwide GCW Zero"
select MACH_JZ4770
config JZ4780_CI20 config JZ4780_CI20
bool "MIPS Creator CI20" bool "MIPS Creator CI20"
select MACH_JZ4780 select MACH_JZ4780
@ -18,6 +22,12 @@ config MACH_JZ4740
bool bool
select SYS_HAS_CPU_MIPS32_R1 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 config MACH_JZ4780
bool bool
select MIPS_CPU_SCACHE select MIPS_CPU_SCACHE

View File

@ -20,33 +20,12 @@
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/fw/fw.h>
#include <asm/mach-jz4740/base.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) void __init prom_init(void)
{ {
jz4740_init_cmdline((int)fw_arg0, (char **)fw_arg1); fw_init_cmdline();
mips_machtype = MACH_INGENIC_JZ4740;
} }
void __init prom_free_prom_memory(void) void __init prom_free_prom_memory(void)

View File

@ -53,6 +53,16 @@ static void __init jz4740_detect_mem(void)
add_memory_region(0, size, BOOT_MEM_RAM); 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) void __init plat_mem_setup(void)
{ {
int offset; int offset;
@ -63,6 +73,8 @@ void __init plat_mem_setup(void)
offset = fdt_path_offset(__dtb_start, "/memory"); offset = fdt_path_offset(__dtb_start, "/memory");
if (offset < 0) if (offset < 0)
jz4740_detect_mem(); jz4740_detect_mem();
mips_machtype = get_board_mach_type(__dtb_start);
} }
void __init device_tree_init(void) void __init device_tree_init(void)
@ -75,11 +87,15 @@ void __init device_tree_init(void)
const char *get_system_type(void) const char *get_system_type(void)
{ {
if (IS_ENABLED(CONFIG_MACH_JZ4780)) switch (mips_machtype) {
case MACH_INGENIC_JZ4780:
return "JZ4780"; return "JZ4780";
case MACH_INGENIC_JZ4770:
return "JZ4770";
default:
return "JZ4740"; return "JZ4740";
} }
}
void __init arch_init_irq(void) void __init arch_init_irq(void)
{ {

View File

@ -113,7 +113,7 @@ static struct clock_event_device jz4740_clockevent = {
#ifdef CONFIG_MACH_JZ4740 #ifdef CONFIG_MACH_JZ4740
.irq = JZ4740_IRQ_TCU0, .irq = JZ4740_IRQ_TCU0,
#endif #endif
#ifdef CONFIG_MACH_JZ4780 #if defined(CONFIG_MACH_JZ4770) || defined(CONFIG_MACH_JZ4780)
.irq = JZ4780_IRQ_TCU2, .irq = JZ4780_IRQ_TCU2,
#endif #endif
}; };

View File

@ -399,7 +399,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
* *
* @regs: Pointer to pt_regs * @regs: Pointer to pt_regs
* @insn: branch instruction to decode * @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 * returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
* evaluating the branch. * evaluating the branch.
* *

View 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 * If fails when getting the stack address of the non-leaf function's
* ra, stop function graph tracer and return * ra, stop function graph tracer and return
*/ */
if (parent_ra_addr == 0) if (parent_ra_addr == NULL)
goto out; goto out;
#endif #endif
/* *parent_ra_addr = return_hooker; */ /* *parent_ra_addr = return_hooker; */

View File

@ -826,25 +826,6 @@ static void __init arch_mem_init(char **cmdline_p)
struct memblock_region *reg; struct memblock_region *reg;
extern void plat_mem_setup(void); 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) #if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else #else
@ -872,6 +853,26 @@ static void __init arch_mem_init(char **cmdline_p)
} }
#endif #endif
#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); strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line; *cmdline_p = command_line;

View File

@ -439,8 +439,6 @@ void play_dead(void)
pr_debug("CPU%d going offline\n", cpu); pr_debug("CPU%d going offline\n", cpu);
if (cpu_has_mipsmt || cpu_has_vp) { if (cpu_has_mipsmt || cpu_has_vp) {
core = cpu_core(&cpu_data[cpu]);
/* Look for another online VPE within the core */ /* Look for another online VPE within the core */
for_each_online_cpu(cpu_death_sibling) { for_each_online_cpu(cpu_death_sibling) {
if (!cpus_are_siblings(cpu, cpu_death_sibling)) if (!cpus_are_siblings(cpu, cpu_death_sibling))

View File

@ -18,27 +18,24 @@
void mips_install_watch_registers(struct task_struct *t) void mips_install_watch_registers(struct task_struct *t)
{ {
struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264; 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) { switch (current_cpu_data.watch_reg_use_cnt) {
default: default:
BUG(); BUG();
case 4: case 4:
write_c0_watchlo3(watches->watchlo[3]); write_c0_watchlo3(watches->watchlo[3]);
/* Write 1 to the I, R, and W bits to clear them, and write_c0_watchhi3(watchhi | watches->watchhi[3]);
1 to G so all ASIDs are trapped. */
write_c0_watchhi3(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
watches->watchhi[3]);
case 3: case 3:
write_c0_watchlo2(watches->watchlo[2]); write_c0_watchlo2(watches->watchlo[2]);
write_c0_watchhi2(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | write_c0_watchhi2(watchhi | watches->watchhi[2]);
watches->watchhi[2]);
case 2: case 2:
write_c0_watchlo1(watches->watchlo[1]); write_c0_watchlo1(watches->watchlo[1]);
write_c0_watchhi1(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | write_c0_watchhi1(watchhi | watches->watchhi[1]);
watches->watchhi[1]);
case 1: case 1:
write_c0_watchlo0(watches->watchlo[0]); write_c0_watchlo0(watches->watchlo[0]);
write_c0_watchhi0(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW | write_c0_watchhi0(watchhi | watches->watchhi[0]);
watches->watchhi[0]);
} }
} }
@ -51,21 +48,19 @@ void mips_read_watch_registers(void)
{ {
struct mips3264_watch_reg_state *watches = struct mips3264_watch_reg_state *watches =
&current->thread.watch.mips3264; &current->thread.watch.mips3264;
unsigned int watchhi_mask = MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW;
switch (current_cpu_data.watch_reg_use_cnt) { switch (current_cpu_data.watch_reg_use_cnt) {
default: default:
BUG(); BUG();
case 4: case 4:
watches->watchhi[3] = (read_c0_watchhi3() & watches->watchhi[3] = (read_c0_watchhi3() & watchhi_mask);
(MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
case 3: case 3:
watches->watchhi[2] = (read_c0_watchhi2() & watches->watchhi[2] = (read_c0_watchhi2() & watchhi_mask);
(MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
case 2: case 2:
watches->watchhi[1] = (read_c0_watchhi1() & watches->watchhi[1] = (read_c0_watchhi1() & watchhi_mask);
(MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
case 1: case 1:
watches->watchhi[0] = (read_c0_watchhi0() & watches->watchhi[0] = (read_c0_watchhi0() & watchhi_mask);
(MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
} }
if (current_cpu_data.watch_reg_use_cnt == 1 && if (current_cpu_data.watch_reg_use_cnt == 1 &&
(watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) { (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) {

View File

@ -17,7 +17,6 @@ config LEMOTE_FULOONG2E
select I8259 select I8259
select ISA select ISA
select IRQ_MIPS_CPU select IRQ_MIPS_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_HIGHMEM
@ -49,7 +48,6 @@ config LEMOTE_MACH2F
select ISA select ISA
select SYS_HAS_CPU_LOONGSON2F select SYS_HAS_CPU_LOONGSON2F
select SYS_HAS_EARLY_PRINTK select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_HIGHMEM
select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN

View File

@ -79,7 +79,7 @@ void __init prom_init_memory(void)
(u64)loongson_memmap->map[i].mem_size << 20, (u64)loongson_memmap->map[i].mem_size << 20,
BOOT_MEM_RAM); BOOT_MEM_RAM);
break; break;
case MEM_RESERVED: case SYSTEM_RAM_RESERVED:
add_memory_region(loongson_memmap->map[i].mem_start, add_memory_region(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20, (u64)loongson_memmap->map[i].mem_size << 20,
BOOT_MEM_RESERVED); BOOT_MEM_RESERVED);

View File

@ -166,7 +166,7 @@ static void __init szmem(unsigned int node)
memblock_add_node(PFN_PHYS(start_pfn), memblock_add_node(PFN_PHYS(start_pfn),
PFN_PHYS(end_pfn - start_pfn), node); PFN_PHYS(end_pfn - start_pfn), node);
break; 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", 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); (u32)node_id, mem_type, mem_start, mem_size);
add_memory_region((node_id << 44) + mem_start, add_memory_region((node_id << 44) + mem_start,

View File

@ -451,7 +451,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
regs->cp0_epc + dec_insn.pc_inc + regs->cp0_epc + dec_insn.pc_inc +
dec_insn.next_pc_inc; dec_insn.next_pc_inc;
} }
/* Fall through */ /* fall through */
case jr_op: case jr_op:
/* For R6, JR already emulated in jalr_op */ /* For R6, JR already emulated in jalr_op */
if (NO_R6EMU && insn.r_format.func == jr_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 + regs->regs[31] = regs->cp0_epc +
dec_insn.pc_inc + dec_insn.pc_inc +
dec_insn.next_pc_inc; dec_insn.next_pc_inc;
/* Fall through */ /* fall through */
case bltzl_op: case bltzl_op:
if (NO_R6EMU) if (NO_R6EMU)
break; break;
/* fall through */
case bltz_op: case bltz_op:
if ((long)regs->regs[insn.i_format.rs] < 0) if ((long)regs->regs[insn.i_format.rs] < 0)
*contpc = regs->cp0_epc + *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 + regs->regs[31] = regs->cp0_epc +
dec_insn.pc_inc + dec_insn.pc_inc +
dec_insn.next_pc_inc; dec_insn.next_pc_inc;
/* Fall through */ /* fall through */
case bgezl_op: case bgezl_op:
if (NO_R6EMU) if (NO_R6EMU)
break; break;
/* fall through */
case bgez_op: case bgez_op:
if ((long)regs->regs[insn.i_format.rs] >= 0) if ((long)regs->regs[insn.i_format.rs] >= 0)
*contpc = regs->cp0_epc + *contpc = regs->cp0_epc +
@ -512,11 +514,12 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
break; break;
case jalx_op: case jalx_op:
set_isa16_mode(bit); set_isa16_mode(bit);
/* fall through */
case jal_op: case jal_op:
regs->regs[31] = regs->cp0_epc + regs->regs[31] = regs->cp0_epc +
dec_insn.pc_inc + dec_insn.pc_inc +
dec_insn.next_pc_inc; dec_insn.next_pc_inc;
/* Fall through */ /* fall through */
case j_op: case j_op:
*contpc = regs->cp0_epc + dec_insn.pc_inc; *contpc = regs->cp0_epc + dec_insn.pc_inc;
*contpc >>= 28; *contpc >>= 28;
@ -528,6 +531,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
case beql_op: case beql_op:
if (NO_R6EMU) if (NO_R6EMU)
break; break;
/* fall through */
case beq_op: case beq_op:
if (regs->regs[insn.i_format.rs] == if (regs->regs[insn.i_format.rs] ==
regs->regs[insn.i_format.rt]) 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: case bnel_op:
if (NO_R6EMU) if (NO_R6EMU)
break; break;
/* fall through */
case bne_op: case bne_op:
if (regs->regs[insn.i_format.rs] != if (regs->regs[insn.i_format.rs] !=
regs->regs[insn.i_format.rt]) 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: case blezl_op:
if (!insn.i_format.rt && NO_R6EMU) if (!insn.i_format.rt && NO_R6EMU)
break; break;
/* fall through */
case blez_op: case blez_op:
/* /*
@ -593,6 +599,7 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
case bgtzl_op: case bgtzl_op:
if (!insn.i_format.rt && NO_R6EMU) if (!insn.i_format.rt && NO_R6EMU)
break; break;
/* fall through */
case bgtz_op: case bgtz_op:
/* /*
* Compact branches for R6 for the * Compact branches for R6 for the
@ -729,7 +736,8 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
return 1; return 1;
} }
/* R2/R6 compatible cop1 instruction. Fall through */ /* R2/R6 compatible cop1 instruction */
/* fall through */
case cop2_op: case cop2_op:
case cop1x_op: case cop1x_op:
if (insn.i_format.rs == bc_op) { if (insn.i_format.rs == bc_op) {
@ -1190,7 +1198,8 @@ emul:
if (!cpu_has_mips_r6 || delay_slot(xcp)) if (!cpu_has_mips_r6 || delay_slot(xcp))
return SIGILL; return SIGILL;
cond = likely = 0; likely = 0;
cond = 0;
fpr = &current->thread.fpu.fpr[MIPSInst_RT(ir)]; fpr = &current->thread.fpu.fpr[MIPSInst_RT(ir)];
bit0 = get_fpr32(fpr, 0) & 0x1; bit0 = get_fpr32(fpr, 0) & 0x1;
switch (MIPSInst_RS(ir)) { switch (MIPSInst_RS(ir)) {
@ -1220,14 +1229,14 @@ emul:
case bcfl_op: case bcfl_op:
if (cpu_has_mips_2_3_4_5_r) if (cpu_has_mips_2_3_4_5_r)
likely = 1; likely = 1;
/* Fall through */ /* fall through */
case bcf_op: case bcf_op:
cond = !cond; cond = !cond;
break; break;
case bctl_op: case bctl_op:
if (cpu_has_mips_2_3_4_5_r) if (cpu_has_mips_2_3_4_5_r)
likely = 1; likely = 1;
/* Fall through */ /* fall through */
case bct_op: case bct_op:
break; break;
} }
@ -1353,7 +1362,8 @@ branch_common:
return SIGILL; return SIGILL;
/* a real fpu computation instruction */ /* a real fpu computation instruction */
if ((sig = fpu_emu(xcp, ctx, ir))) sig = fpu_emu(xcp, ctx, ir);
if (sig)
return sig; return sig;
} }
break; break;

View File

@ -104,8 +104,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
/* FALL THROUGH */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
DPDNORMY; DPDNORMY;

View File

@ -103,6 +103,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
DPDNORMY; DPDNORMY;

View File

@ -96,6 +96,7 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
DPDNORMY; DPDNORMY;
@ -224,6 +225,7 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
DPDNORMY; DPDNORMY;

View File

@ -96,6 +96,7 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
DPDNORMY; DPDNORMY;
@ -224,6 +225,7 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
DPDNORMY; DPDNORMY;

View File

@ -16,7 +16,7 @@
/* 128 bits shift right logical with rounding. */ /* 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; 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): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
if (zc == IEEE754_CLASS_INF) 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): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
if (zc == IEEE754_CLASS_INF) if (zc == IEEE754_CLASS_INF)
return ieee754dp_inf(zs); return ieee754dp_inf(zs);
/* fall through to real computations */ /* continue to real computations */
} }
/* Finally get to do some computation */ /* 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. * 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; lxm = xm;
hxm = xm >> 32; hxm = xm >> 32;
lym = ym; lym = ym;

View File

@ -101,6 +101,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
DPDNORMY; 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. * 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; lxm = xm;
hxm = xm >> 32; hxm = xm >> 32;
lym = ym; lym = ym;

View File

@ -91,7 +91,8 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x)
scalx -= 256; 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 */ /* magic initial approximation to almost 8 sig. bits */
yh = y.bits >> 32; 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 */ /* 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; */ /* 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.bexp += 0x001;
t = ieee754dp_add(t, z); t = ieee754dp_add(t, z);
z = ieee754dp_mul(ieee754dp_sub(x, z), y); z = ieee754dp_mul(ieee754dp_sub(x, z), y);
@ -140,7 +142,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x)
switch (oldcsr.rm) { switch (oldcsr.rm) {
case FPU_CSR_RU: case FPU_CSR_RU:
y.bits += 1; y.bits += 1;
/* drop through */ /* fall through */
case FPU_CSR_RN: case FPU_CSR_RN:
t.bits += 1; t.bits += 1;
break; break;

View File

@ -106,7 +106,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX; DPDNORMX;
/* FALL THROUGH */ /* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
/* normalize ym,ye */ /* normalize ym,ye */

View File

@ -55,6 +55,9 @@ static inline int ieee754dp_finite(union ieee754dp x)
#define XDPSRS1(v) \ #define XDPSRS1(v) \
(((v) >> 1) | ((v) & 1)) (((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 */ /* convert denormal to normalized with extended exponent */
#define DPDNORMx(m,e) \ #define DPDNORMx(m,e) \
while ((m >> DP_FBITS) == 0) { m <<= 1; e--; } while ((m >> DP_FBITS) == 0) { m <<= 1; e--; }

View File

@ -104,8 +104,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
/* FALL THROUGH */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;

View File

@ -103,6 +103,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;

View File

@ -46,7 +46,8 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x)
case IEEE754_CLASS_SNAN: case IEEE754_CLASS_SNAN:
x = ieee754dp_nanxcpt(x); x = ieee754dp_nanxcpt(x);
EXPLODEXDP; EXPLODEXDP;
/* Fall through. */ /* fall through */
case IEEE754_CLASS_QNAN: case IEEE754_CLASS_QNAN:
y = ieee754sp_nan_fdp(xs, xm); y = ieee754sp_nan_fdp(xs, xm);
if (!ieee754_csr.nan2008) { if (!ieee754_csr.nan2008) {

View File

@ -96,6 +96,7 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;
@ -224,6 +225,7 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;

View File

@ -96,6 +96,7 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;
@ -224,6 +225,7 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;

View File

@ -126,6 +126,7 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
if (zc == IEEE754_CLASS_INF) 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): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
if (zc == IEEE754_CLASS_INF) if (zc == IEEE754_CLASS_INF)
return ieee754sp_inf(zs); return ieee754sp_inf(zs);
/* fall through to real computations */ /* continue to real computations */
} }
/* Finally get to do some computation */ /* Finally get to do some computation */

View File

@ -101,6 +101,7 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;

View File

@ -82,7 +82,8 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x)
/* generate sqrt(x) bit by bit */ /* generate sqrt(x) bit by bit */
ix += ix; ix += ix;
q = s = 0; /* q = sqrt(x) */ s = 0;
q = 0; /* q = sqrt(x) */
r = 0x01000000; /* r = moving bit from right to left */ r = 0x01000000; /* r = moving bit from right to left */
while (r != 0) { while (r != 0) {

View File

@ -106,6 +106,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX; SPDNORMX;
/* fall through */
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
SPDNORMY; SPDNORMY;

View File

@ -20,7 +20,6 @@
*/ */
#include "ieee754sp.h" #include "ieee754sp.h"
#include "ieee754dp.h"
s64 ieee754sp_tlong(union ieee754sp x) s64 ieee754sp_tlong(union ieee754sp x)
{ {

View 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) static int mips_dma_supported(struct device *dev, u64 mask)
{ {
return plat_dma_supported(dev, 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_single_for_device = mips_dma_sync_single_for_device,
.sync_sg_for_cpu = mips_dma_sync_sg_for_cpu, .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu,
.sync_sg_for_device = mips_dma_sync_sg_for_device, .sync_sg_for_device = mips_dma_sync_sg_for_device,
.mapping_error = mips_dma_mapping_error,
.dma_supported = mips_dma_supported, .dma_supported = mips_dma_supported,
.cache_sync = mips_dma_cache_sync, .cache_sync = mips_dma_cache_sync,
}; };

View File

@ -16,6 +16,7 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/r4kcache.h> #include <asm/r4kcache.h>
#include <asm/mips-cps.h> #include <asm/mips-cps.h>
#include <asm/bootinfo.h>
/* /*
* MIPS32/MIPS64 L2 cache handling * MIPS32/MIPS64 L2 cache handling
@ -220,6 +221,14 @@ static inline int __init mips_sc_probe(void)
else else
return 0; 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.waysize = c->scache.sets * c->scache.linesz;
c->scache.waybit = __ffs(c->scache.waysize); c->scache.waybit = __ffs(c->scache.waysize);

View File

@ -1,3 +1,4 @@
obj-y += cgu.o obj-y += cgu.o
obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o
obj-$(CONFIG_MACH_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o

View File

@ -100,15 +100,13 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
n += pll_info->n_offset; n += pll_info->n_offset;
od_enc = ctl >> pll_info->od_shift; od_enc = ctl >> pll_info->od_shift;
od_enc &= GENMASK(pll_info->od_bits - 1, 0); 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)); enable = !!(ctl & BIT(pll_info->enable_bit));
if (bypass) if (bypass)
return parent_rate; return parent_rate;
if (!enable)
return 0;
for (od = 0; od < pll_info->od_max; od++) { for (od = 0; od < pll_info->od_max; od++) {
if (pll_info->od_encoding[od] == od_enc) if (pll_info->od_encoding[od] == od_enc)
break; 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); return div_u64((u64)parent_rate * m, n * od);
} }
static long static inline const struct ingenic_cgu_clk_info *to_clk_info(
ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate, struct ingenic_clk *ingenic_clk)
unsigned long *prate)
{ {
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu; struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info; const struct ingenic_cgu_clk_info *clk_info;
clk_info = &cgu->clock_info[ingenic_clk->idx]; clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL); 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); 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, ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
const unsigned timeout = 100;
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu; struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info; const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
const struct ingenic_cgu_pll_info *pll_info; const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
unsigned long rate, flags; unsigned long rate, flags;
unsigned m, n, od, i; unsigned int m, n, od;
u32 ctl; 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, rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
&m, &n, &od); &m, &n, &od);
if (rate != req_rate) 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 &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
ctl |= pll_info->od_encoding[od - 1] << 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->bypass_bit);
ctl |= BIT(pll_info->enable_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; 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 = { static const struct clk_ops ingenic_pll_ops = {
.recalc_rate = ingenic_pll_recalc_rate, .recalc_rate = ingenic_pll_recalc_rate,
.round_rate = ingenic_pll_round_rate, .round_rate = ingenic_pll_round_rate,
.set_rate = ingenic_pll_set_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; div *= clk_info->div.div;
rate /= div; rate /= div;
} else if (clk_info->type & CGU_CLK_FIXDIV) {
rate /= clk_info->fixdiv.div;
} }
return rate; return rate;
@ -598,6 +659,7 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
} }
} else if (caps & CGU_CLK_PLL) { } else if (caps & CGU_CLK_PLL) {
clk_init.ops = &ingenic_pll_ops; clk_init.ops = &ingenic_pll_ops;
clk_init.flags |= CLK_SET_RATE_GATE;
caps &= ~CGU_CLK_PLL; caps &= ~CGU_CLK_PLL;

View File

@ -48,6 +48,7 @@
* @bypass_bit: the index of the bypass bit in the PLL control register * @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 * @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 * @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 { struct ingenic_cgu_pll_info {
unsigned reg; unsigned reg;
@ -58,6 +59,7 @@ struct ingenic_cgu_pll_info {
u8 bypass_bit; u8 bypass_bit;
u8 enable_bit; u8 enable_bit;
u8 stable_bit; u8 stable_bit;
bool no_bypass_bit;
}; };
/** /**
@ -120,7 +122,7 @@ struct ingenic_cgu_gate_info {
* @clk_ops: custom clock operation callbacks * @clk_ops: custom clock operation callbacks
*/ */
struct ingenic_cgu_custom_info { struct ingenic_cgu_custom_info {
struct clk_ops *clk_ops; const struct clk_ops *clk_ops;
}; };
/** /**

View File

@ -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);

View File

@ -203,7 +203,7 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
return 0; 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, .get_parent = jz4780_otg_phy_get_parent,
.set_parent = jz4780_otg_phy_set_parent, .set_parent = jz4780_otg_phy_set_parent,

View File

@ -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__ */