The main MIPS changes for 5.5:
- Atomics-related code sees some rework & cleanup, most notably allowing Loongson LL/SC errata workarounds to be more bulletproof & their correctness to be checked at build time. - Command line setup code is simplified somewhat, resolving various corner cases. - MIPS kernels can now be built with kcov code coverage support. - We can now build with CONFIG_FORTIFY_SOURCE=y. - Miscellaneous cleanups. And some platform specific changes: - We now disable some broken TLB functionality on certain Ingenic systems, and JZ4780 systems gain some devicetree nodes to support more devices. - Loongson support sees a number of cleanups, and we gain initial support for Loongson 3A R4 systems. - We gain support for MediaTek MT7688-based GARDENA Smart Gateway systems. - SGI IP27 (Origin 2*) see a number of fixes, cleanups & simplifications. - SGI IP30 (Octane) systems are now supported. -----BEGIN PGP SIGNATURE----- iIwEABYIADQWIQRgLjeFAZEXQzy86/s+p5+stXUA3QUCXdwj2RYccGF1bGJ1cnRv bkBrZXJuZWwub3JnAAoJED6nn6y1dQDd54QA/2CrWLcWCcWVwN8XwLTh3gWf8/k7 d19Ttd0bYrsBUnaHAP9s9kc9RFOAhB3p1G0dsMZqI0YX7emLGPgW3ejJ7CXNCg== =/Hsa -----END PGP SIGNATURE----- Merge tag 'mips_5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux Pull MIPS updates from Paul Burton: "The main MIPS changes for 5.5: - Atomics-related code sees some rework & cleanup, most notably allowing Loongson LL/SC errata workarounds to be more bulletproof & their correctness to be checked at build time. - Command line setup code is simplified somewhat, resolving various corner cases. - MIPS kernels can now be built with kcov code coverage support. - We can now build with CONFIG_FORTIFY_SOURCE=y. - Miscellaneous cleanups. And some platform specific changes: - We now disable some broken TLB functionality on certain Ingenic systems, and JZ4780 systems gain some devicetree nodes to support more devices. - Loongson support sees a number of cleanups, and we gain initial support for Loongson 3A R4 systems. - We gain support for MediaTek MT7688-based GARDENA Smart Gateway systems. - SGI IP27 (Origin 2*) see a number of fixes, cleanups & simplifications. - SGI IP30 (Octane) systems are now supported" * tag 'mips_5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux: (107 commits) MIPS: SGI-IP27: Enable ethernet phy on second Origin 200 module MIPS: PCI: Fix fake subdevice ID for IOC3 MIPS: Ingenic: Disable abandoned HPTLB function. MIPS: PCI: remember nasid changed by set interrupt affinity MIPS: SGI-IP27: Fix crash, when CPUs are disabled via nr_cpus parameter mips: add support for folded p4d page tables mips: drop __pXd_offset() macros that duplicate pXd_index() ones mips: fix build when "48 bits virtual memory" is enabled MIPS: math-emu: Reuse name array in debugfs_fpuemu() MIPS: allow building with kcov coverage MIPS: Loongson64: Drop setup_pcimap MIPS: Loongson2ef: Convert to early_printk_8250 MIPS: Drop CPU_SUPPORTS_UNCACHED_ACCELERATED MIPS: Loongson{2ef, 32, 64} convert to generic fw cmdline MIPS: Drop pmon.h MIPS: Loongson: Unify LOONGSON3/LOONGSON64 Kconfig usage MIPS: Loongson: Rename LOONGSON1 to LOONGSON32 MIPS: Loongson: Fix return value of loongson_hwmon_init MIPS: add support for SGI Octane (IP30) MIPS: PCI: make phys_to_dma/dma_to_phys for pci-xtalk-bridge common ...
This commit is contained in:
commit
2981dcf333
|
@ -16,3 +16,17 @@ value must be one of the following values:
|
|||
ralink,mt7620a-soc
|
||||
ralink,mt7620n-soc
|
||||
ralink,mt7628a-soc
|
||||
ralink,mt7688a-soc
|
||||
|
||||
2. Boards
|
||||
|
||||
GARDENA smart Gateway (MT7688)
|
||||
|
||||
This board is based on the MediaTek MT7688 and equipped with 128 MiB
|
||||
of DDR and 8 MiB of flash (SPI NOR) and additional 128MiB SPI NAND
|
||||
storage.
|
||||
|
||||
------------------------------
|
||||
Required root node properties:
|
||||
- compatible = "gardena,smart-gateway-mt7688", "ralink,mt7688a-soc",
|
||||
"ralink,mt7628a-soc";
|
||||
|
|
|
@ -343,6 +343,8 @@ patternProperties:
|
|||
description: Freescale Semiconductor
|
||||
"^fujitsu,.*":
|
||||
description: Fujitsu Ltd.
|
||||
"^gardena,.*":
|
||||
description: GARDENA GmbH
|
||||
"^gateworks,.*":
|
||||
description: Gateworks Corporation
|
||||
"^gcw,.*":
|
||||
|
|
|
@ -129,6 +129,8 @@ To facilitate such consumers NVMEM framework provides below apis::
|
|||
struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
|
||||
struct nvmem_device *devm_nvmem_device_get(struct device *dev,
|
||||
const char *name);
|
||||
struct nvmem_device *nvmem_device_find(void *data,
|
||||
int (*match)(struct device *dev, const void *data));
|
||||
void nvmem_device_put(struct nvmem_device *nvmem);
|
||||
int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
|
||||
size_t bytes, void *buf);
|
||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -10900,18 +10900,18 @@ F: arch/mips/include/asm/mach-loongson32/
|
|||
F: drivers/*/*loongson1*
|
||||
F: drivers/*/*/*loongson1*
|
||||
|
||||
MIPS/LOONGSON2 ARCHITECTURE
|
||||
MIPS/LOONGSON2EF ARCHITECTURE
|
||||
M: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
L: linux-mips@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/mips/loongson64/fuloong-2e/
|
||||
F: arch/mips/loongson64/lemote-2f/
|
||||
F: arch/mips/include/asm/mach-loongson64/
|
||||
F: arch/mips/loongson2ef/
|
||||
F: arch/mips/include/asm/mach-loongson2ef/
|
||||
F: drivers/*/*loongson2*
|
||||
F: drivers/*/*/*loongson2*
|
||||
|
||||
MIPS/LOONGSON3 ARCHITECTURE
|
||||
MIPS/LOONGSON64 ARCHITECTURE
|
||||
M: Huacai Chen <chenhc@lemote.com>
|
||||
M: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
L: linux-mips@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/mips/loongson64/
|
||||
|
|
|
@ -17,6 +17,7 @@ platforms += jazz
|
|||
platforms += jz4740
|
||||
platforms += lantiq
|
||||
platforms += lasat
|
||||
platforms += loongson2ef
|
||||
platforms += loongson32
|
||||
platforms += loongson64
|
||||
platforms += mti-malta
|
||||
|
@ -30,6 +31,7 @@ platforms += ralink
|
|||
platforms += rb532
|
||||
platforms += sgi-ip22
|
||||
platforms += sgi-ip27
|
||||
platforms += sgi-ip30
|
||||
platforms += sgi-ip32
|
||||
platforms += sibyte
|
||||
platforms += sni
|
||||
|
|
|
@ -7,6 +7,7 @@ config MIPS
|
|||
select ARCH_CLOCKSOURCE_DATA
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
select ARCH_HAS_FORTIFY_SOURCE
|
||||
select ARCH_SUPPORTS_UPROBES
|
||||
select ARCH_USE_BUILTIN_BSWAP
|
||||
select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
|
||||
|
@ -86,6 +87,8 @@ config MIPS
|
|||
select SYSCTL_EXCEPTION_TRACE
|
||||
select VIRT_TO_BUS
|
||||
select ARCH_HAS_PTE_SPECIAL if !(32BIT && CPU_HAS_RIXI)
|
||||
select ARCH_HAS_KCOV
|
||||
select HAVE_GCC_PLUGINS
|
||||
|
||||
menu "Machine selection"
|
||||
|
||||
|
@ -359,6 +362,8 @@ config MACH_DECSTATION
|
|||
|
||||
config MACH_JAZZ
|
||||
bool "Jazz family of machines"
|
||||
select ARC_MEMORY
|
||||
select ARC_PROMLIB
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select FW_ARC
|
||||
|
@ -441,7 +446,7 @@ config LASAT
|
|||
select SYS_SUPPORTS_LITTLE_ENDIAN
|
||||
|
||||
config MACH_LOONGSON32
|
||||
bool "Loongson-1 family of machines"
|
||||
bool "Loongson 32-bit family of machines"
|
||||
select SYS_SUPPORTS_ZBOOT
|
||||
help
|
||||
This enables support for the Loongson-1 family of machines.
|
||||
|
@ -450,18 +455,48 @@ config MACH_LOONGSON32
|
|||
the Institute of Computing Technology (ICT), Chinese Academy of
|
||||
Sciences (CAS).
|
||||
|
||||
config MACH_LOONGSON64
|
||||
bool "Loongson-2/3 family of machines"
|
||||
config MACH_LOONGSON2EF
|
||||
bool "Loongson-2E/F family of machines"
|
||||
select SYS_SUPPORTS_ZBOOT
|
||||
help
|
||||
This enables the support of early Loongson-2E/F family of machines.
|
||||
|
||||
config MACH_LOONGSON64
|
||||
bool "Loongson 64-bit family of machines"
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select GENERIC_ISA_DMA_SUPPORT_BROKEN
|
||||
select BOOT_ELF32
|
||||
select BOARD_SCACHE
|
||||
select CSRC_R4K
|
||||
select CEVT_R4K
|
||||
select CPU_HAS_WB
|
||||
select FORCE_PCI
|
||||
select ISA
|
||||
select I8259
|
||||
select IRQ_MIPS_CPU
|
||||
select NR_CPUS_DEFAULT_4
|
||||
select USE_GENERIC_EARLY_PRINTK_8250
|
||||
select SYS_HAS_CPU_LOONGSON64
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_SUPPORTS_SMP
|
||||
select SYS_SUPPORTS_HOTPLUG_CPU
|
||||
select SYS_SUPPORTS_NUMA
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_HIGHMEM
|
||||
select SYS_SUPPORTS_LITTLE_ENDIAN
|
||||
select SYS_SUPPORTS_ZBOOT
|
||||
select LOONGSON_MC146818
|
||||
select ZONE_DMA32
|
||||
select NUMA
|
||||
help
|
||||
This enables the support of Loongson-2/3 family of machines.
|
||||
|
||||
Loongson-2 is a family of single-core CPUs and Loongson-3 is a
|
||||
family of multi-core CPUs. They are both 64-bit general-purpose
|
||||
MIPS-compatible CPUs. Loongson-2/3 are developed by the Institute
|
||||
of Computing Technology (ICT), Chinese Academy of Sciences (CAS)
|
||||
in the People's Republic of China. The chief architect is Professor
|
||||
Weiwu Hu.
|
||||
Loongson-2 and Loongson-3 are 64-bit general-purpose processors with
|
||||
GS264/GS464/GS464E/GS464V microarchitecture (except old Loongson-2E
|
||||
and Loongson-2F which will be removed), developed by the Institute
|
||||
of Computing Technology (ICT), Chinese Academy of Sciences (CAS).
|
||||
|
||||
config MACH_PISTACHIO
|
||||
bool "IMG Pistachio SoC based boards"
|
||||
|
@ -631,6 +666,8 @@ config RALINK
|
|||
|
||||
config SGI_IP22
|
||||
bool "SGI IP22 (Indy/Indigo2)"
|
||||
select ARC_MEMORY
|
||||
select ARC_PROMLIB
|
||||
select FW_ARC
|
||||
select FW_ARC32
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
|
@ -654,14 +691,7 @@ config SGI_IP22
|
|||
select SWAP_IO_SPACE
|
||||
select SYS_HAS_CPU_R4X00
|
||||
select SYS_HAS_CPU_R5000
|
||||
#
|
||||
# Disable EARLY_PRINTK for now since it leads to overwritten prom
|
||||
# memory during early boot on some machines.
|
||||
#
|
||||
# See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com
|
||||
# for a more details discussion
|
||||
#
|
||||
# select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
|
@ -674,8 +704,10 @@ config SGI_IP22
|
|||
config SGI_IP27
|
||||
bool "SGI IP27 (Origin200/2000)"
|
||||
select ARCH_HAS_PHYS_TO_DMA
|
||||
select ARCH_SPARSEMEM_ENABLE
|
||||
select FW_ARC
|
||||
select FW_ARC64
|
||||
select ARC_CMDLINE_ONLY
|
||||
select BOOT_ELF64
|
||||
select DEFAULT_SGI_PARTITION
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
|
@ -698,6 +730,8 @@ config SGI_IP27
|
|||
|
||||
config SGI_IP28
|
||||
bool "SGI IP28 (Indigo2 R10k)"
|
||||
select ARC_MEMORY
|
||||
select ARC_PROMLIB
|
||||
select FW_ARC
|
||||
select FW_ARC64
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
|
@ -719,14 +753,7 @@ config SGI_IP28
|
|||
select SGI_HAS_ZILOG
|
||||
select SWAP_IO_SPACE
|
||||
select SYS_HAS_CPU_R10000
|
||||
#
|
||||
# Disable EARLY_PRINTK for now since it leads to overwritten prom
|
||||
# memory during early boot on some machines.
|
||||
#
|
||||
# See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com
|
||||
# for a more details discussion
|
||||
#
|
||||
# select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select MIPS_L1_CACHE_SHIFT_7
|
||||
|
@ -734,8 +761,37 @@ config SGI_IP28
|
|||
This is the SGI Indigo2 with R10000 processor. To compile a Linux
|
||||
kernel that runs on these, say Y here.
|
||||
|
||||
config SGI_IP30
|
||||
bool "SGI IP30 (Octane/Octane2)"
|
||||
select ARCH_HAS_PHYS_TO_DMA
|
||||
select FW_ARC
|
||||
select FW_ARC64
|
||||
select BOOT_ELF64
|
||||
select CEVT_R4K
|
||||
select CSRC_R4K
|
||||
select SYNC_R4K if SMP
|
||||
select ZONE_DMA32
|
||||
select HAVE_PCI
|
||||
select IRQ_MIPS_CPU
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
select NR_CPUS_DEFAULT_2
|
||||
select PCI_DRIVERS_GENERIC
|
||||
select PCI_XTALK_BRIDGE
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_HAS_CPU_R10000
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select SYS_SUPPORTS_SMP
|
||||
select MIPS_L1_CACHE_SHIFT_7
|
||||
select ARC_MEMORY
|
||||
help
|
||||
These are the SGI Octane and Octane2 graphics workstations. To
|
||||
compile a Linux kernel that runs on these, say Y here.
|
||||
|
||||
config SGI_IP32
|
||||
bool "SGI IP32 (O2)"
|
||||
select ARC_MEMORY
|
||||
select ARC_PROMLIB
|
||||
select ARCH_HAS_PHYS_TO_DMA
|
||||
select FW_ARC
|
||||
select FW_ARC32
|
||||
|
@ -843,6 +899,8 @@ config SIBYTE_BIGSUR
|
|||
|
||||
config SNI_RM
|
||||
bool "SNI RM200/300/400"
|
||||
select ARC_MEMORY
|
||||
select ARC_PROMLIB
|
||||
select FW_ARC if CPU_LITTLE_ENDIAN
|
||||
select FW_ARC32 if CPU_LITTLE_ENDIAN
|
||||
select FW_SNIPROM if CPU_BIG_ENDIAN
|
||||
|
@ -1038,6 +1096,7 @@ source "arch/mips/sibyte/Kconfig"
|
|||
source "arch/mips/txx9/Kconfig"
|
||||
source "arch/mips/vr41xx/Kconfig"
|
||||
source "arch/mips/cavium-octeon/Kconfig"
|
||||
source "arch/mips/loongson2ef/Kconfig"
|
||||
source "arch/mips/loongson32/Kconfig"
|
||||
source "arch/mips/loongson64/Kconfig"
|
||||
source "arch/mips/netlogic/Kconfig"
|
||||
|
@ -1353,19 +1412,18 @@ config MIPS_L1_CACHE_SHIFT
|
|||
config HAVE_STD_PC_SERIAL_PORT
|
||||
bool
|
||||
|
||||
config ARC_CMDLINE_ONLY
|
||||
bool
|
||||
|
||||
config ARC_CONSOLE
|
||||
bool "ARC console support"
|
||||
depends on SGI_IP22 || SGI_IP28 || (SNI_RM && CPU_LITTLE_ENDIAN)
|
||||
|
||||
config ARC_MEMORY
|
||||
bool
|
||||
depends on MACH_JAZZ || SNI_RM || SGI_IP32
|
||||
default y
|
||||
|
||||
config ARC_PROMLIB
|
||||
bool
|
||||
depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP28 || SGI_IP32
|
||||
default y
|
||||
|
||||
config FW_ARC64
|
||||
bool
|
||||
|
@ -1379,51 +1437,56 @@ choice
|
|||
prompt "CPU type"
|
||||
default CPU_R4X00
|
||||
|
||||
config CPU_LOONGSON3
|
||||
bool "Loongson 3 CPU"
|
||||
depends on SYS_HAS_CPU_LOONGSON3
|
||||
config CPU_LOONGSON64
|
||||
bool "Loongson 64-bit CPU"
|
||||
depends on SYS_HAS_CPU_LOONGSON64
|
||||
select ARCH_HAS_PHYS_TO_DMA
|
||||
select CPU_SUPPORTS_64BIT_KERNEL
|
||||
select CPU_SUPPORTS_HIGHMEM
|
||||
select CPU_SUPPORTS_HUGEPAGES
|
||||
select CPU_SUPPORTS_MSA
|
||||
select CPU_HAS_LOAD_STORE_LR
|
||||
select WEAK_ORDERING
|
||||
select WEAK_REORDERING_BEYOND_LLSC
|
||||
select MIPS_ASID_BITS_VARIABLE
|
||||
select MIPS_PGD_C0_CONTEXT
|
||||
select MIPS_L1_CACHE_SHIFT_6
|
||||
select GPIOLIB
|
||||
select SWIOTLB
|
||||
help
|
||||
The Loongson 3 processor implements the MIPS64R2 instruction
|
||||
set with many extensions.
|
||||
The Loongson GSx64(GS264/GS464/GS464E/GS464V) series of processor
|
||||
cores implements the MIPS64R2 instruction set with many extensions,
|
||||
including most 64-bit Loongson-2 (2H, 2K) and Loongson-3 (3A1000,
|
||||
3B1000, 3B1500, 3A2000, 3A3000 and 3A4000) processors. However, old
|
||||
Loongson-2E/2F is not covered here and will be removed in future.
|
||||
|
||||
config LOONGSON3_ENHANCEMENT
|
||||
bool "New Loongson 3 CPU Enhancements"
|
||||
bool "New Loongson-3 CPU Enhancements"
|
||||
default n
|
||||
select CPU_MIPSR2
|
||||
select CPU_HAS_PREFETCH
|
||||
depends on CPU_LOONGSON3
|
||||
depends on CPU_LOONGSON64
|
||||
help
|
||||
New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A
|
||||
New Loongson-3 cores (since Loongson-3A R2, as opposed to Loongson-3A
|
||||
R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as
|
||||
FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User
|
||||
FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPr2 ASE, User
|
||||
Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer),
|
||||
Fast TLB refill support, etc.
|
||||
|
||||
This option enable those enhancements which are not probed at run
|
||||
time. If you want a generic kernel to run on all Loongson 3 machines,
|
||||
please say 'N' here. If you want a high-performance kernel to run on
|
||||
new Loongson 3 machines only, please say 'Y' here.
|
||||
new Loongson-3 machines only, please say 'Y' here.
|
||||
|
||||
config CPU_LOONGSON3_WORKAROUNDS
|
||||
bool "Old Loongson 3 LLSC Workarounds"
|
||||
bool "Old Loongson-3 LLSC Workarounds"
|
||||
default y if SMP
|
||||
depends on CPU_LOONGSON3
|
||||
depends on CPU_LOONGSON64
|
||||
help
|
||||
Loongson 3 processors have the llsc issues which require workarounds.
|
||||
Loongson-3 processors have the llsc issues which require workarounds.
|
||||
Without workarounds the system may hang unexpectedly.
|
||||
|
||||
Newer Loongson 3 will fix these issues and no workarounds are needed.
|
||||
Newer Loongson-3 will fix these issues and no workarounds are needed.
|
||||
The workarounds have no significant side effect on them but may
|
||||
decrease the performance of the system so this option should be
|
||||
disabled unless the kernel is intended to be run on old systems.
|
||||
|
@ -1433,7 +1496,7 @@ config CPU_LOONGSON3_WORKAROUNDS
|
|||
config CPU_LOONGSON2E
|
||||
bool "Loongson 2E"
|
||||
depends on SYS_HAS_CPU_LOONGSON2E
|
||||
select CPU_LOONGSON2
|
||||
select CPU_LOONGSON2EF
|
||||
help
|
||||
The Loongson 2E processor implements the MIPS III instruction set
|
||||
with many extensions.
|
||||
|
@ -1444,7 +1507,7 @@ config CPU_LOONGSON2E
|
|||
config CPU_LOONGSON2F
|
||||
bool "Loongson 2F"
|
||||
depends on SYS_HAS_CPU_LOONGSON2F
|
||||
select CPU_LOONGSON2
|
||||
select CPU_LOONGSON2EF
|
||||
select GPIOLIB
|
||||
help
|
||||
The Loongson 2F processor implements the MIPS III instruction set
|
||||
|
@ -1457,7 +1520,7 @@ config CPU_LOONGSON2F
|
|||
config CPU_LOONGSON1B
|
||||
bool "Loongson 1B"
|
||||
depends on SYS_HAS_CPU_LOONGSON1B
|
||||
select CPU_LOONGSON1
|
||||
select CPU_LOONGSON32
|
||||
select LEDS_GPIO_REGISTER
|
||||
help
|
||||
The Loongson 1B is a 32-bit SoC, which implements the MIPS32
|
||||
|
@ -1467,7 +1530,7 @@ config CPU_LOONGSON1B
|
|||
config CPU_LOONGSON1C
|
||||
bool "Loongson 1C"
|
||||
depends on SYS_HAS_CPU_LOONGSON1C
|
||||
select CPU_LOONGSON1
|
||||
select CPU_LOONGSON32
|
||||
select LEDS_GPIO_REGISTER
|
||||
help
|
||||
The Loongson 1C is a 32-bit SoC, which implements the MIPS32
|
||||
|
@ -1857,7 +1920,7 @@ config SYS_SUPPORTS_ZBOOT_UART_PROM
|
|||
bool
|
||||
select SYS_SUPPORTS_ZBOOT
|
||||
|
||||
config CPU_LOONGSON2
|
||||
config CPU_LOONGSON2EF
|
||||
bool
|
||||
select CPU_SUPPORTS_32BIT_KERNEL
|
||||
select CPU_SUPPORTS_64BIT_KERNEL
|
||||
|
@ -1866,7 +1929,7 @@ config CPU_LOONGSON2
|
|||
select ARCH_HAS_PHYS_TO_DMA
|
||||
select CPU_HAS_LOAD_STORE_LR
|
||||
|
||||
config CPU_LOONGSON1
|
||||
config CPU_LOONGSON32
|
||||
bool
|
||||
select CPU_MIPS32
|
||||
select CPU_MIPSR2
|
||||
|
@ -1900,7 +1963,7 @@ config CPU_BMIPS5000
|
|||
select SYS_SUPPORTS_HOTPLUG_CPU
|
||||
select CPU_HAS_RIXI
|
||||
|
||||
config SYS_HAS_CPU_LOONGSON3
|
||||
config SYS_HAS_CPU_LOONGSON64
|
||||
bool
|
||||
select CPU_SUPPORTS_CPUFREQ
|
||||
select CPU_HAS_RIXI
|
||||
|
@ -1912,7 +1975,6 @@ config SYS_HAS_CPU_LOONGSON2F
|
|||
bool
|
||||
select CPU_SUPPORTS_CPUFREQ
|
||||
select CPU_SUPPORTS_ADDRWINCFG if 64BIT
|
||||
select CPU_SUPPORTS_UNCACHED_ACCELERATED
|
||||
|
||||
config SYS_HAS_CPU_LOONGSON1B
|
||||
bool
|
||||
|
@ -2089,8 +2151,6 @@ config CPU_SUPPORTS_ADDRWINCFG
|
|||
config CPU_SUPPORTS_HUGEPAGES
|
||||
bool
|
||||
depends on !(32BIT && (ARCH_PHYS_ADDR_T_64BIT || EVA))
|
||||
config CPU_SUPPORTS_UNCACHED_ACCELERATED
|
||||
bool
|
||||
config MIPS_PGD_C0_CONTEXT
|
||||
bool
|
||||
default y if 64BIT && (CPU_MIPSR2 || CPU_MIPSR6) && !CPU_XLP
|
||||
|
@ -2162,7 +2222,7 @@ choice
|
|||
|
||||
config PAGE_SIZE_4KB
|
||||
bool "4kB"
|
||||
depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
|
||||
depends on !CPU_LOONGSON2EF && !CPU_LOONGSON64
|
||||
help
|
||||
This option select the standard 4kB Linux page size. On some
|
||||
R3000-family processors this is the only available page size. Using
|
||||
|
@ -2554,6 +2614,10 @@ config CPU_R4000_WORKAROUNDS
|
|||
config CPU_R4400_WORKAROUNDS
|
||||
bool
|
||||
|
||||
config CPU_R4X00_BUGS64
|
||||
bool
|
||||
default y if SYS_HAS_CPU_R4X00 && 64BIT && (TARGET_ISA_REV < 1)
|
||||
|
||||
config MIPS_ASID_SHIFT
|
||||
int
|
||||
default 6 if CPU_R3000 || CPU_TX39XX
|
||||
|
@ -2612,20 +2676,11 @@ config CPU_SUPPORTS_MSA
|
|||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
depends on !NUMA && !CPU_LOONGSON2
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
bool
|
||||
default y if SGI_IP27
|
||||
help
|
||||
Say Y to support efficient handling of discontiguous physical memory,
|
||||
for architectures which are either NUMA (Non-Uniform Memory Access)
|
||||
or have huge holes in the physical address space for other reasons.
|
||||
See <file:Documentation/vm/numa.rst> for more.
|
||||
depends on !NUMA && !CPU_LOONGSON2EF
|
||||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
bool
|
||||
select SPARSEMEM_STATIC
|
||||
select SPARSEMEM_STATIC if !SGI_IP27
|
||||
|
||||
config NUMA
|
||||
bool "NUMA Support"
|
||||
|
@ -2702,7 +2757,7 @@ config NODES_SHIFT
|
|||
|
||||
config HW_PERF_EVENTS
|
||||
bool "Enable hardware performance counter support for perf events"
|
||||
depends on PERF_EVENTS && !OPROFILE && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3)
|
||||
depends on PERF_EVENTS && !OPROFILE && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON64)
|
||||
default y
|
||||
help
|
||||
Enable hardware performance counter support for perf events. If
|
||||
|
|
|
@ -32,7 +32,6 @@ config USE_GENERIC_EARLY_PRINTK_8250
|
|||
|
||||
config CMDLINE_BOOL
|
||||
bool "Built-in kernel command line"
|
||||
default n
|
||||
help
|
||||
For most systems, it is firmware or second stage bootloader that
|
||||
by default specifies the kernel command line options. However,
|
||||
|
@ -53,7 +52,6 @@ config CMDLINE_BOOL
|
|||
config CMDLINE
|
||||
string "Default kernel command string"
|
||||
depends on CMDLINE_BOOL
|
||||
default ""
|
||||
help
|
||||
On some platforms, there is currently no way for the boot loader to
|
||||
pass arguments to the kernel. For these platforms, and for the cases
|
||||
|
@ -68,7 +66,6 @@ config CMDLINE
|
|||
|
||||
config CMDLINE_OVERRIDE
|
||||
bool "Built-in command line overrides firmware arguments"
|
||||
default n
|
||||
depends on CMDLINE_BOOL
|
||||
help
|
||||
By setting this option to 'Y' you will have your kernel ignore
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
archscripts: scripts_basic
|
||||
$(Q)$(MAKE) $(build)=arch/mips/tools elf-entry
|
||||
ifeq ($(CONFIG_CPU_LOONGSON3_WORKAROUNDS),y)
|
||||
$(Q)$(MAKE) $(build)=arch/mips/tools loongson3-llsc-check
|
||||
endif
|
||||
$(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs
|
||||
|
||||
KBUILD_DEFCONFIG := 32r2el_defconfig
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
# Post-link MIPS pass
|
||||
# ===========================================================================
|
||||
#
|
||||
# 1. Insert relocations into vmlinux
|
||||
# 1. Check that Loongson3 LL/SC workarounds are applied correctly
|
||||
# 2. Insert relocations into vmlinux
|
||||
|
||||
PHONY := __archpost
|
||||
__archpost:
|
||||
|
@ -11,6 +12,10 @@ __archpost:
|
|||
-include include/config/auto.conf
|
||||
include scripts/Kbuild.include
|
||||
|
||||
CMD_LS3_LLSC = arch/mips/tools/loongson3-llsc-check
|
||||
quiet_cmd_ls3_llsc = LLSCCHK $@
|
||||
cmd_ls3_llsc = $(CMD_LS3_LLSC) $@
|
||||
|
||||
CMD_RELOCS = arch/mips/boot/tools/relocs
|
||||
quiet_cmd_relocs = RELOCS $@
|
||||
cmd_relocs = $(CMD_RELOCS) $@
|
||||
|
@ -19,6 +24,9 @@ quiet_cmd_relocs = RELOCS $@
|
|||
|
||||
vmlinux: FORCE
|
||||
@true
|
||||
ifeq ($(CONFIG_CPU_LOONGSON3_WORKAROUNDS),y)
|
||||
$(call if_changed,ls3_llsc)
|
||||
endif
|
||||
ifeq ($(CONFIG_RELOCATABLE),y)
|
||||
$(call if_changed,relocs)
|
||||
endif
|
||||
|
|
|
@ -25,12 +25,47 @@
|
|||
0x30000000 0x30000000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led0 {
|
||||
label = "ci20:red:led0";
|
||||
gpios = <&gpc 3 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "none";
|
||||
};
|
||||
|
||||
led1 {
|
||||
label = "ci20:red:led1";
|
||||
gpios = <&gpc 2 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "nand-disk";
|
||||
};
|
||||
|
||||
led2 {
|
||||
label = "ci20:red:led2";
|
||||
gpios = <&gpc 1 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "cpu1";
|
||||
};
|
||||
|
||||
led3 {
|
||||
label = "ci20:red:led3";
|
||||
gpios = <&gpc 0 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "cpu0";
|
||||
};
|
||||
};
|
||||
|
||||
eth0_power: fixedregulator@0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "eth0_power";
|
||||
gpio = <&gpb 25 GPIO_ACTIVE_LOW>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
wlan0_power: fixedregulator@1 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "wlan0_power";
|
||||
gpio = <&gpb 19 GPIO_ACTIVE_LOW>;
|
||||
enable-active-high;
|
||||
};
|
||||
};
|
||||
|
||||
&ext {
|
||||
|
@ -54,9 +89,18 @@
|
|||
|
||||
bus-width = <4>;
|
||||
max-frequency = <50000000>;
|
||||
non-removable;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_mmc1>;
|
||||
|
||||
brcmf: wifi@1 {
|
||||
/* reg = <4>;*/
|
||||
compatible = "brcm,bcm4330-fmac";
|
||||
vcc-supply = <&wlan0_power>;
|
||||
device-wakeup-gpios = <&gpd 9 GPIO_ACTIVE_HIGH>;
|
||||
shutdown-gpios = <&gpf 7 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
|
@ -73,6 +117,23 @@
|
|||
pinctrl-0 = <&pins_uart1>;
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_uart2>;
|
||||
uart-has-rtscts;
|
||||
|
||||
bluetooth {
|
||||
compatible = "brcm,bcm4330-bt";
|
||||
reset-gpios = <&gpf 8 GPIO_ACTIVE_HIGH>;
|
||||
vcc-supply = <&wlan0_power>;
|
||||
device-wakeup-gpios = <&gpf 5 GPIO_ACTIVE_HIGH>;
|
||||
host-wakeup-gpios = <&gpf 6 GPIO_ACTIVE_HIGH>;
|
||||
shutdown-gpios = <&gpf 4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart3 {
|
||||
status = "okay";
|
||||
|
||||
|
@ -87,6 +148,123 @@
|
|||
pinctrl-0 = <&pins_uart4>;
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c0>;
|
||||
|
||||
clock-frequency = <400000>;
|
||||
|
||||
act8600: act8600@5a {
|
||||
compatible = "active-semi,act8600";
|
||||
reg = <0x5a>;
|
||||
status = "okay";
|
||||
|
||||
regulators {
|
||||
vddcore: SUDCDC1 {
|
||||
regulator-name = "VDDCORE";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vddmem: SUDCDC2 {
|
||||
regulator-name = "VDDMEM";
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vcc_33: SUDCDC3 {
|
||||
regulator-name = "VCC33";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vcc_50: SUDCDC4 {
|
||||
regulator-name = "VCC50";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vcc_25: LDO_REG5 {
|
||||
regulator-name = "VCC25";
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
wifi_io: LDO_REG6 {
|
||||
regulator-name = "WIFIIO";
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vcc_28: LDO_REG7 {
|
||||
regulator-name = "VCC28";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vcc_15: LDO_REG8 {
|
||||
regulator-name = "VCC15";
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vcc_18: LDO_REG9 {
|
||||
regulator-name = "VCC18";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
vcc_11: LDO_REG10 {
|
||||
regulator-name = "VCC11";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c1>;
|
||||
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c2>;
|
||||
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c3>;
|
||||
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c4>;
|
||||
|
||||
clock-frequency = <400000>;
|
||||
|
||||
rtc@51 {
|
||||
compatible = "nxp,pcf8563";
|
||||
reg = <0x51>;
|
||||
interrupts = <110>;
|
||||
};
|
||||
};
|
||||
|
||||
&nemc {
|
||||
status = "okay";
|
||||
|
||||
|
@ -197,6 +375,12 @@
|
|||
bias-disable;
|
||||
};
|
||||
|
||||
pins_uart2: uart2 {
|
||||
function = "uart2";
|
||||
groups = "uart2-data", "uart2-hwflow";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pins_uart3: uart3 {
|
||||
function = "uart3";
|
||||
groups = "uart3-data", "uart3-hwflow";
|
||||
|
@ -209,6 +393,36 @@
|
|||
bias-disable;
|
||||
};
|
||||
|
||||
pins_i2c0: i2c0 {
|
||||
function = "i2c0";
|
||||
groups = "i2c0-data";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pins_i2c1: i2c1 {
|
||||
function = "i2c1";
|
||||
groups = "i2c1-data";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pins_i2c2: i2c2 {
|
||||
function = "i2c2";
|
||||
groups = "i2c2-data";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pins_i2c3: i2c3 {
|
||||
function = "i2c3";
|
||||
groups = "i2c3-data";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pins_i2c4: i2c4 {
|
||||
function = "i2c4";
|
||||
groups = "i2c4-data-e";
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pins_nemc: nemc {
|
||||
function = "nemc";
|
||||
groups = "nemc-data", "nemc-cle-ale", "nemc-rd-we", "nemc-frd-fwe";
|
||||
|
|
|
@ -262,6 +262,92 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c0: i2c@10050000 {
|
||||
compatible = "ingenic,jz4780-i2c";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
reg = <0x10050000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <60>;
|
||||
|
||||
clocks = <&cgu JZ4780_CLK_SMB0>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c0_data>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c1: i2c@10051000 {
|
||||
compatible = "ingenic,jz4780-i2c";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x10051000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <59>;
|
||||
|
||||
clocks = <&cgu JZ4780_CLK_SMB1>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c1_data>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c2: i2c@10052000 {
|
||||
compatible = "ingenic,jz4780-i2c";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x10052000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <58>;
|
||||
|
||||
clocks = <&cgu JZ4780_CLK_SMB2>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c2_data>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c3: i2c@10053000 {
|
||||
compatible = "ingenic,jz4780-i2c";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x10053000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <57>;
|
||||
|
||||
clocks = <&cgu JZ4780_CLK_SMB3>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c3_data>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c4: i2c@10054000 {
|
||||
compatible = "ingenic,jz4780-i2c";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x10054000 0x1000>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <56>;
|
||||
|
||||
clocks = <&cgu JZ4780_CLK_SMB4>;
|
||||
clock-frequency = <100000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_i2c4_data>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
watchdog: watchdog@10002000 {
|
||||
compatible = "ingenic,jz4780-watchdog";
|
||||
reg = <0x10002000 0x10>;
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 Stefan Roese <sr@denx.de>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/include/ "mt7628a.dtsi"
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
compatible = "gardena,smart-gateway-mt7688", "ralink,mt7688a-soc",
|
||||
"ralink,mt7628a-soc";
|
||||
model = "GARDENA smart Gateway (MT7688)";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
gpio-keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_gpio_gpio>; /* GPIO11 */
|
||||
|
||||
user_btn1 {
|
||||
label = "USER_BTN1";
|
||||
gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
|
||||
linux,code =<KEY_PROG1> ;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_pwm0_gpio>, /* GPIO18 */
|
||||
<&pinmux_pwm1_gpio>, /* GPIO19 */
|
||||
<&pinmux_sdmode_gpio>, /* GPIO22..29 */
|
||||
<&pinmux_p0led_an_gpio>; /* GPIO43 */
|
||||
/*
|
||||
* <&pinmux_i2s_gpio> (covers GPIO0..3) is needed here as
|
||||
* well for GPIO3. But this is already claimed for uart1
|
||||
* (see below). So we can't include it in this LED node.
|
||||
*/
|
||||
|
||||
power_blue {
|
||||
label = "smartgw:power:blue";
|
||||
gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
power_green {
|
||||
label = "smartgw:power:green";
|
||||
gpios = <&gpio 19 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
power_red {
|
||||
label = "smartgw:power:red";
|
||||
gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
radio_blue {
|
||||
label = "smartgw:radio:blue";
|
||||
gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
radio_green {
|
||||
label = "smartgw:radio:green";
|
||||
gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
radio_red {
|
||||
label = "smartgw:radio:red";
|
||||
gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
internet_blue {
|
||||
label = "smartgw:internet:blue";
|
||||
gpios = <&gpio 26 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
internet_green {
|
||||
label = "smartgw:internet:green";
|
||||
gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
internet_red {
|
||||
label = "smartgw:internet:red";
|
||||
gpios = <&gpio 28 GPIO_ACTIVE_HIGH>;
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
ethernet_link {
|
||||
label = "smartgw:eth:link";
|
||||
gpios = <&gpio 3 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "netdev";
|
||||
};
|
||||
|
||||
ethernet_activity {
|
||||
label = "smartgw:eth:act";
|
||||
gpios = <&gpio 43 GPIO_ACTIVE_LOW>;
|
||||
linux,default-trigger = "netdev";
|
||||
};
|
||||
};
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_spi_spi>, <&pinmux_spi_cs1_cs>;
|
||||
|
||||
m25p80@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <40000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "uboot";
|
||||
reg = <0x0 0xa0000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@a0000 {
|
||||
label = "uboot_env0";
|
||||
reg = <0xa0000 0x10000>;
|
||||
};
|
||||
|
||||
partition@b0000 {
|
||||
label = "uboot_env1";
|
||||
reg = <0xb0000 0x10000>;
|
||||
};
|
||||
|
||||
factory: partition@c0000 {
|
||||
label = "factory";
|
||||
reg = <0xc0000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nand_flash@1 {
|
||||
compatible = "spi-nand";
|
||||
linux,mtd-name = "gd5f";
|
||||
reg = <1>;
|
||||
spi-max-frequency = <40000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_i2s_gpio>; /* GPIO0..3 */
|
||||
|
||||
rts-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
|
||||
cts-gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
status = "okay";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_p2led_an_gpio>, /* GPIO41 */
|
||||
<&pinmux_p3led_an_gpio>; /* GPIO40 */
|
||||
|
||||
rts-gpios = <&gpio 40 GPIO_ACTIVE_LOW>;
|
||||
cts-gpios = <&gpio 41 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
&watchdog {
|
||||
status = "okay";
|
||||
};
|
|
@ -199,6 +199,22 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c: i2c@900 {
|
||||
compatible = "mediatek,mt7621-i2c";
|
||||
reg = <0x900 0x100>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_i2c_i2c>;
|
||||
|
||||
resets = <&resetc 16>;
|
||||
reset-names = "i2c";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart0: uartlite@c00 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0xc00 0x100>;
|
||||
|
|
|
@ -844,7 +844,7 @@ void __init prom_init(void)
|
|||
* BIST should always be enabled when doing a soft reset. L2
|
||||
* Cache locking for instance is not cleared unless BIST is
|
||||
* enabled. Unfortunately due to a chip errata G-200 for
|
||||
* Cn38XX and CN31XX, BIST msut be disabled on these parts.
|
||||
* Cn38XX and CN31XX, BIST must be disabled on these parts.
|
||||
*/
|
||||
if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) ||
|
||||
OCTEON_IS_MODEL(OCTEON_CN31XX))
|
||||
|
|
|
@ -15,7 +15,7 @@ CONFIG_EXPERT=y
|
|||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_SLAB=y
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_MACH_LOONGSON64=y
|
||||
CONFIG_MACH_LOONGSON2EF=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_MIPS32_O32=y
|
||||
CONFIG_MIPS32_N32=y
|
||||
|
|
|
@ -12,7 +12,7 @@ CONFIG_LOG_BUF_SHIFT=15
|
|||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_EXPERT=y
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_MACH_LOONGSON64=y
|
||||
CONFIG_MACH_LOONGSON2EF=y
|
||||
CONFIG_LEMOTE_MACH2F=y
|
||||
CONFIG_KEXEC=y
|
||||
# CONFIG_SECCOMP is not set
|
||||
|
|
|
@ -12,7 +12,6 @@ CONFIG_TASKSTATS=y
|
|||
CONFIG_TASK_DELAY_ACCT=y
|
||||
CONFIG_TASK_XACCT=y
|
||||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_MEMCG=y
|
||||
CONFIG_MEMCG_SWAP=y
|
||||
CONFIG_BLK_CGROUP=y
|
||||
|
@ -24,7 +23,6 @@ CONFIG_BLK_DEV_INITRD=y
|
|||
CONFIG_SYSCTL_SYSCALL=y
|
||||
CONFIG_EMBEDDED=y
|
||||
CONFIG_MACH_LOONGSON64=y
|
||||
CONFIG_LOONGSON_MACH3X=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_HZ_256=y
|
||||
CONFIG_KEXEC=y
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
# Makefile for the ARC prom monitor library routines under Linux.
|
||||
#
|
||||
|
||||
ifdef CONFIG_ARC_CMDLINE_ONLY
|
||||
lib-y += cmdline.o
|
||||
else
|
||||
lib-y += cmdline.o env.o file.o identify.o init.o \
|
||||
misc.o salone.o time.o tree.o
|
||||
misc.o
|
||||
endif
|
||||
|
||||
lib-$(CONFIG_ARC_MEMORY) += memory.o
|
||||
lib-$(CONFIG_ARC_CONSOLE) += arc_con.o
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
|
||||
#undef DEBUG_CMDLINE
|
||||
|
||||
/*
|
||||
* A 32-bit ARC PROM pass arguments and environment as 32-bit pointer.
|
||||
* These macro take care of sign extension.
|
||||
*/
|
||||
#define prom_argv(index) ((char *) (long)argv[(index)])
|
||||
|
||||
static char *ignored[] = {
|
||||
"ConsoleIn=",
|
||||
"ConsoleOut=",
|
||||
|
@ -32,14 +38,14 @@ static char *used_arc[][2] = {
|
|||
{ "OSLoadOptions=", "" }
|
||||
};
|
||||
|
||||
static char * __init move_firmware_args(char* cp)
|
||||
static char __init *move_firmware_args(int argc, LONG *argv, char *cp)
|
||||
{
|
||||
char *s;
|
||||
int actr, i;
|
||||
|
||||
actr = 1; /* Always ignore argv[0] */
|
||||
|
||||
while (actr < prom_argc) {
|
||||
while (actr < argc) {
|
||||
for(i = 0; i < ARRAY_SIZE(used_arc); i++) {
|
||||
int len = strlen(used_arc[i][0]);
|
||||
|
||||
|
@ -64,7 +70,7 @@ static char * __init move_firmware_args(char* cp)
|
|||
return cp;
|
||||
}
|
||||
|
||||
void __init prom_init_cmdline(void)
|
||||
void __init prom_init_cmdline(int argc, LONG *argv)
|
||||
{
|
||||
char *cp;
|
||||
int actr, i;
|
||||
|
@ -76,9 +82,9 @@ void __init prom_init_cmdline(void)
|
|||
* Move ARC variables to the beginning to make sure they can be
|
||||
* overridden by later arguments.
|
||||
*/
|
||||
cp = move_firmware_args(cp);
|
||||
cp = move_firmware_args(argc, argv, cp);
|
||||
|
||||
while (actr < prom_argc) {
|
||||
while (actr < argc) {
|
||||
for (i = 0; i < ARRAY_SIZE(ignored); i++) {
|
||||
int len = strlen(ignored[i]);
|
||||
|
||||
|
|
|
@ -19,9 +19,3 @@ ArcGetEnvironmentVariable(CHAR *name)
|
|||
{
|
||||
return (CHAR *) ARC_CALL1(get_evar, name);
|
||||
}
|
||||
|
||||
LONG __init
|
||||
ArcSetEnvironmentVariable(PCHAR name, PCHAR value)
|
||||
{
|
||||
return ARC_CALL2(set_evar, name, value);
|
||||
}
|
||||
|
|
|
@ -12,63 +12,14 @@
|
|||
#include <asm/fw/arc/types.h>
|
||||
#include <asm/sgialib.h>
|
||||
|
||||
LONG
|
||||
ArcGetDirectoryEntry(ULONG FileID, struct linux_vdirent *Buffer,
|
||||
ULONG N, ULONG *Count)
|
||||
{
|
||||
return ARC_CALL4(get_vdirent, FileID, Buffer, N, Count);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcOpen(CHAR *Path, enum linux_omode OpenMode, ULONG *FileID)
|
||||
{
|
||||
return ARC_CALL3(open, Path, OpenMode, FileID);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcClose(ULONG FileID)
|
||||
{
|
||||
return ARC_CALL1(close, FileID);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcRead(ULONG FileID, VOID *Buffer, ULONG N, ULONG *Count)
|
||||
{
|
||||
return ARC_CALL4(read, FileID, Buffer, N, Count);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcGetReadStatus(ULONG FileID)
|
||||
{
|
||||
return ARC_CALL1(get_rstatus, FileID);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcWrite(ULONG FileID, PVOID Buffer, ULONG N, PULONG Count)
|
||||
{
|
||||
return ARC_CALL4(write, FileID, Buffer, N, Count);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcSeek(ULONG FileID, struct linux_bigint *Position, enum linux_seekmode SeekMode)
|
||||
{
|
||||
return ARC_CALL3(seek, FileID, Position, SeekMode);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcMount(char *name, enum linux_mountops op)
|
||||
{
|
||||
return ARC_CALL2(mount, name, op);
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcGetFileInformation(ULONG FileID, struct linux_finfo *Information)
|
||||
{
|
||||
return ARC_CALL2(get_finfo, FileID, Information);
|
||||
}
|
||||
|
||||
LONG ArcSetFileInformation(ULONG FileID, ULONG AttributeFlags,
|
||||
ULONG AttributeMask)
|
||||
{
|
||||
return ARC_CALL3(set_finfo, FileID, AttributeFlags, AttributeMask);
|
||||
}
|
||||
|
|
|
@ -31,10 +31,6 @@ static struct smatch mach_table[] = {
|
|||
.arcname = "SGI-IP22",
|
||||
.liname = "SGI Indy",
|
||||
.flags = PROM_FLAG_ARCS,
|
||||
}, {
|
||||
.arcname = "SGI-IP27",
|
||||
.liname = "SGI Origin",
|
||||
.flags = PROM_FLAG_ARCS,
|
||||
}, {
|
||||
.arcname = "SGI-IP28",
|
||||
.liname = "SGI IP28",
|
||||
|
@ -87,6 +83,11 @@ const char *get_system_type(void)
|
|||
return system_type;
|
||||
}
|
||||
|
||||
static pcomponent * __init ArcGetChild(pcomponent *Current)
|
||||
{
|
||||
return (pcomponent *) ARC_CALL1(child_component, Current);
|
||||
}
|
||||
|
||||
void __init prom_identify_arch(void)
|
||||
{
|
||||
pcomponent *p;
|
||||
|
@ -98,13 +99,7 @@ void __init prom_identify_arch(void)
|
|||
*/
|
||||
p = ArcGetChild(PROM_NULL_COMPONENT);
|
||||
if (p == NULL) {
|
||||
#ifdef CONFIG_SGI_IP27
|
||||
/* IP27 PROM misbehaves, seems to not implement ARC
|
||||
GetChild(). So we just assume it's an IP27. */
|
||||
iname = "SGI-IP27";
|
||||
#else
|
||||
iname = "Unknown";
|
||||
#endif
|
||||
} else
|
||||
iname = (char *) (long) p->iname;
|
||||
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
|
||||
/* Master romvec interface. */
|
||||
struct linux_romvec *romvec;
|
||||
int prom_argc;
|
||||
LONG *_prom_argv, *_prom_envp;
|
||||
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
|
||||
/* stack for calling 32bit ARC prom */
|
||||
u64 o32_stk[4096];
|
||||
#endif
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
|
@ -27,10 +30,6 @@ void __init prom_init(void)
|
|||
|
||||
romvec = ROMVECTOR;
|
||||
|
||||
prom_argc = fw_arg0;
|
||||
_prom_argv = (LONG *) fw_arg1;
|
||||
_prom_envp = (LONG *) fw_arg2;
|
||||
|
||||
if (pb->magic != 0x53435241) {
|
||||
printk(KERN_CRIT "Aieee, bad prom vector magic %08lx\n",
|
||||
(unsigned long) pb->magic);
|
||||
|
@ -38,7 +37,7 @@ void __init prom_init(void)
|
|||
;
|
||||
}
|
||||
|
||||
prom_init_cmdline();
|
||||
prom_init_cmdline(fw_arg0, (LONG *)fw_arg1);
|
||||
prom_identify_arch();
|
||||
printk(KERN_INFO "PROMLIB: ARC firmware Version %d Revision %d\n",
|
||||
pb->ver, pb->rev);
|
||||
|
@ -49,11 +48,4 @@ void __init prom_init(void)
|
|||
ArcRead(0, &c, 1, &cnt);
|
||||
ArcEnterInteractiveMode();
|
||||
#endif
|
||||
#ifdef CONFIG_SGI_IP27
|
||||
{
|
||||
extern const struct plat_smp_ops ip27_smp_ops;
|
||||
|
||||
register_smp_ops(&ip27_smp_ops);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -158,6 +158,10 @@ void __init prom_meminit(void)
|
|||
}
|
||||
}
|
||||
|
||||
void __weak __init prom_cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -169,4 +173,9 @@ void __init prom_free_prom_memory(void)
|
|||
free_init_pages("prom memory",
|
||||
prom_mem_base[i], prom_mem_base[i] + prom_mem_size[i]);
|
||||
}
|
||||
/*
|
||||
* at this point it isn't safe to call PROM functions
|
||||
* give platforms a way to do PROM cleanups
|
||||
*/
|
||||
prom_cleanup();
|
||||
}
|
||||
|
|
|
@ -20,47 +20,6 @@
|
|||
#include <asm/sgialib.h>
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
VOID __noreturn
|
||||
ArcHalt(VOID)
|
||||
{
|
||||
bc_disable();
|
||||
local_irq_disable();
|
||||
ARC_CALL0(halt);
|
||||
|
||||
unreachable();
|
||||
}
|
||||
|
||||
VOID __noreturn
|
||||
ArcPowerDown(VOID)
|
||||
{
|
||||
bc_disable();
|
||||
local_irq_disable();
|
||||
ARC_CALL0(pdown);
|
||||
|
||||
unreachable();
|
||||
}
|
||||
|
||||
/* XXX is this a soft reset basically? XXX */
|
||||
VOID __noreturn
|
||||
ArcRestart(VOID)
|
||||
{
|
||||
bc_disable();
|
||||
local_irq_disable();
|
||||
ARC_CALL0(restart);
|
||||
|
||||
unreachable();
|
||||
}
|
||||
|
||||
VOID __noreturn
|
||||
ArcReboot(VOID)
|
||||
{
|
||||
bc_disable();
|
||||
local_irq_disable();
|
||||
ARC_CALL0(reboot);
|
||||
|
||||
unreachable();
|
||||
}
|
||||
|
||||
VOID __noreturn
|
||||
ArcEnterInteractiveMode(VOID)
|
||||
{
|
||||
|
@ -71,24 +30,6 @@ ArcEnterInteractiveMode(VOID)
|
|||
unreachable();
|
||||
}
|
||||
|
||||
LONG
|
||||
ArcSaveConfiguration(VOID)
|
||||
{
|
||||
return ARC_CALL0(cfg_save);
|
||||
}
|
||||
|
||||
struct linux_sysid *
|
||||
ArcGetSystemId(VOID)
|
||||
{
|
||||
return (struct linux_sysid *) ARC_CALL0(get_sysid);
|
||||
}
|
||||
|
||||
VOID __init
|
||||
ArcFlushAllCaches(VOID)
|
||||
{
|
||||
ARC_CALL0(cache_flush);
|
||||
}
|
||||
|
||||
DISPLAY_STATUS * __init ArcGetDisplayStatus(ULONG FileID)
|
||||
{
|
||||
return (DISPLAY_STATUS *) ARC_CALL1(GetDisplayStatus, FileID);
|
||||
|
|
|
@ -11,6 +11,21 @@
|
|||
#include <asm/bcache.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
|
||||
/*
|
||||
* For 64bit kernels working with a 32bit ARC PROM pointer arguments
|
||||
* for ARC calls need to reside in CKEG0/1. But as soon as the kernel
|
||||
* switches to it's first kernel thread stack is set to an address in
|
||||
* XKPHYS, so anything on stack can't be used anymore. This is solved
|
||||
* by using a * static declartion variables are put into BSS, which is
|
||||
* linked to a CKSEG0 address. Since this is only used on UP platforms
|
||||
* there is not spinlock needed
|
||||
*/
|
||||
#define O32_STATIC static
|
||||
#else
|
||||
#define O32_STATIC
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IP22 boardcache is not compatible with board caches. Thus we disable it
|
||||
* during romvec action. Since r4xx0.c is always compiled and linked with your
|
||||
|
@ -23,8 +38,10 @@
|
|||
|
||||
void prom_putchar(char c)
|
||||
{
|
||||
ULONG cnt;
|
||||
CHAR it = c;
|
||||
O32_STATIC ULONG cnt;
|
||||
O32_STATIC CHAR it;
|
||||
|
||||
it = c;
|
||||
|
||||
bc_disable();
|
||||
ArcWrite(1, &it, 1, &cnt);
|
||||
|
@ -33,8 +50,8 @@ void prom_putchar(char c)
|
|||
|
||||
char prom_getchar(void)
|
||||
{
|
||||
ULONG cnt;
|
||||
CHAR c;
|
||||
O32_STATIC ULONG cnt;
|
||||
O32_STATIC CHAR c;
|
||||
|
||||
bc_disable();
|
||||
ArcRead(0, &c, 1, &cnt);
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Routines to load into memory and execute stand-along program images using
|
||||
* ARCS PROM firmware.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <asm/sgialib.h>
|
||||
|
||||
LONG __init ArcLoad(CHAR *Path, ULONG TopAddr, ULONG *ExecAddr, ULONG *LowAddr)
|
||||
{
|
||||
return ARC_CALL4(load, Path, TopAddr, ExecAddr, LowAddr);
|
||||
}
|
||||
|
||||
LONG __init ArcInvoke(ULONG ExecAddr, ULONG StackAddr, ULONG Argc, CHAR *Argv[],
|
||||
CHAR *Envp[])
|
||||
{
|
||||
return ARC_CALL5(invoke, ExecAddr, StackAddr, Argc, Argv, Envp);
|
||||
}
|
||||
|
||||
LONG __init ArcExecute(CHAR *Path, LONG Argc, CHAR *Argv[], CHAR *Envp[])
|
||||
{
|
||||
return ARC_CALL4(exec, Path, Argc, Argv, Envp);
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Extracting time information from ARCS prom.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/fw/arc/types.h>
|
||||
#include <asm/sgialib.h>
|
||||
|
||||
struct linux_tinfo * __init
|
||||
ArcGetTime(VOID)
|
||||
{
|
||||
return (struct linux_tinfo *) ARC_CALL0(get_tinfo);
|
||||
}
|
||||
|
||||
ULONG __init
|
||||
ArcGetRelativeTime(VOID)
|
||||
{
|
||||
return ARC_CALL0(get_rtime);
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* PROM component device tree code.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@davemloft.net)
|
||||
* Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
|
||||
* Copyright (C) 1999 Silicon Graphics, Inc.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <asm/fw/arc/types.h>
|
||||
#include <asm/sgialib.h>
|
||||
|
||||
#undef DEBUG_PROM_TREE
|
||||
|
||||
pcomponent * __init
|
||||
ArcGetPeer(pcomponent *Current)
|
||||
{
|
||||
if (Current == PROM_NULL_COMPONENT)
|
||||
return PROM_NULL_COMPONENT;
|
||||
|
||||
return (pcomponent *) ARC_CALL1(next_component, Current);
|
||||
}
|
||||
|
||||
pcomponent * __init
|
||||
ArcGetChild(pcomponent *Current)
|
||||
{
|
||||
return (pcomponent *) ARC_CALL1(child_component, Current);
|
||||
}
|
||||
|
||||
pcomponent * __init
|
||||
ArcGetParent(pcomponent *Current)
|
||||
{
|
||||
if (Current == PROM_NULL_COMPONENT)
|
||||
return PROM_NULL_COMPONENT;
|
||||
|
||||
return (pcomponent *) ARC_CALL1(parent_component, Current);
|
||||
}
|
||||
|
||||
LONG __init
|
||||
ArcGetConfigurationData(VOID *Buffer, pcomponent *Current)
|
||||
{
|
||||
return ARC_CALL2(component_data, Buffer, Current);
|
||||
}
|
||||
|
||||
pcomponent * __init
|
||||
ArcAddChild(pcomponent *Current, pcomponent *Template, VOID *ConfigurationData)
|
||||
{
|
||||
return (pcomponent *)
|
||||
ARC_CALL3(child_add, Current, Template, ConfigurationData);
|
||||
}
|
||||
|
||||
LONG __init
|
||||
ArcDeleteComponent(pcomponent *ComponentToDelete)
|
||||
{
|
||||
return ARC_CALL1(comp_del, ComponentToDelete);
|
||||
}
|
||||
|
||||
pcomponent * __init
|
||||
ArcGetComponent(CHAR *Path)
|
||||
{
|
||||
return (pcomponent *)ARC_CALL1(component_by_path, Path);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PROM_TREE
|
||||
|
||||
static char *classes[] = {
|
||||
"system", "processor", "cache", "adapter", "controller", "peripheral",
|
||||
"memory"
|
||||
};
|
||||
|
||||
static char *types[] = {
|
||||
"arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache",
|
||||
"sccache", "memdev", "eisa adapter", "tc adapter", "scsi adapter",
|
||||
"dti adapter", "multi-func adapter", "disk controller",
|
||||
"tp controller", "cdrom controller", "worm controller",
|
||||
"serial controller", "net controller", "display controller",
|
||||
"parallel controller", "pointer controller", "keyboard controller",
|
||||
"audio controller", "misc controller", "disk peripheral",
|
||||
"floppy peripheral", "tp peripheral", "modem peripheral",
|
||||
"monitor peripheral", "printer peripheral", "pointer peripheral",
|
||||
"keyboard peripheral", "terminal peripheral", "line peripheral",
|
||||
"net peripheral", "misc peripheral", "anonymous"
|
||||
};
|
||||
|
||||
static char *iflags[] = {
|
||||
"bogus", "read only", "removable", "console in", "console out",
|
||||
"input", "output"
|
||||
};
|
||||
|
||||
static void __init
|
||||
dump_component(pcomponent *p)
|
||||
{
|
||||
printk("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
|
||||
p, classes[p->class], types[p->type],
|
||||
iflags[p->iflags], p->vers, p->rev);
|
||||
printk("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n",
|
||||
p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
|
||||
}
|
||||
|
||||
static void __init
|
||||
traverse(pcomponent *p, int op)
|
||||
{
|
||||
dump_component(p);
|
||||
if(ArcGetChild(p))
|
||||
traverse(ArcGetChild(p), 1);
|
||||
if(ArcGetPeer(p) && op)
|
||||
traverse(ArcGetPeer(p), 1);
|
||||
}
|
||||
|
||||
void __init
|
||||
prom_testtree(void)
|
||||
{
|
||||
pcomponent *p;
|
||||
|
||||
p = ArcGetChild(PROM_NULL_COMPONENT);
|
||||
dump_component(p);
|
||||
p = ArcGetChild(p);
|
||||
while(p) {
|
||||
dump_component(p);
|
||||
p = ArcGetPeer(p);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG_PROM_TREE */
|
|
@ -20,9 +20,9 @@
|
|||
#include <asm/smp-ops.h>
|
||||
#include <asm/time.h>
|
||||
|
||||
static __initdata const void *fdt;
|
||||
static __initdata const struct mips_machine *mach;
|
||||
static __initdata const void *mach_match_data;
|
||||
static __initconst const void *fdt;
|
||||
static __initconst const struct mips_machine *mach;
|
||||
static __initconst const void *mach_match_data;
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
|
|
|
@ -20,157 +20,176 @@
|
|||
#include <asm/compiler.h>
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/llsc.h>
|
||||
#include <asm/sync.h>
|
||||
#include <asm/war.h>
|
||||
|
||||
/*
|
||||
* Using a branch-likely instruction to check the result of an sc instruction
|
||||
* works around a bug present in R10000 CPUs prior to revision 3.0 that could
|
||||
* cause ll-sc sequences to execute non-atomically.
|
||||
*/
|
||||
#if R10000_LLSC_WAR
|
||||
# define __scbeqz "beqzl"
|
||||
#else
|
||||
# define __scbeqz "beqz"
|
||||
#define ATOMIC_OPS(pfx, type) \
|
||||
static __always_inline type pfx##_read(const pfx##_t *v) \
|
||||
{ \
|
||||
return READ_ONCE(v->counter); \
|
||||
} \
|
||||
\
|
||||
static __always_inline void pfx##_set(pfx##_t *v, type i) \
|
||||
{ \
|
||||
WRITE_ONCE(v->counter, i); \
|
||||
} \
|
||||
\
|
||||
static __always_inline type pfx##_cmpxchg(pfx##_t *v, type o, type n) \
|
||||
{ \
|
||||
return cmpxchg(&v->counter, o, n); \
|
||||
} \
|
||||
\
|
||||
static __always_inline type pfx##_xchg(pfx##_t *v, type n) \
|
||||
{ \
|
||||
return xchg(&v->counter, n); \
|
||||
}
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
ATOMIC_OPS(atomic, int)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
# define ATOMIC64_INIT(i) { (i) }
|
||||
ATOMIC_OPS(atomic64, s64)
|
||||
#endif
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
/*
|
||||
* atomic_read - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v.
|
||||
*/
|
||||
#define atomic_read(v) READ_ONCE((v)->counter)
|
||||
|
||||
/*
|
||||
* atomic_set - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i.
|
||||
*/
|
||||
#define atomic_set(v, i) WRITE_ONCE((v)->counter, (i))
|
||||
|
||||
#define ATOMIC_OP(op, c_op, asm_op) \
|
||||
static __inline__ void atomic_##op(int i, atomic_t * v) \
|
||||
{ \
|
||||
if (kernel_uses_llsc) { \
|
||||
int temp; \
|
||||
\
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_LEVEL" \n" \
|
||||
"1: ll %0, %1 # atomic_" #op " \n" \
|
||||
" " #asm_op " %0, %2 \n" \
|
||||
" sc %0, %1 \n" \
|
||||
"\t" __scbeqz " %0, 1b \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
} else { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
v->counter c_op i; \
|
||||
raw_local_irq_restore(flags); \
|
||||
} \
|
||||
#define ATOMIC_OP(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
static __inline__ void pfx##_##op(type i, pfx##_t * v) \
|
||||
{ \
|
||||
type temp; \
|
||||
\
|
||||
if (!kernel_uses_llsc) { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
v->counter c_op i; \
|
||||
raw_local_irq_restore(flags); \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_LEVEL " \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " #ll " %0, %1 # " #pfx "_" #op " \n" \
|
||||
" " #asm_op " %0, %2 \n" \
|
||||
" " #sc " %0, %1 \n" \
|
||||
"\t" __SC_BEQZ "%0, 1b \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
}
|
||||
|
||||
#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
|
||||
static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v) \
|
||||
{ \
|
||||
int result; \
|
||||
\
|
||||
if (kernel_uses_llsc) { \
|
||||
int temp; \
|
||||
\
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_LEVEL" \n" \
|
||||
"1: ll %1, %2 # atomic_" #op "_return \n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" sc %0, %2 \n" \
|
||||
"\t" __scbeqz " %0, 1b \n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (result), "=&r" (temp), \
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
} else { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
result = v->counter; \
|
||||
result c_op i; \
|
||||
v->counter = result; \
|
||||
raw_local_irq_restore(flags); \
|
||||
} \
|
||||
\
|
||||
return result; \
|
||||
#define ATOMIC_OP_RETURN(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
static __inline__ type pfx##_##op##_return_relaxed(type i, pfx##_t * v) \
|
||||
{ \
|
||||
type temp, result; \
|
||||
\
|
||||
if (!kernel_uses_llsc) { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
result = v->counter; \
|
||||
result c_op i; \
|
||||
v->counter = result; \
|
||||
raw_local_irq_restore(flags); \
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_LEVEL " \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " #ll " %1, %2 # " #pfx "_" #op "_return\n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" " #sc " %0, %2 \n" \
|
||||
"\t" __SC_BEQZ "%0, 1b \n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (result), "=&r" (temp), \
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ATOMIC_FETCH_OP(op, c_op, asm_op) \
|
||||
static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \
|
||||
{ \
|
||||
int result; \
|
||||
\
|
||||
if (kernel_uses_llsc) { \
|
||||
int temp; \
|
||||
\
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_LEVEL" \n" \
|
||||
"1: ll %1, %2 # atomic_fetch_" #op " \n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" sc %0, %2 \n" \
|
||||
"\t" __scbeqz " %0, 1b \n" \
|
||||
" .set pop \n" \
|
||||
" move %0, %1 \n" \
|
||||
: "=&r" (result), "=&r" (temp), \
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
} else { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
result = v->counter; \
|
||||
v->counter c_op i; \
|
||||
raw_local_irq_restore(flags); \
|
||||
} \
|
||||
\
|
||||
return result; \
|
||||
#define ATOMIC_FETCH_OP(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
static __inline__ type pfx##_fetch_##op##_relaxed(type i, pfx##_t * v) \
|
||||
{ \
|
||||
int temp, result; \
|
||||
\
|
||||
if (!kernel_uses_llsc) { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
result = v->counter; \
|
||||
v->counter c_op i; \
|
||||
raw_local_irq_restore(flags); \
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_LEVEL " \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " #ll " %1, %2 # " #pfx "_fetch_" #op "\n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" " #sc " %0, %2 \n" \
|
||||
"\t" __SC_BEQZ "%0, 1b \n" \
|
||||
" .set pop \n" \
|
||||
" move %0, %1 \n" \
|
||||
: "=&r" (result), "=&r" (temp), \
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ATOMIC_OPS(op, c_op, asm_op) \
|
||||
ATOMIC_OP(op, c_op, asm_op) \
|
||||
ATOMIC_OP_RETURN(op, c_op, asm_op) \
|
||||
ATOMIC_FETCH_OP(op, c_op, asm_op)
|
||||
#undef ATOMIC_OPS
|
||||
#define ATOMIC_OPS(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
ATOMIC_OP(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
ATOMIC_OP_RETURN(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
ATOMIC_FETCH_OP(pfx, op, type, c_op, asm_op, ll, sc)
|
||||
|
||||
ATOMIC_OPS(add, +=, addu)
|
||||
ATOMIC_OPS(sub, -=, subu)
|
||||
ATOMIC_OPS(atomic, add, int, +=, addu, ll, sc)
|
||||
ATOMIC_OPS(atomic, sub, int, -=, subu, ll, sc)
|
||||
|
||||
#define atomic_add_return_relaxed atomic_add_return_relaxed
|
||||
#define atomic_sub_return_relaxed atomic_sub_return_relaxed
|
||||
#define atomic_fetch_add_relaxed atomic_fetch_add_relaxed
|
||||
#define atomic_fetch_sub_relaxed atomic_fetch_sub_relaxed
|
||||
|
||||
#undef ATOMIC_OPS
|
||||
#define ATOMIC_OPS(op, c_op, asm_op) \
|
||||
ATOMIC_OP(op, c_op, asm_op) \
|
||||
ATOMIC_FETCH_OP(op, c_op, asm_op)
|
||||
#ifdef CONFIG_64BIT
|
||||
ATOMIC_OPS(atomic64, add, s64, +=, daddu, lld, scd)
|
||||
ATOMIC_OPS(atomic64, sub, s64, -=, dsubu, lld, scd)
|
||||
# define atomic64_add_return_relaxed atomic64_add_return_relaxed
|
||||
# define atomic64_sub_return_relaxed atomic64_sub_return_relaxed
|
||||
# define atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed
|
||||
# define atomic64_fetch_sub_relaxed atomic64_fetch_sub_relaxed
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
ATOMIC_OPS(and, &=, and)
|
||||
ATOMIC_OPS(or, |=, or)
|
||||
ATOMIC_OPS(xor, ^=, xor)
|
||||
#undef ATOMIC_OPS
|
||||
#define ATOMIC_OPS(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
ATOMIC_OP(pfx, op, type, c_op, asm_op, ll, sc) \
|
||||
ATOMIC_FETCH_OP(pfx, op, type, c_op, asm_op, ll, sc)
|
||||
|
||||
ATOMIC_OPS(atomic, and, int, &=, and, ll, sc)
|
||||
ATOMIC_OPS(atomic, or, int, |=, or, ll, sc)
|
||||
ATOMIC_OPS(atomic, xor, int, ^=, xor, ll, sc)
|
||||
|
||||
#define atomic_fetch_and_relaxed atomic_fetch_and_relaxed
|
||||
#define atomic_fetch_or_relaxed atomic_fetch_or_relaxed
|
||||
#define atomic_fetch_xor_relaxed atomic_fetch_xor_relaxed
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
ATOMIC_OPS(atomic64, and, s64, &=, and, lld, scd)
|
||||
ATOMIC_OPS(atomic64, or, s64, |=, or, lld, scd)
|
||||
ATOMIC_OPS(atomic64, xor, s64, ^=, xor, lld, scd)
|
||||
# define atomic64_fetch_and_relaxed atomic64_fetch_and_relaxed
|
||||
# define atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed
|
||||
# define atomic64_fetch_xor_relaxed atomic64_fetch_xor_relaxed
|
||||
#endif
|
||||
|
||||
#undef ATOMIC_OPS
|
||||
#undef ATOMIC_FETCH_OP
|
||||
#undef ATOMIC_OP_RETURN
|
||||
|
@ -184,258 +203,66 @@ ATOMIC_OPS(xor, ^=, xor)
|
|||
* Atomically test @v and subtract @i if @v is greater or equal than @i.
|
||||
* The function returns the old value of @v minus @i.
|
||||
*/
|
||||
static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
|
||||
{
|
||||
int result;
|
||||
|
||||
smp_mb__before_llsc();
|
||||
|
||||
if (kernel_uses_llsc) {
|
||||
int temp;
|
||||
|
||||
loongson_llsc_mb();
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_LEVEL" \n"
|
||||
"1: ll %1, %2 # atomic_sub_if_positive\n"
|
||||
" .set pop \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
" move %1, %0 \n"
|
||||
" bltz %0, 2f \n"
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_LEVEL" \n"
|
||||
" sc %1, %2 \n"
|
||||
"\t" __scbeqz " %1, 1b \n"
|
||||
"2: \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (result), "=&r" (temp),
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||
: "Ir" (i) : __LLSC_CLOBBER);
|
||||
} else {
|
||||
unsigned long flags;
|
||||
|
||||
raw_local_irq_save(flags);
|
||||
result = v->counter;
|
||||
result -= i;
|
||||
if (result >= 0)
|
||||
v->counter = result;
|
||||
raw_local_irq_restore(flags);
|
||||
}
|
||||
|
||||
smp_llsc_mb();
|
||||
|
||||
return result;
|
||||
#define ATOMIC_SIP_OP(pfx, type, op, ll, sc) \
|
||||
static __inline__ int pfx##_sub_if_positive(type i, pfx##_t * v) \
|
||||
{ \
|
||||
type temp, result; \
|
||||
\
|
||||
smp_mb__before_atomic(); \
|
||||
\
|
||||
if (!kernel_uses_llsc) { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
result = v->counter; \
|
||||
result -= i; \
|
||||
if (result >= 0) \
|
||||
v->counter = result; \
|
||||
raw_local_irq_restore(flags); \
|
||||
smp_mb__after_atomic(); \
|
||||
return result; \
|
||||
} \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_LEVEL " \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " #ll " %1, %2 # atomic_sub_if_positive\n" \
|
||||
" .set pop \n" \
|
||||
" " #op " %0, %1, %3 \n" \
|
||||
" move %1, %0 \n" \
|
||||
" bltz %0, 2f \n" \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_LEVEL " \n" \
|
||||
" " #sc " %1, %2 \n" \
|
||||
" " __SC_BEQZ "%1, 1b \n" \
|
||||
"2: " __SYNC(full, loongson3_war) " \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (result), "=&r" (temp), \
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) \
|
||||
: __LLSC_CLOBBER); \
|
||||
\
|
||||
/* \
|
||||
* In the Loongson3 workaround case we already have a \
|
||||
* completion barrier at 2: above, which is needed due to the \
|
||||
* bltz that can branch to code outside of the LL/SC loop. As \
|
||||
* such, we don't need to emit another barrier here. \
|
||||
*/ \
|
||||
if (!__SYNC_loongson3_war) \
|
||||
smp_mb__after_atomic(); \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
|
||||
#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
|
||||
|
||||
/*
|
||||
* atomic_dec_if_positive - decrement by 1 if old value positive
|
||||
* @v: pointer of type atomic_t
|
||||
*/
|
||||
ATOMIC_SIP_OP(atomic, int, subu, ll, sc)
|
||||
#define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
#define ATOMIC64_INIT(i) { (i) }
|
||||
|
||||
/*
|
||||
* atomic64_read - read atomic variable
|
||||
* @v: pointer of type atomic64_t
|
||||
*
|
||||
*/
|
||||
#define atomic64_read(v) READ_ONCE((v)->counter)
|
||||
|
||||
/*
|
||||
* atomic64_set - set atomic variable
|
||||
* @v: pointer of type atomic64_t
|
||||
* @i: required value
|
||||
*/
|
||||
#define atomic64_set(v, i) WRITE_ONCE((v)->counter, (i))
|
||||
|
||||
#define ATOMIC64_OP(op, c_op, asm_op) \
|
||||
static __inline__ void atomic64_##op(s64 i, atomic64_t * v) \
|
||||
{ \
|
||||
if (kernel_uses_llsc) { \
|
||||
s64 temp; \
|
||||
\
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_LEVEL" \n" \
|
||||
"1: lld %0, %1 # atomic64_" #op " \n" \
|
||||
" " #asm_op " %0, %2 \n" \
|
||||
" scd %0, %1 \n" \
|
||||
"\t" __scbeqz " %0, 1b \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
} else { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
v->counter c_op i; \
|
||||
raw_local_irq_restore(flags); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ATOMIC64_OP_RETURN(op, c_op, asm_op) \
|
||||
static __inline__ s64 atomic64_##op##_return_relaxed(s64 i, atomic64_t * v) \
|
||||
{ \
|
||||
s64 result; \
|
||||
\
|
||||
if (kernel_uses_llsc) { \
|
||||
s64 temp; \
|
||||
\
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_LEVEL" \n" \
|
||||
"1: lld %1, %2 # atomic64_" #op "_return\n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" scd %0, %2 \n" \
|
||||
"\t" __scbeqz " %0, 1b \n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (result), "=&r" (temp), \
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
} else { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
result = v->counter; \
|
||||
result c_op i; \
|
||||
v->counter = result; \
|
||||
raw_local_irq_restore(flags); \
|
||||
} \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ATOMIC64_FETCH_OP(op, c_op, asm_op) \
|
||||
static __inline__ s64 atomic64_fetch_##op##_relaxed(s64 i, atomic64_t * v) \
|
||||
{ \
|
||||
s64 result; \
|
||||
\
|
||||
if (kernel_uses_llsc) { \
|
||||
s64 temp; \
|
||||
\
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_LEVEL" \n" \
|
||||
"1: lld %1, %2 # atomic64_fetch_" #op "\n" \
|
||||
" " #asm_op " %0, %1, %3 \n" \
|
||||
" scd %0, %2 \n" \
|
||||
"\t" __scbeqz " %0, 1b \n" \
|
||||
" move %0, %1 \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (result), "=&r" (temp), \
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter) \
|
||||
: "Ir" (i) : __LLSC_CLOBBER); \
|
||||
} else { \
|
||||
unsigned long flags; \
|
||||
\
|
||||
raw_local_irq_save(flags); \
|
||||
result = v->counter; \
|
||||
v->counter c_op i; \
|
||||
raw_local_irq_restore(flags); \
|
||||
} \
|
||||
\
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ATOMIC64_OPS(op, c_op, asm_op) \
|
||||
ATOMIC64_OP(op, c_op, asm_op) \
|
||||
ATOMIC64_OP_RETURN(op, c_op, asm_op) \
|
||||
ATOMIC64_FETCH_OP(op, c_op, asm_op)
|
||||
|
||||
ATOMIC64_OPS(add, +=, daddu)
|
||||
ATOMIC64_OPS(sub, -=, dsubu)
|
||||
|
||||
#define atomic64_add_return_relaxed atomic64_add_return_relaxed
|
||||
#define atomic64_sub_return_relaxed atomic64_sub_return_relaxed
|
||||
#define atomic64_fetch_add_relaxed atomic64_fetch_add_relaxed
|
||||
#define atomic64_fetch_sub_relaxed atomic64_fetch_sub_relaxed
|
||||
|
||||
#undef ATOMIC64_OPS
|
||||
#define ATOMIC64_OPS(op, c_op, asm_op) \
|
||||
ATOMIC64_OP(op, c_op, asm_op) \
|
||||
ATOMIC64_FETCH_OP(op, c_op, asm_op)
|
||||
|
||||
ATOMIC64_OPS(and, &=, and)
|
||||
ATOMIC64_OPS(or, |=, or)
|
||||
ATOMIC64_OPS(xor, ^=, xor)
|
||||
|
||||
#define atomic64_fetch_and_relaxed atomic64_fetch_and_relaxed
|
||||
#define atomic64_fetch_or_relaxed atomic64_fetch_or_relaxed
|
||||
#define atomic64_fetch_xor_relaxed atomic64_fetch_xor_relaxed
|
||||
|
||||
#undef ATOMIC64_OPS
|
||||
#undef ATOMIC64_FETCH_OP
|
||||
#undef ATOMIC64_OP_RETURN
|
||||
#undef ATOMIC64_OP
|
||||
|
||||
/*
|
||||
* atomic64_sub_if_positive - conditionally subtract integer from atomic
|
||||
* variable
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type atomic64_t
|
||||
*
|
||||
* Atomically test @v and subtract @i if @v is greater or equal than @i.
|
||||
* The function returns the old value of @v minus @i.
|
||||
*/
|
||||
static __inline__ s64 atomic64_sub_if_positive(s64 i, atomic64_t * v)
|
||||
{
|
||||
s64 result;
|
||||
|
||||
smp_mb__before_llsc();
|
||||
|
||||
if (kernel_uses_llsc) {
|
||||
s64 temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_LEVEL" \n"
|
||||
"1: lld %1, %2 # atomic64_sub_if_positive\n"
|
||||
" dsubu %0, %1, %3 \n"
|
||||
" move %1, %0 \n"
|
||||
" bltz %0, 1f \n"
|
||||
" scd %1, %2 \n"
|
||||
"\t" __scbeqz " %1, 1b \n"
|
||||
"1: \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (result), "=&r" (temp),
|
||||
"+" GCC_OFF_SMALL_ASM() (v->counter)
|
||||
: "Ir" (i));
|
||||
} else {
|
||||
unsigned long flags;
|
||||
|
||||
raw_local_irq_save(flags);
|
||||
result = v->counter;
|
||||
result -= i;
|
||||
if (result >= 0)
|
||||
v->counter = result;
|
||||
raw_local_irq_restore(flags);
|
||||
}
|
||||
|
||||
smp_llsc_mb();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define atomic64_cmpxchg(v, o, n) \
|
||||
((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
|
||||
#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new)))
|
||||
|
||||
/*
|
||||
* atomic64_dec_if_positive - decrement by 1 if old value positive
|
||||
* @v: pointer of type atomic64_t
|
||||
*/
|
||||
ATOMIC_SIP_OP(atomic64, s64, dsubu, lld, scd)
|
||||
#define atomic64_dec_if_positive(v) atomic64_sub_if_positive(1, v)
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
#undef ATOMIC_SIP_OP
|
||||
|
||||
#endif /* _ASM_ATOMIC_H */
|
||||
|
|
|
@ -9,131 +9,26 @@
|
|||
#define __ASM_BARRIER_H
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/sync.h>
|
||||
|
||||
/*
|
||||
* Sync types defined by the MIPS architecture (document MD00087 table 6.5)
|
||||
* These values are used with the sync instruction to perform memory barriers.
|
||||
* Types of ordering guarantees available through the SYNC instruction:
|
||||
* - Completion Barriers
|
||||
* - Ordering Barriers
|
||||
* As compared to the completion barrier, the ordering barrier is a
|
||||
* lighter-weight operation as it does not require the specified instructions
|
||||
* before the SYNC to be already completed. Instead it only requires that those
|
||||
* specified instructions which are subsequent to the SYNC in the instruction
|
||||
* stream are never re-ordered for processing ahead of the specified
|
||||
* instructions which are before the SYNC in the instruction stream.
|
||||
* This potentially reduces how many cycles the barrier instruction must stall
|
||||
* before it completes.
|
||||
* Implementations that do not use any of the non-zero values of stype to define
|
||||
* different barriers, such as ordering barriers, must make those stype values
|
||||
* act the same as stype zero.
|
||||
*/
|
||||
static inline void __sync(void)
|
||||
{
|
||||
asm volatile(__SYNC(full, always) ::: "memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* Completion barriers:
|
||||
* - Every synchronizable specified memory instruction (loads or stores or both)
|
||||
* that occurs in the instruction stream before the SYNC instruction must be
|
||||
* already globally performed before any synchronizable specified memory
|
||||
* instructions that occur after the SYNC are allowed to be performed, with
|
||||
* respect to any other processor or coherent I/O module.
|
||||
*
|
||||
* - The barrier does not guarantee the order in which instruction fetches are
|
||||
* performed.
|
||||
*
|
||||
* - A stype value of zero will always be defined such that it performs the most
|
||||
* complete set of synchronization operations that are defined.This means
|
||||
* stype zero always does a completion barrier that affects both loads and
|
||||
* stores preceding the SYNC instruction and both loads and stores that are
|
||||
* subsequent to the SYNC instruction. Non-zero values of stype may be defined
|
||||
* by the architecture or specific implementations to perform synchronization
|
||||
* behaviors that are less complete than that of stype zero. If an
|
||||
* implementation does not use one of these non-zero values to define a
|
||||
* different synchronization behavior, then that non-zero value of stype must
|
||||
* act the same as stype zero completion barrier. This allows software written
|
||||
* for an implementation with a lighter-weight barrier to work on another
|
||||
* implementation which only implements the stype zero completion barrier.
|
||||
*
|
||||
* - A completion barrier is required, potentially in conjunction with SSNOP (in
|
||||
* Release 1 of the Architecture) or EHB (in Release 2 of the Architecture),
|
||||
* to guarantee that memory reference results are visible across operating
|
||||
* mode changes. For example, a completion barrier is required on some
|
||||
* implementations on entry to and exit from Debug Mode to guarantee that
|
||||
* memory effects are handled correctly.
|
||||
*/
|
||||
static inline void rmb(void)
|
||||
{
|
||||
asm volatile(__SYNC(rmb, always) ::: "memory");
|
||||
}
|
||||
#define rmb rmb
|
||||
|
||||
/*
|
||||
* stype 0 - A completion barrier that affects preceding loads and stores and
|
||||
* subsequent loads and stores.
|
||||
* Older instructions which must reach the load/store ordering point before the
|
||||
* SYNC instruction completes: Loads, Stores
|
||||
* Younger instructions which must reach the load/store ordering point only
|
||||
* after the SYNC instruction completes: Loads, Stores
|
||||
* Older instructions which must be globally performed when the SYNC instruction
|
||||
* completes: Loads, Stores
|
||||
*/
|
||||
#define STYPE_SYNC 0x0
|
||||
static inline void wmb(void)
|
||||
{
|
||||
asm volatile(__SYNC(wmb, always) ::: "memory");
|
||||
}
|
||||
#define wmb wmb
|
||||
|
||||
/*
|
||||
* Ordering barriers:
|
||||
* - Every synchronizable specified memory instruction (loads or stores or both)
|
||||
* that occurs in the instruction stream before the SYNC instruction must
|
||||
* reach a stage in the load/store datapath after which no instruction
|
||||
* re-ordering is possible before any synchronizable specified memory
|
||||
* instruction which occurs after the SYNC instruction in the instruction
|
||||
* stream reaches the same stage in the load/store datapath.
|
||||
*
|
||||
* - If any memory instruction before the SYNC instruction in program order,
|
||||
* generates a memory request to the external memory and any memory
|
||||
* instruction after the SYNC instruction in program order also generates a
|
||||
* memory request to external memory, the memory request belonging to the
|
||||
* older instruction must be globally performed before the time the memory
|
||||
* request belonging to the younger instruction is globally performed.
|
||||
*
|
||||
* - The barrier does not guarantee the order in which instruction fetches are
|
||||
* performed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* stype 0x10 - An ordering barrier that affects preceding loads and stores and
|
||||
* subsequent loads and stores.
|
||||
* Older instructions which must reach the load/store ordering point before the
|
||||
* SYNC instruction completes: Loads, Stores
|
||||
* Younger instructions which must reach the load/store ordering point only
|
||||
* after the SYNC instruction completes: Loads, Stores
|
||||
* Older instructions which must be globally performed when the SYNC instruction
|
||||
* completes: N/A
|
||||
*/
|
||||
#define STYPE_SYNC_MB 0x10
|
||||
|
||||
/*
|
||||
* stype 0x14 - A completion barrier specific to global invalidations
|
||||
*
|
||||
* When a sync instruction of this type completes any preceding GINVI or GINVT
|
||||
* operation has been globalized & completed on all coherent CPUs. Anything
|
||||
* that the GINV* instruction should invalidate will have been invalidated on
|
||||
* all coherent CPUs when this instruction completes. It is implementation
|
||||
* specific whether the GINV* instructions themselves will ensure completion,
|
||||
* or this sync type will.
|
||||
*
|
||||
* In systems implementing global invalidates (ie. with Config5.GI == 2 or 3)
|
||||
* this sync type also requires that previous SYNCI operations have completed.
|
||||
*/
|
||||
#define STYPE_GINV 0x14
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_SYNC
|
||||
#define __sync() \
|
||||
__asm__ __volatile__( \
|
||||
".set push\n\t" \
|
||||
".set noreorder\n\t" \
|
||||
".set mips2\n\t" \
|
||||
"sync\n\t" \
|
||||
".set pop" \
|
||||
: /* no output */ \
|
||||
: /* no input */ \
|
||||
: "memory")
|
||||
#else
|
||||
#define __sync() do { } while(0)
|
||||
#endif
|
||||
#define fast_mb() __sync()
|
||||
|
||||
#define __fast_iob() \
|
||||
__asm__ __volatile__( \
|
||||
|
@ -146,17 +41,8 @@
|
|||
: "m" (*(int *)CKSEG1) \
|
||||
: "memory")
|
||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||
# define OCTEON_SYNCW_STR ".set push\n.set arch=octeon\nsyncw\nsyncw\n.set pop\n"
|
||||
# define __syncw() __asm__ __volatile__(OCTEON_SYNCW_STR : : : "memory")
|
||||
|
||||
# define fast_wmb() __syncw()
|
||||
# define fast_rmb() barrier()
|
||||
# define fast_mb() __sync()
|
||||
# define fast_iob() do { } while (0)
|
||||
#else /* ! CONFIG_CPU_CAVIUM_OCTEON */
|
||||
# define fast_wmb() __sync()
|
||||
# define fast_rmb() __sync()
|
||||
# define fast_mb() __sync()
|
||||
# ifdef CONFIG_SGI_IP28
|
||||
# define fast_iob() \
|
||||
__asm__ __volatile__( \
|
||||
|
@ -192,23 +78,14 @@
|
|||
|
||||
#endif /* !CONFIG_CPU_HAS_WB */
|
||||
|
||||
#define wmb() fast_wmb()
|
||||
#define rmb() fast_rmb()
|
||||
|
||||
#if defined(CONFIG_WEAK_ORDERING)
|
||||
# ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||
# define __smp_mb() __sync()
|
||||
# define __smp_rmb() barrier()
|
||||
# define __smp_wmb() __syncw()
|
||||
# else
|
||||
# define __smp_mb() __asm__ __volatile__("sync" : : :"memory")
|
||||
# define __smp_rmb() __asm__ __volatile__("sync" : : :"memory")
|
||||
# define __smp_wmb() __asm__ __volatile__("sync" : : :"memory")
|
||||
# endif
|
||||
# define __smp_mb() __sync()
|
||||
# define __smp_rmb() rmb()
|
||||
# define __smp_wmb() wmb()
|
||||
#else
|
||||
#define __smp_mb() barrier()
|
||||
#define __smp_rmb() barrier()
|
||||
#define __smp_wmb() barrier()
|
||||
# define __smp_mb() barrier()
|
||||
# define __smp_rmb() barrier()
|
||||
# define __smp_wmb() barrier()
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -218,13 +95,14 @@
|
|||
* ordering will be done by smp_llsc_mb() and friends.
|
||||
*/
|
||||
#if defined(CONFIG_WEAK_REORDERING_BEYOND_LLSC) && defined(CONFIG_SMP)
|
||||
#define __WEAK_LLSC_MB " sync \n"
|
||||
#define smp_llsc_mb() __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")
|
||||
#define __LLSC_CLOBBER
|
||||
# define __WEAK_LLSC_MB sync
|
||||
# define smp_llsc_mb() \
|
||||
__asm__ __volatile__(__stringify(__WEAK_LLSC_MB) : : :"memory")
|
||||
# define __LLSC_CLOBBER
|
||||
#else
|
||||
#define __WEAK_LLSC_MB " \n"
|
||||
#define smp_llsc_mb() do { } while (0)
|
||||
#define __LLSC_CLOBBER "memory"
|
||||
# define __WEAK_LLSC_MB
|
||||
# define smp_llsc_mb() do { } while (0)
|
||||
# define __LLSC_CLOBBER "memory"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||
|
@ -241,52 +119,22 @@
|
|||
#define nudge_writes() mb()
|
||||
#endif
|
||||
|
||||
#define __smp_mb__before_atomic() __smp_mb__before_llsc()
|
||||
#define __smp_mb__after_atomic() smp_llsc_mb()
|
||||
|
||||
/*
|
||||
* Some Loongson 3 CPUs have a bug wherein execution of a memory access (load,
|
||||
* store or prefetch) in between an LL & SC can cause the SC instruction to
|
||||
* erroneously succeed, breaking atomicity. Whilst it's unusual to write code
|
||||
* containing such sequences, this bug bites harder than we might otherwise
|
||||
* expect due to reordering & speculation:
|
||||
*
|
||||
* 1) A memory access appearing prior to the LL in program order may actually
|
||||
* be executed after the LL - this is the reordering case.
|
||||
*
|
||||
* In order to avoid this we need to place a memory barrier (ie. a SYNC
|
||||
* instruction) prior to every LL instruction, in between it and any earlier
|
||||
* memory access instructions.
|
||||
*
|
||||
* This reordering case is fixed by 3A R2 CPUs, ie. 3A2000 models and later.
|
||||
*
|
||||
* 2) If a conditional branch exists between an LL & SC with a target outside
|
||||
* of the LL-SC loop, for example an exit upon value mismatch in cmpxchg()
|
||||
* or similar, then misprediction of the branch may allow speculative
|
||||
* execution of memory accesses from outside of the LL-SC loop.
|
||||
*
|
||||
* In order to avoid this we need a memory barrier (ie. a SYNC instruction)
|
||||
* at each affected branch target, for which we also use loongson_llsc_mb()
|
||||
* defined below.
|
||||
*
|
||||
* This case affects all current Loongson 3 CPUs.
|
||||
*
|
||||
* The above described cases cause an error in the cache coherence protocol;
|
||||
* such that the Invalidate of a competing LL-SC goes 'missing' and SC
|
||||
* erroneously observes its core still has Exclusive state and lets the SC
|
||||
* proceed.
|
||||
*
|
||||
* Therefore the error only occurs on SMP systems.
|
||||
* In the Loongson3 LL/SC workaround case, all of our LL/SC loops already have
|
||||
* a completion barrier immediately preceding the LL instruction. Therefore we
|
||||
* can skip emitting a barrier from __smp_mb__before_atomic().
|
||||
*/
|
||||
#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS /* Loongson-3's LLSC workaround */
|
||||
#define loongson_llsc_mb() __asm__ __volatile__("sync" : : :"memory")
|
||||
#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS
|
||||
# define __smp_mb__before_atomic()
|
||||
#else
|
||||
#define loongson_llsc_mb() do { } while (0)
|
||||
# define __smp_mb__before_atomic() __smp_mb__before_llsc()
|
||||
#endif
|
||||
|
||||
#define __smp_mb__after_atomic() smp_llsc_mb()
|
||||
|
||||
static inline void sync_ginv(void)
|
||||
{
|
||||
asm volatile("sync\t%0" :: "i"(STYPE_GINV));
|
||||
asm volatile(__SYNC(ginv, always));
|
||||
}
|
||||
|
||||
#include <asm-generic/barrier.h>
|
||||
|
|
|
@ -13,16 +13,55 @@
|
|||
#error only <linux/bitops.h> can be included directly
|
||||
#endif
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/byteorder.h> /* sigh ... */
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/isa-rev.h>
|
||||
#include <asm/llsc.h>
|
||||
#include <asm/sgidefs.h>
|
||||
#include <asm/war.h>
|
||||
|
||||
#define __bit_op(mem, insn, inputs...) do { \
|
||||
unsigned long temp; \
|
||||
\
|
||||
asm volatile( \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_LEVEL " \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " __LL "%0, %1 \n" \
|
||||
" " insn " \n" \
|
||||
" " __SC "%0, %1 \n" \
|
||||
" " __SC_BEQZ "%0, 1b \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r"(temp), "+" GCC_OFF_SMALL_ASM()(mem) \
|
||||
: inputs \
|
||||
: __LLSC_CLOBBER); \
|
||||
} while (0)
|
||||
|
||||
#define __test_bit_op(mem, ll_dst, insn, inputs...) ({ \
|
||||
unsigned long orig, temp; \
|
||||
\
|
||||
asm volatile( \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_LEVEL " \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " __LL ll_dst ", %2 \n" \
|
||||
" " insn " \n" \
|
||||
" " __SC "%1, %2 \n" \
|
||||
" " __SC_BEQZ "%1, 1b \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r"(orig), "=&r"(temp), \
|
||||
"+" GCC_OFF_SMALL_ASM()(mem) \
|
||||
: inputs \
|
||||
: __LLSC_CLOBBER); \
|
||||
\
|
||||
orig; \
|
||||
})
|
||||
|
||||
/*
|
||||
* These are the "slower" versions of the functions and are in bitops.c.
|
||||
* These functions call raw_local_irq_{save,restore}().
|
||||
|
@ -30,8 +69,6 @@
|
|||
void __mips_set_bit(unsigned long nr, volatile unsigned long *addr);
|
||||
void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr);
|
||||
void __mips_change_bit(unsigned long nr, volatile unsigned long *addr);
|
||||
int __mips_test_and_set_bit(unsigned long nr,
|
||||
volatile unsigned long *addr);
|
||||
int __mips_test_and_set_bit_lock(unsigned long nr,
|
||||
volatile unsigned long *addr);
|
||||
int __mips_test_and_clear_bit(unsigned long nr,
|
||||
|
@ -52,51 +89,20 @@ int __mips_test_and_change_bit(unsigned long nr,
|
|||
*/
|
||||
static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
int bit = nr & SZLONG_MASK;
|
||||
unsigned long temp;
|
||||
volatile unsigned long *m = &addr[BIT_WORD(nr)];
|
||||
int bit = nr % BITS_PER_LONG;
|
||||
|
||||
if (kernel_uses_llsc && R10000_LLSC_WAR) {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set arch=r4000 \n"
|
||||
"1: " __LL "%0, %1 # set_bit \n"
|
||||
" or %0, %2 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
" beqzl %0, 1b \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "=" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m)
|
||||
: __LLSC_CLOBBER);
|
||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" " __LL "%0, %1 # set_bit \n"
|
||||
" " __INS "%0, %3, %2, 1 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (bit), "r" (~0)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!temp));
|
||||
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
|
||||
} else if (kernel_uses_llsc) {
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __LL "%0, %1 # set_bit \n"
|
||||
" or %0, %2 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!temp));
|
||||
} else
|
||||
if (!kernel_uses_llsc) {
|
||||
__mips_set_bit(nr, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(bit) && (bit >= 16)) {
|
||||
__bit_op(*m, __INS "%0, %3, %2, 1", "i"(bit), "r"(~0));
|
||||
return;
|
||||
}
|
||||
|
||||
__bit_op(*m, "or\t%0, %2", "ir"(BIT(bit)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -111,51 +117,20 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
|
|||
*/
|
||||
static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
int bit = nr & SZLONG_MASK;
|
||||
unsigned long temp;
|
||||
volatile unsigned long *m = &addr[BIT_WORD(nr)];
|
||||
int bit = nr % BITS_PER_LONG;
|
||||
|
||||
if (kernel_uses_llsc && R10000_LLSC_WAR) {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set arch=r4000 \n"
|
||||
"1: " __LL "%0, %1 # clear_bit \n"
|
||||
" and %0, %2 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
" beqzl %0, 1b \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (~(1UL << bit))
|
||||
: __LLSC_CLOBBER);
|
||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" " __LL "%0, %1 # clear_bit \n"
|
||||
" " __INS "%0, $0, %2, 1 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!temp));
|
||||
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
|
||||
} else if (kernel_uses_llsc) {
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __LL "%0, %1 # clear_bit \n"
|
||||
" and %0, %2 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (~(1UL << bit))
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!temp));
|
||||
} else
|
||||
if (!kernel_uses_llsc) {
|
||||
__mips_clear_bit(nr, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(bit)) {
|
||||
__bit_op(*m, __INS "%0, $0, %2, 1", "i"(bit));
|
||||
return;
|
||||
}
|
||||
|
||||
__bit_op(*m, "and\t%0, %2", "ir"(~BIT(bit)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -183,101 +158,15 @@ static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *ad
|
|||
*/
|
||||
static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
|
||||
{
|
||||
int bit = nr & SZLONG_MASK;
|
||||
volatile unsigned long *m = &addr[BIT_WORD(nr)];
|
||||
int bit = nr % BITS_PER_LONG;
|
||||
|
||||
if (kernel_uses_llsc && R10000_LLSC_WAR) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set arch=r4000 \n"
|
||||
"1: " __LL "%0, %1 # change_bit \n"
|
||||
" xor %0, %2 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
" beqzl %0, 1b \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} else if (kernel_uses_llsc) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __LL "%0, %1 # change_bit \n"
|
||||
" xor %0, %2 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m)
|
||||
: "ir" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!temp));
|
||||
} else
|
||||
if (!kernel_uses_llsc) {
|
||||
__mips_change_bit(nr, addr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static inline int test_and_set_bit(unsigned long nr,
|
||||
volatile unsigned long *addr)
|
||||
{
|
||||
int bit = nr & SZLONG_MASK;
|
||||
unsigned long res;
|
||||
|
||||
smp_mb__before_llsc();
|
||||
|
||||
if (kernel_uses_llsc && R10000_LLSC_WAR) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set arch=r4000 \n"
|
||||
"1: " __LL "%0, %1 # test_and_set_bit \n"
|
||||
" or %2, %0, %3 \n"
|
||||
" " __SC "%2, %1 \n"
|
||||
" beqzl %2, 1b \n"
|
||||
" and %2, %0, %3 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} else if (kernel_uses_llsc) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __LL "%0, %1 # test_and_set_bit \n"
|
||||
" or %2, %0, %3 \n"
|
||||
" " __SC "%2, %1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!res));
|
||||
|
||||
res = temp & (1UL << bit);
|
||||
} else
|
||||
res = __mips_test_and_set_bit(nr, addr);
|
||||
|
||||
smp_llsc_mb();
|
||||
|
||||
return res != 0;
|
||||
__bit_op(*m, "xor\t%0, %2", "ir"(BIT(bit)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -291,51 +180,39 @@ static inline int test_and_set_bit(unsigned long nr,
|
|||
static inline int test_and_set_bit_lock(unsigned long nr,
|
||||
volatile unsigned long *addr)
|
||||
{
|
||||
int bit = nr & SZLONG_MASK;
|
||||
unsigned long res;
|
||||
volatile unsigned long *m = &addr[BIT_WORD(nr)];
|
||||
int bit = nr % BITS_PER_LONG;
|
||||
unsigned long res, orig;
|
||||
|
||||
if (kernel_uses_llsc && R10000_LLSC_WAR) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set arch=r4000 \n"
|
||||
"1: " __LL "%0, %1 # test_and_set_bit \n"
|
||||
" or %2, %0, %3 \n"
|
||||
" " __SC "%2, %1 \n"
|
||||
" beqzl %2, 1b \n"
|
||||
" and %2, %0, %3 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+m" (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} else if (kernel_uses_llsc) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __LL "%0, %1 # test_and_set_bit \n"
|
||||
" or %2, %0, %3 \n"
|
||||
" " __SC "%2, %1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!res));
|
||||
|
||||
res = temp & (1UL << bit);
|
||||
} else
|
||||
if (!kernel_uses_llsc) {
|
||||
res = __mips_test_and_set_bit_lock(nr, addr);
|
||||
} else {
|
||||
orig = __test_bit_op(*m, "%0",
|
||||
"or\t%1, %0, %3",
|
||||
"ir"(BIT(bit)));
|
||||
res = (orig & BIT(bit)) != 0;
|
||||
}
|
||||
|
||||
smp_llsc_mb();
|
||||
|
||||
return res != 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static inline int test_and_set_bit(unsigned long nr,
|
||||
volatile unsigned long *addr)
|
||||
{
|
||||
smp_mb__before_atomic();
|
||||
return test_and_set_bit_lock(nr, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
|
@ -347,71 +224,30 @@ static inline int test_and_set_bit_lock(unsigned long nr,
|
|||
static inline int test_and_clear_bit(unsigned long nr,
|
||||
volatile unsigned long *addr)
|
||||
{
|
||||
int bit = nr & SZLONG_MASK;
|
||||
unsigned long res;
|
||||
volatile unsigned long *m = &addr[BIT_WORD(nr)];
|
||||
int bit = nr % BITS_PER_LONG;
|
||||
unsigned long res, orig;
|
||||
|
||||
smp_mb__before_llsc();
|
||||
smp_mb__before_atomic();
|
||||
|
||||
if (kernel_uses_llsc && R10000_LLSC_WAR) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set arch=r4000 \n"
|
||||
"1: " __LL "%0, %1 # test_and_clear_bit \n"
|
||||
" or %2, %0, %3 \n"
|
||||
" xor %2, %3 \n"
|
||||
" " __SC "%2, %1 \n"
|
||||
" beqzl %2, 1b \n"
|
||||
" and %2, %0, %3 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
|
||||
} else if (kernel_uses_llsc && __builtin_constant_p(nr)) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" " __LL "%0, %1 # test_and_clear_bit \n"
|
||||
" " __EXT "%2, %0, %3, 1 \n"
|
||||
" " __INS "%0, $0, %3, 1 \n"
|
||||
" " __SC "%0, %1 \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "ir" (bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!temp));
|
||||
#endif
|
||||
} else if (kernel_uses_llsc) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __LL "%0, %1 # test_and_clear_bit \n"
|
||||
" or %2, %0, %3 \n"
|
||||
" xor %2, %3 \n"
|
||||
" " __SC "%2, %1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!res));
|
||||
|
||||
res = temp & (1UL << bit);
|
||||
} else
|
||||
if (!kernel_uses_llsc) {
|
||||
res = __mips_test_and_clear_bit(nr, addr);
|
||||
} else if ((MIPS_ISA_REV >= 2) && __builtin_constant_p(nr)) {
|
||||
res = __test_bit_op(*m, "%1",
|
||||
__EXT "%0, %1, %3, 1;"
|
||||
__INS "%1, $0, %3, 1",
|
||||
"i"(bit));
|
||||
} else {
|
||||
orig = __test_bit_op(*m, "%0",
|
||||
"or\t%1, %0, %3;"
|
||||
"xor\t%1, %1, %3",
|
||||
"ir"(BIT(bit)));
|
||||
res = (orig & BIT(bit)) != 0;
|
||||
}
|
||||
|
||||
smp_llsc_mb();
|
||||
|
||||
return res != 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -425,54 +261,29 @@ static inline int test_and_clear_bit(unsigned long nr,
|
|||
static inline int test_and_change_bit(unsigned long nr,
|
||||
volatile unsigned long *addr)
|
||||
{
|
||||
int bit = nr & SZLONG_MASK;
|
||||
unsigned long res;
|
||||
volatile unsigned long *m = &addr[BIT_WORD(nr)];
|
||||
int bit = nr % BITS_PER_LONG;
|
||||
unsigned long res, orig;
|
||||
|
||||
smp_mb__before_llsc();
|
||||
smp_mb__before_atomic();
|
||||
|
||||
if (kernel_uses_llsc && R10000_LLSC_WAR) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set arch=r4000 \n"
|
||||
"1: " __LL "%0, %1 # test_and_change_bit \n"
|
||||
" xor %2, %0, %3 \n"
|
||||
" " __SC "%2, %1 \n"
|
||||
" beqzl %2, 1b \n"
|
||||
" and %2, %0, %3 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} else if (kernel_uses_llsc) {
|
||||
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
|
||||
unsigned long temp;
|
||||
|
||||
loongson_llsc_mb();
|
||||
do {
|
||||
__asm__ __volatile__(
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __LL "%0, %1 # test_and_change_bit \n"
|
||||
" xor %2, %0, %3 \n"
|
||||
" " __SC "\t%2, %1 \n"
|
||||
" .set pop \n"
|
||||
: "=&r" (temp), "+" GCC_OFF_SMALL_ASM() (*m), "=&r" (res)
|
||||
: "r" (1UL << bit)
|
||||
: __LLSC_CLOBBER);
|
||||
} while (unlikely(!res));
|
||||
|
||||
res = temp & (1UL << bit);
|
||||
} else
|
||||
if (!kernel_uses_llsc) {
|
||||
res = __mips_test_and_change_bit(nr, addr);
|
||||
} else {
|
||||
orig = __test_bit_op(*m, "%0",
|
||||
"xor\t%1, %0, %3",
|
||||
"ir"(BIT(bit)));
|
||||
res = (orig & BIT(bit)) != 0;
|
||||
}
|
||||
|
||||
smp_llsc_mb();
|
||||
|
||||
return res != 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef __bit_op
|
||||
#undef __test_bit_op
|
||||
|
||||
#include <asm-generic/bitops/non-atomic.h>
|
||||
|
||||
/*
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
/*
|
||||
* Valid machtype for Loongson family
|
||||
*/
|
||||
enum loongson_machine_type {
|
||||
enum loongson2ef_machine_type {
|
||||
MACH_LOONGSON_UNKNOWN,
|
||||
MACH_LEMOTE_FL2E,
|
||||
MACH_LEMOTE_FL2F,
|
||||
|
@ -70,7 +70,6 @@ enum loongson_machine_type {
|
|||
MACH_DEXXON_GDIUM2F10,
|
||||
MACH_LEMOTE_NAS,
|
||||
MACH_LEMOTE_LL2F,
|
||||
MACH_LOONGSON_GENERIC,
|
||||
MACH_LOONGSON_END
|
||||
};
|
||||
|
||||
|
@ -99,6 +98,7 @@ extern void detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_ad
|
|||
|
||||
extern void prom_init(void);
|
||||
extern void prom_free_prom_memory(void);
|
||||
extern void prom_cleanup(void);
|
||||
|
||||
extern void free_init_pages(const char *what,
|
||||
unsigned long begin, unsigned long end);
|
||||
|
|
|
@ -26,9 +26,8 @@ extern void check_bugs64(void);
|
|||
|
||||
static inline void check_bugs_early(void)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
check_bugs64_early();
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_CPU_R4X00_BUGS64))
|
||||
check_bugs64_early();
|
||||
}
|
||||
|
||||
static inline void check_bugs(void)
|
||||
|
@ -37,19 +36,18 @@ static inline void check_bugs(void)
|
|||
|
||||
cpu_data[cpu].udelay_val = loops_per_jiffy;
|
||||
check_bugs32();
|
||||
#ifdef CONFIG_64BIT
|
||||
check_bugs64();
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_CPU_R4X00_BUGS64))
|
||||
check_bugs64();
|
||||
}
|
||||
|
||||
static inline int r4k_daddiu_bug(void)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
if (!IS_ENABLED(CONFIG_CPU_R4X00_BUGS64))
|
||||
return 0;
|
||||
|
||||
WARN_ON(daddiu_bug < 0);
|
||||
return daddiu_bug != 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ASM_BUGS_H */
|
||||
|
|
|
@ -11,19 +11,10 @@
|
|||
#include <linux/bug.h>
|
||||
#include <linux/irqflags.h>
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/llsc.h>
|
||||
#include <asm/sync.h>
|
||||
#include <asm/war.h>
|
||||
|
||||
/*
|
||||
* Using a branch-likely instruction to check the result of an sc instruction
|
||||
* works around a bug present in R10000 CPUs prior to revision 3.0 that could
|
||||
* cause ll-sc sequences to execute non-atomically.
|
||||
*/
|
||||
#if R10000_LLSC_WAR
|
||||
# define __scbeqz "beqzl"
|
||||
#else
|
||||
# define __scbeqz "beqz"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These functions doesn't exist, so if they are called you'll either:
|
||||
*
|
||||
|
@ -46,18 +37,18 @@ extern unsigned long __xchg_called_with_bad_pointer(void)
|
|||
__typeof(*(m)) __ret; \
|
||||
\
|
||||
if (kernel_uses_llsc) { \
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noat \n" \
|
||||
" .set push \n" \
|
||||
" .set " MIPS_ISA_ARCH_LEVEL " \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " ld " %0, %2 # __xchg_asm \n" \
|
||||
" .set pop \n" \
|
||||
" move $1, %z3 \n" \
|
||||
" .set " MIPS_ISA_ARCH_LEVEL " \n" \
|
||||
" " st " $1, %1 \n" \
|
||||
"\t" __scbeqz " $1, 1b \n" \
|
||||
"\t" __SC_BEQZ "$1, 1b \n" \
|
||||
" .set pop \n" \
|
||||
: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m) \
|
||||
: GCC_OFF_SMALL_ASM() (*m), "Jr" (val) \
|
||||
|
@ -103,7 +94,13 @@ unsigned long __xchg(volatile void *ptr, unsigned long x, int size)
|
|||
({ \
|
||||
__typeof__(*(ptr)) __res; \
|
||||
\
|
||||
smp_mb__before_llsc(); \
|
||||
/* \
|
||||
* In the Loongson3 workaround case __xchg_asm() already \
|
||||
* contains a completion barrier prior to the LL, so we don't \
|
||||
* need to emit an extra one here. \
|
||||
*/ \
|
||||
if (!__SYNC_loongson3_war) \
|
||||
smp_mb__before_llsc(); \
|
||||
\
|
||||
__res = (__typeof__(*(ptr))) \
|
||||
__xchg((ptr), (unsigned long)(x), sizeof(*(ptr))); \
|
||||
|
@ -118,25 +115,24 @@ unsigned long __xchg(volatile void *ptr, unsigned long x, int size)
|
|||
__typeof(*(m)) __ret; \
|
||||
\
|
||||
if (kernel_uses_llsc) { \
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noat \n" \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: " ld " %0, %2 # __cmpxchg_asm \n" \
|
||||
" bne %0, %z3, 2f \n" \
|
||||
" .set pop \n" \
|
||||
" move $1, %z4 \n" \
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||
" " st " $1, %1 \n" \
|
||||
"\t" __scbeqz " $1, 1b \n" \
|
||||
"\t" __SC_BEQZ "$1, 1b \n" \
|
||||
" .set pop \n" \
|
||||
"2: \n" \
|
||||
"2: " __SYNC(full, loongson3_war) " \n" \
|
||||
: "=&r" (__ret), "=" GCC_OFF_SMALL_ASM() (*m) \
|
||||
: GCC_OFF_SMALL_ASM() (*m), "Jr" (old), "Jr" (new) \
|
||||
: __LLSC_CLOBBER); \
|
||||
loongson_llsc_mb(); \
|
||||
} else { \
|
||||
unsigned long __flags; \
|
||||
\
|
||||
|
@ -190,9 +186,23 @@ unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
|
|||
({ \
|
||||
__typeof__(*(ptr)) __res; \
|
||||
\
|
||||
smp_mb__before_llsc(); \
|
||||
/* \
|
||||
* In the Loongson3 workaround case __cmpxchg_asm() already \
|
||||
* contains a completion barrier prior to the LL, so we don't \
|
||||
* need to emit an extra one here. \
|
||||
*/ \
|
||||
if (!__SYNC_loongson3_war) \
|
||||
smp_mb__before_llsc(); \
|
||||
\
|
||||
__res = cmpxchg_local((ptr), (old), (new)); \
|
||||
smp_llsc_mb(); \
|
||||
\
|
||||
/* \
|
||||
* In the Loongson3 workaround case __cmpxchg_asm() already \
|
||||
* contains a completion barrier after the SC, so we don't \
|
||||
* need to emit an extra one here. \
|
||||
*/ \
|
||||
if (!__SYNC_loongson3_war) \
|
||||
smp_llsc_mb(); \
|
||||
\
|
||||
__res; \
|
||||
})
|
||||
|
@ -233,11 +243,11 @@ static inline unsigned long __cmpxchg64(volatile void *ptr,
|
|||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
loongson_llsc_mb();
|
||||
asm volatile(
|
||||
" .set push \n"
|
||||
" .set " MIPS_ISA_ARCH_LEVEL " \n"
|
||||
/* Load 64 bits from ptr */
|
||||
" " __SYNC(full, loongson3_war) " \n"
|
||||
"1: lld %L0, %3 # __cmpxchg64 \n"
|
||||
/*
|
||||
* Split the 64 bit value we loaded into the 2 registers that hold the
|
||||
|
@ -269,9 +279,9 @@ static inline unsigned long __cmpxchg64(volatile void *ptr,
|
|||
/* Attempt to store new at ptr */
|
||||
" scd %L1, %2 \n"
|
||||
/* If we failed, loop! */
|
||||
"\t" __scbeqz " %L1, 1b \n"
|
||||
"\t" __SC_BEQZ "%L1, 1b \n"
|
||||
" .set pop \n"
|
||||
"2: \n"
|
||||
"2: " __SYNC(full, loongson3_war) " \n"
|
||||
: "=&r"(ret),
|
||||
"=&r"(tmp),
|
||||
"=" GCC_OFF_SMALL_ASM() (*(unsigned long long *)ptr)
|
||||
|
@ -279,7 +289,6 @@ static inline unsigned long __cmpxchg64(volatile void *ptr,
|
|||
"r" (old),
|
||||
"r" (new)
|
||||
: "memory");
|
||||
loongson_llsc_mb();
|
||||
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
|
@ -312,6 +321,4 @@ static inline unsigned long __cmpxchg64(volatile void *ptr,
|
|||
# endif /* !CONFIG_SMP */
|
||||
#endif /* !CONFIG_64BIT */
|
||||
|
||||
#undef __scbeqz
|
||||
|
||||
#endif /* __ASM_CMPXCHG_H */
|
||||
|
|
|
@ -33,7 +33,7 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *);
|
|||
#define cop2_present 1
|
||||
#define cop2_lazy_restore 0
|
||||
|
||||
#elif defined(CONFIG_CPU_LOONGSON3)
|
||||
#elif defined(CONFIG_CPU_LOONGSON64)
|
||||
|
||||
#define cop2_present 1
|
||||
#define cop2_lazy_restore 1
|
||||
|
|
|
@ -15,18 +15,17 @@
|
|||
static inline int __pure __get_cpu_type(const int cpu_type)
|
||||
{
|
||||
switch (cpu_type) {
|
||||
#if defined(CONFIG_SYS_HAS_CPU_LOONGSON2E) || \
|
||||
defined(CONFIG_SYS_HAS_CPU_LOONGSON2F)
|
||||
case CPU_LOONGSON2:
|
||||
#if defined(CONFIG_SYS_HAS_CPU_LOONGSON2EF)
|
||||
case CPU_LOONGSON2EF:
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_HAS_CPU_LOONGSON3
|
||||
case CPU_LOONGSON3:
|
||||
#ifdef CONFIG_SYS_HAS_CPU_LOONGSON64
|
||||
case CPU_LOONGSON64:
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SYS_HAS_CPU_LOONGSON1B) || \
|
||||
defined(CONFIG_SYS_HAS_CPU_LOONGSON1C)
|
||||
case CPU_LOONGSON1:
|
||||
case CPU_LOONGSON32:
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R1
|
||||
|
|
|
@ -91,7 +91,9 @@
|
|||
#define PRID_IMP_LOONGSON_32 0x4200 /* Loongson-1 */
|
||||
#define PRID_IMP_R5432 0x5400
|
||||
#define PRID_IMP_R5500 0x5500
|
||||
#define PRID_IMP_LOONGSON_64 0x6300 /* Loongson-2/3 */
|
||||
#define PRID_IMP_LOONGSON_64R 0x6100 /* Reduced Loongson-2 */
|
||||
#define PRID_IMP_LOONGSON_64C 0x6300 /* Classic Loongson-2 and Loongson-3 */
|
||||
#define PRID_IMP_LOONGSON_64G 0xc000 /* Generic Loongson-2 and Loongson-3 */
|
||||
|
||||
#define PRID_IMP_UNKNOWN 0xff00
|
||||
|
||||
|
@ -310,15 +312,15 @@ enum cpu_type_enum {
|
|||
*/
|
||||
CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
|
||||
CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
|
||||
CPU_BMIPS4380, CPU_BMIPS5000, CPU_XBURST, CPU_LOONGSON1, CPU_M14KC,
|
||||
CPU_BMIPS4380, CPU_BMIPS5000, CPU_XBURST, CPU_LOONGSON32, CPU_M14KC,
|
||||
CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K,
|
||||
CPU_M5150, CPU_I6400, CPU_P6600, CPU_M6250,
|
||||
|
||||
/*
|
||||
* MIPS64 class processors
|
||||
*/
|
||||
CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
|
||||
CPU_LOONGSON3, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
|
||||
CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2EF,
|
||||
CPU_LOONGSON64, CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS,
|
||||
CPU_CAVIUM_OCTEON2, CPU_CAVIUM_OCTEON3, CPU_XLR, CPU_XLP, CPU_I6500,
|
||||
|
||||
CPU_QEMU_GENERIC,
|
||||
|
|
|
@ -70,7 +70,7 @@ enum fixed_addresses {
|
|||
#include <asm-generic/fixmap.h>
|
||||
|
||||
#define kmap_get_fixmap_pte(vaddr) \
|
||||
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))
|
||||
pte_offset_kernel(pmd_offset(pud_offset(p4d_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr)), (vaddr))
|
||||
|
||||
/*
|
||||
* Called from pgtable_init()
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <asm/barrier.h>
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/sync.h>
|
||||
#include <asm/war.h>
|
||||
|
||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
|
||||
|
@ -32,7 +33,7 @@
|
|||
" .set arch=r4000 \n" \
|
||||
"2: sc $1, %2 \n" \
|
||||
" beqzl $1, 1b \n" \
|
||||
__WEAK_LLSC_MB \
|
||||
__stringify(__WEAK_LLSC_MB) " \n" \
|
||||
"3: \n" \
|
||||
" .insn \n" \
|
||||
" .set pop \n" \
|
||||
|
@ -50,19 +51,19 @@
|
|||
"i" (-EFAULT) \
|
||||
: "memory"); \
|
||||
} else if (cpu_has_llsc) { \
|
||||
loongson_llsc_mb(); \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noat \n" \
|
||||
" .set push \n" \
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||
" " __SYNC(full, loongson3_war) " \n" \
|
||||
"1: "user_ll("%1", "%4")" # __futex_atomic_op\n" \
|
||||
" .set pop \n" \
|
||||
" " insn " \n" \
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||
"2: "user_sc("$1", "%2")" \n" \
|
||||
" beqz $1, 1b \n" \
|
||||
__WEAK_LLSC_MB \
|
||||
__stringify(__WEAK_LLSC_MB) " \n" \
|
||||
"3: \n" \
|
||||
" .insn \n" \
|
||||
" .set pop \n" \
|
||||
|
@ -147,7 +148,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|||
" .set arch=r4000 \n"
|
||||
"2: sc $1, %2 \n"
|
||||
" beqzl $1, 1b \n"
|
||||
__WEAK_LLSC_MB
|
||||
__stringify(__WEAK_LLSC_MB) " \n"
|
||||
"3: \n"
|
||||
" .insn \n"
|
||||
" .set pop \n"
|
||||
|
@ -164,13 +165,13 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|||
"i" (-EFAULT)
|
||||
: "memory");
|
||||
} else if (cpu_has_llsc) {
|
||||
loongson_llsc_mb();
|
||||
__asm__ __volatile__(
|
||||
"# futex_atomic_cmpxchg_inatomic \n"
|
||||
" .set push \n"
|
||||
" .set noat \n"
|
||||
" .set push \n"
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
" " __SYNC(full, loongson3_war) " \n"
|
||||
"1: "user_ll("%1", "%3")" \n"
|
||||
" bne %1, %z4, 3f \n"
|
||||
" .set pop \n"
|
||||
|
@ -178,8 +179,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
"2: "user_sc("$1", "%2")" \n"
|
||||
" beqz $1, 1b \n"
|
||||
__WEAK_LLSC_MB
|
||||
"3: \n"
|
||||
"3: " __SYNC_ELSE(full, loongson3_war, __WEAK_LLSC_MB) "\n"
|
||||
" .insn \n"
|
||||
" .set pop \n"
|
||||
" .section .fixup,\"ax\" \n"
|
||||
|
@ -194,7 +194,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|||
: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
|
||||
"i" (-EFAULT)
|
||||
: "memory");
|
||||
loongson_llsc_mb();
|
||||
} else
|
||||
return -ENOSYS;
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ do { \
|
|||
} while (0)
|
||||
|
||||
#elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
|
||||
defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_LOONGSON3_ENHANCEMENT) || \
|
||||
defined(CONFIG_CPU_LOONGSON2EF) || defined(CONFIG_LOONGSON3_ENHANCEMENT) || \
|
||||
defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)
|
||||
|
||||
/*
|
||||
|
|
|
@ -306,7 +306,7 @@ static inline void iounmap(const volatile void __iomem *addr)
|
|||
#undef __IS_KSEG1
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_CPU_LOONGSON3)
|
||||
#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_CPU_LOONGSON64)
|
||||
#define war_io_reorder_wmb() wmb()
|
||||
#else
|
||||
#define war_io_reorder_wmb() barrier()
|
||||
|
|
|
@ -41,7 +41,7 @@ static inline unsigned long arch_local_irq_save(void)
|
|||
" .set push \n"
|
||||
" .set reorder \n"
|
||||
" .set noat \n"
|
||||
#if defined(CONFIG_CPU_LOONGSON3) || defined (CONFIG_CPU_LOONGSON1)
|
||||
#if defined(CONFIG_CPU_LOONGSON64) || defined(CONFIG_CPU_LOONGSON32)
|
||||
" mfc0 %[flags], $12 \n"
|
||||
" di \n"
|
||||
#else
|
||||
|
|
|
@ -9,20 +9,31 @@
|
|||
#ifndef __ASM_LLSC_H
|
||||
#define __ASM_LLSC_H
|
||||
|
||||
#include <asm/isa-rev.h>
|
||||
|
||||
#if _MIPS_SZLONG == 32
|
||||
#define SZLONG_LOG 5
|
||||
#define SZLONG_MASK 31UL
|
||||
#define __LL "ll "
|
||||
#define __SC "sc "
|
||||
#define __INS "ins "
|
||||
#define __EXT "ext "
|
||||
#elif _MIPS_SZLONG == 64
|
||||
#define SZLONG_LOG 6
|
||||
#define SZLONG_MASK 63UL
|
||||
#define __LL "lld "
|
||||
#define __SC "scd "
|
||||
#define __INS "dins "
|
||||
#define __EXT "dext "
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Using a branch-likely instruction to check the result of an sc instruction
|
||||
* works around a bug present in R10000 CPUs prior to revision 3.0 that could
|
||||
* cause ll-sc sequences to execute non-atomically.
|
||||
*/
|
||||
#if R10000_LLSC_WAR
|
||||
# define __SC_BEQZ "beqzl "
|
||||
#elif MIPS_ISA_REV >= 6
|
||||
# define __SC_BEQZ "beqzc "
|
||||
#else
|
||||
# define __SC_BEQZ "beqz "
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_LLSC_H */
|
||||
|
|
|
@ -10,17 +10,7 @@
|
|||
#ifndef _ASM_MACH_IP22_SPACES_H
|
||||
#define _ASM_MACH_IP22_SPACES_H
|
||||
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
#define PAGE_OFFSET 0xffffffff80000000UL
|
||||
|
||||
#define CAC_BASE 0xffffffff80000000
|
||||
#define IO_BASE 0xffffffffa0000000
|
||||
#define UNCAC_BASE 0xffffffffa0000000
|
||||
#define MAP_BASE 0xc000000000000000
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
#define PHYS_OFFSET _AC(0x08000000, UL)
|
||||
|
||||
#include <asm/mach-generic/spaces.h>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <asm/sn/arch.h>
|
||||
#include <asm/sn/hub.h>
|
||||
|
||||
#define pa_to_nid(addr) NASID_TO_COMPACT_NODEID(NASID_GET(addr))
|
||||
#define pa_to_nid(addr) NASID_GET(addr)
|
||||
|
||||
struct hub_data {
|
||||
kern_vars_t kern_vars;
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
#include <asm/mmzone.h>
|
||||
|
||||
struct cpuinfo_ip27 {
|
||||
cnodeid_t p_nodeid; /* my node ID in compact-id-space */
|
||||
nasid_t p_nasid; /* my node ID in numa-as-id-space */
|
||||
unsigned char p_slice; /* Physical position on node board */
|
||||
};
|
||||
|
||||
extern struct cpuinfo_ip27 sn_cpu_info[NR_CPUS];
|
||||
|
||||
#define cpu_to_node(cpu) (sn_cpu_info[(cpu)].p_nodeid)
|
||||
#define cpu_to_node(cpu) (cputonasid(cpu))
|
||||
#define cpumask_of_node(node) ((node) == -1 ? \
|
||||
cpu_all_mask : \
|
||||
&hub_data(node)->h_cpus)
|
||||
|
@ -23,7 +22,7 @@ extern int pcibus_to_node(struct pci_bus *);
|
|||
|
||||
#define cpumask_of_pcibus(bus) (cpumask_of_node(pcibus_to_node(bus)))
|
||||
|
||||
extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
|
||||
extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
|
||||
|
||||
#define node_distance(from, to) (__node_distances[(from)][(to)])
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* IP30/Octane cpu-features overrides.
|
||||
*
|
||||
* Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org>
|
||||
* 2004-2007 Stanislaw Skowronek <skylark@unaligned.org>
|
||||
* 2009 Johannes Dickgreber <tanzy@gmx.de>
|
||||
* 2015 Joshua Kinard <kumba@gentoo.org>
|
||||
*
|
||||
*/
|
||||
#ifndef __ASM_MACH_IP30_CPU_FEATURE_OVERRIDES_H
|
||||
#define __ASM_MACH_IP30_CPU_FEATURE_OVERRIDES_H
|
||||
|
||||
#include <asm/cpu.h>
|
||||
|
||||
/*
|
||||
* IP30 only supports R1[024]000 processors, all using the same config
|
||||
*/
|
||||
#define cpu_has_tlb 1
|
||||
#define cpu_has_tlbinv 0
|
||||
#define cpu_has_segments 0
|
||||
#define cpu_has_eva 0
|
||||
#define cpu_has_htw 0
|
||||
#define cpu_has_rixiex 0
|
||||
#define cpu_has_maar 0
|
||||
#define cpu_has_rw_llb 0
|
||||
#define cpu_has_3kex 0
|
||||
#define cpu_has_4kex 1
|
||||
#define cpu_has_3k_cache 0
|
||||
#define cpu_has_4k_cache 1
|
||||
#define cpu_has_6k_cache 0
|
||||
#define cpu_has_8k_cache 0
|
||||
#define cpu_has_tx39_cache 0
|
||||
#define cpu_has_fpu 1
|
||||
#define cpu_has_nofpuex 0
|
||||
#define cpu_has_32fpr 1
|
||||
#define cpu_has_counter 1
|
||||
#define cpu_has_watch 1
|
||||
#define cpu_has_64bits 1
|
||||
#define cpu_has_divec 0
|
||||
#define cpu_has_vce 0
|
||||
#define cpu_has_cache_cdex_p 0
|
||||
#define cpu_has_cache_cdex_s 0
|
||||
#define cpu_has_prefetch 1
|
||||
#define cpu_has_mcheck 0
|
||||
#define cpu_has_ejtag 0
|
||||
#define cpu_has_llsc 1
|
||||
#define cpu_has_mips16 0
|
||||
#define cpu_has_mdmx 0
|
||||
#define cpu_has_mips3d 0
|
||||
#define cpu_has_smartmips 0
|
||||
#define cpu_has_rixi 0
|
||||
#define cpu_has_xpa 0
|
||||
#define cpu_has_vtag_icache 0
|
||||
#define cpu_has_dc_aliases 0
|
||||
#define cpu_has_ic_fills_f_dc 0
|
||||
|
||||
#define cpu_icache_snoops_remote_store 1
|
||||
|
||||
#define cpu_has_mips32r1 0
|
||||
#define cpu_has_mips32r2 0
|
||||
#define cpu_has_mips64r1 0
|
||||
#define cpu_has_mips64r2 0
|
||||
#define cpu_has_mips32r6 0
|
||||
#define cpu_has_mips64r6 0
|
||||
|
||||
#define cpu_has_dsp 0
|
||||
#define cpu_has_dsp2 0
|
||||
#define cpu_has_mipsmt 0
|
||||
#define cpu_has_userlocal 0
|
||||
#define cpu_has_inclusive_pcaches 1
|
||||
#define cpu_hwrena_impl_bits 0
|
||||
#define cpu_has_perf_cntr_intr_bit 0
|
||||
#define cpu_has_vz 0
|
||||
#define cpu_has_fre 0
|
||||
#define cpu_has_cdmm 0
|
||||
|
||||
#define cpu_dcache_line_size() 32
|
||||
#define cpu_icache_line_size() 64
|
||||
#define cpu_scache_line_size() 128
|
||||
|
||||
#endif /* __ASM_MACH_IP30_CPU_FEATURE_OVERRIDES_H */
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* HEART IRQ defines
|
||||
*
|
||||
* Copyright (C) 2009 Johannes Dickgreber <tanzy@gmx.de>
|
||||
* 2014-2016 Joshua Kinard <kumba@gentoo.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_IP30_IRQ_H
|
||||
#define __ASM_MACH_IP30_IRQ_H
|
||||
|
||||
/*
|
||||
* HEART has 64 hardware interrupts, but use 128 to leave room for a few
|
||||
* software interrupts as well (such as the CPU timer interrupt.
|
||||
*/
|
||||
#define NR_IRQS 128
|
||||
|
||||
extern void __init ip30_install_ipi(void);
|
||||
|
||||
/*
|
||||
* HEART has 64 interrupt vectors available to it, subdivided into five
|
||||
* priority levels. They are numbered 0 to 63.
|
||||
*/
|
||||
#define HEART_NUM_IRQS 64
|
||||
|
||||
/*
|
||||
* These are the five interrupt priority levels and their corresponding
|
||||
* CPU IPx interrupt pins.
|
||||
*
|
||||
* Level 4 - Error Interrupts.
|
||||
* Level 3 - HEART timer interrupt.
|
||||
* Level 2 - CPU IPI, CPU debug, power putton, general device interrupts.
|
||||
* Level 1 - General device interrupts.
|
||||
* Level 0 - General device GFX flow control interrupts.
|
||||
*/
|
||||
#define HEART_L4_INT_MASK 0xfff8000000000000ULL /* IP6 */
|
||||
#define HEART_L3_INT_MASK 0x0004000000000000ULL /* IP5 */
|
||||
#define HEART_L2_INT_MASK 0x0003ffff00000000ULL /* IP4 */
|
||||
#define HEART_L1_INT_MASK 0x00000000ffff0000ULL /* IP3 */
|
||||
#define HEART_L0_INT_MASK 0x000000000000ffffULL /* IP2 */
|
||||
|
||||
/* HEART L0 Interrupts (Low Priority) */
|
||||
#define HEART_L0_INT_GENERIC 0
|
||||
#define HEART_L0_INT_FLOW_CTRL_HWTR_0 1
|
||||
#define HEART_L0_INT_FLOW_CTRL_HWTR_1 2
|
||||
|
||||
/* HEART L2 Interrupts (High Priority) */
|
||||
#define HEART_L2_INT_RESCHED_CPU_0 46
|
||||
#define HEART_L2_INT_RESCHED_CPU_1 47
|
||||
#define HEART_L2_INT_CALL_CPU_0 48
|
||||
#define HEART_L2_INT_CALL_CPU_1 49
|
||||
|
||||
/* HEART L3 Interrupts (Compare/Counter Timer) */
|
||||
#define HEART_L3_INT_TIMER 50
|
||||
|
||||
/* HEART L4 Interrupts (Errors) */
|
||||
#define HEART_L4_INT_XWID_ERR_9 51
|
||||
#define HEART_L4_INT_XWID_ERR_A 52
|
||||
#define HEART_L4_INT_XWID_ERR_B 53
|
||||
#define HEART_L4_INT_XWID_ERR_C 54
|
||||
#define HEART_L4_INT_XWID_ERR_D 55
|
||||
#define HEART_L4_INT_XWID_ERR_E 56
|
||||
#define HEART_L4_INT_XWID_ERR_F 57
|
||||
#define HEART_L4_INT_XWID_ERR_XBOW 58
|
||||
#define HEART_L4_INT_CPU_BUS_ERR_0 59
|
||||
#define HEART_L4_INT_CPU_BUS_ERR_1 60
|
||||
#define HEART_L4_INT_CPU_BUS_ERR_2 61
|
||||
#define HEART_L4_INT_CPU_BUS_ERR_3 62
|
||||
#define HEART_L4_INT_HEART_EXCP 63
|
||||
|
||||
/*
|
||||
* Power Switch is wired via BaseIO BRIDGE slot #6.
|
||||
*
|
||||
* ACFail is wired via BaseIO BRIDGE slot #7.
|
||||
*/
|
||||
#define IP30_POWER_IRQ HEART_L2_INT_POWER_BTN
|
||||
|
||||
#include_next <irq.h>
|
||||
|
||||
#define IP30_HEART_L0_IRQ (MIPS_CPU_IRQ_BASE + 2)
|
||||
#define IP30_HEART_L1_IRQ (MIPS_CPU_IRQ_BASE + 3)
|
||||
#define IP30_HEART_L2_IRQ (MIPS_CPU_IRQ_BASE + 4)
|
||||
#define IP30_HEART_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 5)
|
||||
#define IP30_HEART_ERR_IRQ (MIPS_CPU_IRQ_BASE + 6)
|
||||
|
||||
#endif /* __ASM_MACH_IP30_IRQ_H */
|
|
@ -0,0 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __ASM_MACH_IP30_KERNEL_ENTRY_H
|
||||
#define __ASM_MACH_IP30_KERNEL_ENTRY_H
|
||||
|
||||
.macro kernel_entry_setup
|
||||
.endm
|
||||
|
||||
.macro smp_slave_setup
|
||||
move gp, a0
|
||||
.endm
|
||||
|
||||
#endif /* __ASM_MACH_IP30_KERNEL_ENTRY_H */
|
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2003, 2004 Ralf Baechle
|
||||
*/
|
||||
#ifndef __ASM_MACH_IP30_MANGLE_PORT_H
|
||||
#define __ASM_MACH_IP30_MANGLE_PORT_H
|
||||
|
||||
#define __swizzle_addr_b(port) ((port)^3)
|
||||
#define __swizzle_addr_w(port) ((port)^2)
|
||||
#define __swizzle_addr_l(port) (port)
|
||||
#define __swizzle_addr_q(port) (port)
|
||||
|
||||
#define ioswabb(a, x) (x)
|
||||
#define __mem_ioswabb(a, x) (x)
|
||||
#define ioswabw(a, x) (x)
|
||||
#define __mem_ioswabw(a, x) cpu_to_le16(x)
|
||||
#define ioswabl(a, x) (x)
|
||||
#define __mem_ioswabl(a, x) cpu_to_le32(x)
|
||||
#define ioswabq(a, x) (x)
|
||||
#define __mem_ioswabq(a, x) cpu_to_le64(x)
|
||||
|
||||
#endif /* __ASM_MACH_IP30_MANGLE_PORT_H */
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2016 Joshua Kinard <kumba@gentoo.org>
|
||||
*
|
||||
*/
|
||||
#ifndef _ASM_MACH_IP30_SPACES_H
|
||||
#define _ASM_MACH_IP30_SPACES_H
|
||||
|
||||
/*
|
||||
* Memory in IP30/Octane is offset 512MB in the physical address space.
|
||||
*/
|
||||
#define PHYS_OFFSET _AC(0x20000000, UL)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define CAC_BASE _AC(0xA800000000000000, UL)
|
||||
#endif
|
||||
|
||||
#include <asm/mach-generic/spaces.h>
|
||||
|
||||
#endif /* _ASM_MACH_IP30_SPACES_H */
|
|
@ -0,0 +1,26 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
|
||||
*/
|
||||
#ifndef __ASM_MIPS_MACH_IP30_WAR_H
|
||||
#define __ASM_MIPS_MACH_IP30_WAR_H
|
||||
|
||||
#define R4600_V1_INDEX_ICACHEOP_WAR 0
|
||||
#define R4600_V1_HIT_CACHEOP_WAR 0
|
||||
#define R4600_V2_HIT_CACHEOP_WAR 0
|
||||
#define MIPS_CACHE_SYNC_WAR 0
|
||||
#define BCM1250_M3_WAR 0
|
||||
#define SIBYTE_1956_WAR 0
|
||||
#define MIPS4K_ICACHE_REFILL_WAR 0
|
||||
#define MIPS34K_MISSED_ITLB_WAR 0
|
||||
#define R5432_CP0_INTERRUPT_WAR 0
|
||||
#define TX49XX_ICACHE_INDEX_INV_WAR 0
|
||||
#define ICACHE_REFILLS_WORKAROUND_WAR 0
|
||||
|
||||
#ifdef CONFIG_CPU_R10000
|
||||
#define R10000_LLSC_WAR 1
|
||||
#else
|
||||
#define R10000_LLSC_WAR 0
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_MIPS_MACH_IP30_WAR_H */
|
|
@ -0,0 +1,44 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2009 Wu Zhangjin <wuzhangjin@gmail.com>
|
||||
* Copyright (C) 2009 Philippe Vachon <philippe@cowpig.ca>
|
||||
* Copyright (C) 2009 Zhang Le <r0bertz@gentoo.org>
|
||||
*
|
||||
* reference: /proc/cpuinfo,
|
||||
* arch/mips/kernel/cpu-probe.c(cpu_probe_legacy),
|
||||
* arch/mips/kernel/proc.c(show_cpuinfo),
|
||||
* loongson2f user manual.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_LOONGSON2EF_CPU_FEATURE_OVERRIDES_H
|
||||
#define __ASM_MACH_LOONGSON2EF_CPU_FEATURE_OVERRIDES_H
|
||||
|
||||
#define cpu_has_32fpr 1
|
||||
#define cpu_has_3k_cache 0
|
||||
#define cpu_has_4k_cache 1
|
||||
#define cpu_has_4kex 1
|
||||
#define cpu_has_64bits 1
|
||||
#define cpu_has_cache_cdex_p 0
|
||||
#define cpu_has_cache_cdex_s 0
|
||||
#define cpu_has_counter 1
|
||||
#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
|
||||
#define cpu_has_divec 0
|
||||
#define cpu_has_ejtag 0
|
||||
#define cpu_has_inclusive_pcaches 1
|
||||
#define cpu_has_llsc 1
|
||||
#define cpu_has_mcheck 0
|
||||
#define cpu_has_mdmx 0
|
||||
#define cpu_has_mips16 0
|
||||
#define cpu_has_mips16e2 0
|
||||
#define cpu_has_mips3d 0
|
||||
#define cpu_has_mipsmt 0
|
||||
#define cpu_has_smartmips 0
|
||||
#define cpu_has_tlb 1
|
||||
#define cpu_has_tx39_cache 0
|
||||
#define cpu_has_vce 0
|
||||
#define cpu_has_veic 0
|
||||
#define cpu_has_vint 0
|
||||
#define cpu_has_vtag_icache 0
|
||||
#define cpu_has_watch 1
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */
|
|
@ -0,0 +1,326 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2009 Lemote, Inc.
|
||||
* Author: Wu Zhangjin <wuzhangjin@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_LOONGSON2EF_LOONGSON_H
|
||||
#define __ASM_MACH_LOONGSON2EF_LOONGSON_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
/* loongson internal northbridge initialization */
|
||||
extern void bonito_irq_init(void);
|
||||
|
||||
/* machine-specific reboot/halt operation */
|
||||
extern void mach_prepare_reboot(void);
|
||||
extern void mach_prepare_shutdown(void);
|
||||
|
||||
/* environment arguments from bootloader */
|
||||
extern u32 cpu_clock_freq;
|
||||
extern u32 memsize, highmemsize;
|
||||
|
||||
/* loongson-specific command line, env and memory initialization */
|
||||
extern void __init prom_init_memory(void);
|
||||
extern void __init prom_init_machtype(void);
|
||||
extern void __init prom_init_env(void);
|
||||
#ifdef CONFIG_LOONGSON_UART_BASE
|
||||
extern unsigned long _loongson_uart_base, loongson_uart_base;
|
||||
extern void prom_init_loongson_uart_base(void);
|
||||
#endif
|
||||
|
||||
static inline void prom_init_uart_base(void)
|
||||
{
|
||||
#ifdef CONFIG_LOONGSON_UART_BASE
|
||||
prom_init_loongson_uart_base();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* irq operation functions */
|
||||
extern void bonito_irqdispatch(void);
|
||||
extern void __init bonito_irq_init(void);
|
||||
extern void __init mach_init_irq(void);
|
||||
extern void mach_irq_dispatch(unsigned int pending);
|
||||
extern int mach_i8259_irq(void);
|
||||
|
||||
/* We need this in some places... */
|
||||
#define delay() ({ \
|
||||
int x; \
|
||||
for (x = 0; x < 100000; x++) \
|
||||
__asm__ __volatile__(""); \
|
||||
})
|
||||
|
||||
#define LOONGSON_REG(x) \
|
||||
(*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
|
||||
|
||||
#define LOONGSON_IRQ_BASE 32
|
||||
#define LOONGSON2_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
static inline void do_perfcnt_IRQ(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_OPROFILE)
|
||||
do_IRQ(LOONGSON2_PERFCNT_IRQ);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define LOONGSON_FLASH_BASE 0x1c000000
|
||||
#define LOONGSON_FLASH_SIZE 0x02000000 /* 32M */
|
||||
#define LOONGSON_FLASH_TOP (LOONGSON_FLASH_BASE+LOONGSON_FLASH_SIZE-1)
|
||||
|
||||
#define LOONGSON_LIO0_BASE 0x1e000000
|
||||
#define LOONGSON_LIO0_SIZE 0x01C00000 /* 28M */
|
||||
#define LOONGSON_LIO0_TOP (LOONGSON_LIO0_BASE+LOONGSON_LIO0_SIZE-1)
|
||||
|
||||
#define LOONGSON_BOOT_BASE 0x1fc00000
|
||||
#define LOONGSON_BOOT_SIZE 0x00100000 /* 1M */
|
||||
#define LOONGSON_BOOT_TOP (LOONGSON_BOOT_BASE+LOONGSON_BOOT_SIZE-1)
|
||||
#define LOONGSON_REG_BASE 0x1fe00000
|
||||
#define LOONGSON_REG_SIZE 0x00100000 /* 256Bytes + 256Bytes + ??? */
|
||||
#define LOONGSON_REG_TOP (LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
|
||||
|
||||
#define LOONGSON_LIO1_BASE 0x1ff00000
|
||||
#define LOONGSON_LIO1_SIZE 0x00100000 /* 1M */
|
||||
#define LOONGSON_LIO1_TOP (LOONGSON_LIO1_BASE+LOONGSON_LIO1_SIZE-1)
|
||||
|
||||
#define LOONGSON_PCILO0_BASE 0x10000000
|
||||
#define LOONGSON_PCILO1_BASE 0x14000000
|
||||
#define LOONGSON_PCILO2_BASE 0x18000000
|
||||
#define LOONGSON_PCILO_BASE LOONGSON_PCILO0_BASE
|
||||
#define LOONGSON_PCILO_SIZE 0x0c000000 /* 64M * 3 */
|
||||
#define LOONGSON_PCILO_TOP (LOONGSON_PCILO0_BASE+LOONGSON_PCILO_SIZE-1)
|
||||
|
||||
#define LOONGSON_PCICFG_BASE 0x1fe80000
|
||||
#define LOONGSON_PCICFG_SIZE 0x00000800 /* 2K */
|
||||
#define LOONGSON_PCICFG_TOP (LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
|
||||
#define LOONGSON_PCIIO_BASE 0x1fd00000
|
||||
|
||||
#define LOONGSON_PCIIO_SIZE 0x00100000 /* 1M */
|
||||
#define LOONGSON_PCIIO_TOP (LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
|
||||
|
||||
/* Loongson Register Bases */
|
||||
|
||||
#define LOONGSON_PCICONFIGBASE 0x00
|
||||
#define LOONGSON_REGBASE 0x100
|
||||
|
||||
/* PCI Configuration Registers */
|
||||
|
||||
#define LOONGSON_PCI_REG(x) LOONGSON_REG(LOONGSON_PCICONFIGBASE + (x))
|
||||
#define LOONGSON_PCIDID LOONGSON_PCI_REG(0x00)
|
||||
#define LOONGSON_PCICMD LOONGSON_PCI_REG(0x04)
|
||||
#define LOONGSON_PCICLASS LOONGSON_PCI_REG(0x08)
|
||||
#define LOONGSON_PCILTIMER LOONGSON_PCI_REG(0x0c)
|
||||
#define LOONGSON_PCIBASE0 LOONGSON_PCI_REG(0x10)
|
||||
#define LOONGSON_PCIBASE1 LOONGSON_PCI_REG(0x14)
|
||||
#define LOONGSON_PCIBASE2 LOONGSON_PCI_REG(0x18)
|
||||
#define LOONGSON_PCIBASE3 LOONGSON_PCI_REG(0x1c)
|
||||
#define LOONGSON_PCIBASE4 LOONGSON_PCI_REG(0x20)
|
||||
#define LOONGSON_PCIEXPRBASE LOONGSON_PCI_REG(0x30)
|
||||
#define LOONGSON_PCIINT LOONGSON_PCI_REG(0x3c)
|
||||
|
||||
#define LOONGSON_PCI_ISR4C LOONGSON_PCI_REG(0x4c)
|
||||
|
||||
#define LOONGSON_PCICMD_PERR_CLR 0x80000000
|
||||
#define LOONGSON_PCICMD_SERR_CLR 0x40000000
|
||||
#define LOONGSON_PCICMD_MABORT_CLR 0x20000000
|
||||
#define LOONGSON_PCICMD_MTABORT_CLR 0x10000000
|
||||
#define LOONGSON_PCICMD_TABORT_CLR 0x08000000
|
||||
#define LOONGSON_PCICMD_MPERR_CLR 0x01000000
|
||||
#define LOONGSON_PCICMD_PERRRESPEN 0x00000040
|
||||
#define LOONGSON_PCICMD_ASTEPEN 0x00000080
|
||||
#define LOONGSON_PCICMD_SERREN 0x00000100
|
||||
#define LOONGSON_PCILTIMER_BUSLATENCY 0x0000ff00
|
||||
#define LOONGSON_PCILTIMER_BUSLATENCY_SHIFT 8
|
||||
|
||||
/* Loongson h/w Configuration */
|
||||
|
||||
#define LOONGSON_GENCFG_OFFSET 0x4
|
||||
#define LOONGSON_GENCFG LOONGSON_REG(LOONGSON_REGBASE + LOONGSON_GENCFG_OFFSET)
|
||||
|
||||
#define LOONGSON_GENCFG_DEBUGMODE 0x00000001
|
||||
#define LOONGSON_GENCFG_SNOOPEN 0x00000002
|
||||
#define LOONGSON_GENCFG_CPUSELFRESET 0x00000004
|
||||
|
||||
#define LOONGSON_GENCFG_FORCE_IRQA 0x00000008
|
||||
#define LOONGSON_GENCFG_IRQA_ISOUT 0x00000010
|
||||
#define LOONGSON_GENCFG_IRQA_FROM_INT1 0x00000020
|
||||
#define LOONGSON_GENCFG_BYTESWAP 0x00000040
|
||||
|
||||
#define LOONGSON_GENCFG_UNCACHED 0x00000080
|
||||
#define LOONGSON_GENCFG_PREFETCHEN 0x00000100
|
||||
#define LOONGSON_GENCFG_WBEHINDEN 0x00000200
|
||||
#define LOONGSON_GENCFG_CACHEALG 0x00000c00
|
||||
#define LOONGSON_GENCFG_CACHEALG_SHIFT 10
|
||||
#define LOONGSON_GENCFG_PCIQUEUE 0x00001000
|
||||
#define LOONGSON_GENCFG_CACHESTOP 0x00002000
|
||||
#define LOONGSON_GENCFG_MSTRBYTESWAP 0x00004000
|
||||
#define LOONGSON_GENCFG_BUSERREN 0x00008000
|
||||
#define LOONGSON_GENCFG_NORETRYTIMEOUT 0x00010000
|
||||
#define LOONGSON_GENCFG_SHORTCOPYTIMEOUT 0x00020000
|
||||
|
||||
/* PCI address map control */
|
||||
|
||||
#define LOONGSON_PCIMAP LOONGSON_REG(LOONGSON_REGBASE + 0x10)
|
||||
#define LOONGSON_PCIMEMBASECFG LOONGSON_REG(LOONGSON_REGBASE + 0x14)
|
||||
#define LOONGSON_PCIMAP_CFG LOONGSON_REG(LOONGSON_REGBASE + 0x18)
|
||||
|
||||
/* GPIO Regs - r/w */
|
||||
|
||||
#define LOONGSON_GPIODATA LOONGSON_REG(LOONGSON_REGBASE + 0x1c)
|
||||
#define LOONGSON_GPIOIE LOONGSON_REG(LOONGSON_REGBASE + 0x20)
|
||||
|
||||
/* ICU Configuration Regs - r/w */
|
||||
|
||||
#define LOONGSON_INTEDGE LOONGSON_REG(LOONGSON_REGBASE + 0x24)
|
||||
#define LOONGSON_INTSTEER LOONGSON_REG(LOONGSON_REGBASE + 0x28)
|
||||
#define LOONGSON_INTPOL LOONGSON_REG(LOONGSON_REGBASE + 0x2c)
|
||||
|
||||
/* ICU Enable Regs - IntEn & IntISR are r/o. */
|
||||
|
||||
#define LOONGSON_INTENSET LOONGSON_REG(LOONGSON_REGBASE + 0x30)
|
||||
#define LOONGSON_INTENCLR LOONGSON_REG(LOONGSON_REGBASE + 0x34)
|
||||
#define LOONGSON_INTEN LOONGSON_REG(LOONGSON_REGBASE + 0x38)
|
||||
#define LOONGSON_INTISR LOONGSON_REG(LOONGSON_REGBASE + 0x3c)
|
||||
|
||||
/* ICU */
|
||||
#define LOONGSON_ICU_MBOXES 0x0000000f
|
||||
#define LOONGSON_ICU_MBOXES_SHIFT 0
|
||||
#define LOONGSON_ICU_DMARDY 0x00000010
|
||||
#define LOONGSON_ICU_DMAEMPTY 0x00000020
|
||||
#define LOONGSON_ICU_COPYRDY 0x00000040
|
||||
#define LOONGSON_ICU_COPYEMPTY 0x00000080
|
||||
#define LOONGSON_ICU_COPYERR 0x00000100
|
||||
#define LOONGSON_ICU_PCIIRQ 0x00000200
|
||||
#define LOONGSON_ICU_MASTERERR 0x00000400
|
||||
#define LOONGSON_ICU_SYSTEMERR 0x00000800
|
||||
#define LOONGSON_ICU_DRAMPERR 0x00001000
|
||||
#define LOONGSON_ICU_RETRYERR 0x00002000
|
||||
#define LOONGSON_ICU_GPIOS 0x01ff0000
|
||||
#define LOONGSON_ICU_GPIOS_SHIFT 16
|
||||
#define LOONGSON_ICU_GPINS 0x7e000000
|
||||
#define LOONGSON_ICU_GPINS_SHIFT 25
|
||||
#define LOONGSON_ICU_MBOX(N) (1<<(LOONGSON_ICU_MBOXES_SHIFT+(N)))
|
||||
#define LOONGSON_ICU_GPIO(N) (1<<(LOONGSON_ICU_GPIOS_SHIFT+(N)))
|
||||
#define LOONGSON_ICU_GPIN(N) (1<<(LOONGSON_ICU_GPINS_SHIFT+(N)))
|
||||
|
||||
/* PCI prefetch window base & mask */
|
||||
|
||||
#define LOONGSON_MEM_WIN_BASE_L LOONGSON_REG(LOONGSON_REGBASE + 0x40)
|
||||
#define LOONGSON_MEM_WIN_BASE_H LOONGSON_REG(LOONGSON_REGBASE + 0x44)
|
||||
#define LOONGSON_MEM_WIN_MASK_L LOONGSON_REG(LOONGSON_REGBASE + 0x48)
|
||||
#define LOONGSON_MEM_WIN_MASK_H LOONGSON_REG(LOONGSON_REGBASE + 0x4c)
|
||||
|
||||
/* PCI_Hit*_Sel_* */
|
||||
|
||||
#define LOONGSON_PCI_HIT0_SEL_L LOONGSON_REG(LOONGSON_REGBASE + 0x50)
|
||||
#define LOONGSON_PCI_HIT0_SEL_H LOONGSON_REG(LOONGSON_REGBASE + 0x54)
|
||||
#define LOONGSON_PCI_HIT1_SEL_L LOONGSON_REG(LOONGSON_REGBASE + 0x58)
|
||||
#define LOONGSON_PCI_HIT1_SEL_H LOONGSON_REG(LOONGSON_REGBASE + 0x5c)
|
||||
#define LOONGSON_PCI_HIT2_SEL_L LOONGSON_REG(LOONGSON_REGBASE + 0x60)
|
||||
#define LOONGSON_PCI_HIT2_SEL_H LOONGSON_REG(LOONGSON_REGBASE + 0x64)
|
||||
|
||||
/* PXArb Config & Status */
|
||||
|
||||
#define LOONGSON_PXARB_CFG LOONGSON_REG(LOONGSON_REGBASE + 0x68)
|
||||
#define LOONGSON_PXARB_STATUS LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
|
||||
|
||||
/* Chip Config registor of each physical cpu package, PRid >= Loongson-2F */
|
||||
#define LOONGSON_CHIPCFG (void __iomem *)TO_UNCAC(0x1fc00180)
|
||||
|
||||
/* pcimap */
|
||||
|
||||
#define LOONGSON_PCIMAP_PCIMAP_LO0 0x0000003f
|
||||
#define LOONGSON_PCIMAP_PCIMAP_LO0_SHIFT 0
|
||||
#define LOONGSON_PCIMAP_PCIMAP_LO1 0x00000fc0
|
||||
#define LOONGSON_PCIMAP_PCIMAP_LO1_SHIFT 6
|
||||
#define LOONGSON_PCIMAP_PCIMAP_LO2 0x0003f000
|
||||
#define LOONGSON_PCIMAP_PCIMAP_LO2_SHIFT 12
|
||||
#define LOONGSON_PCIMAP_PCIMAP_2 0x00040000
|
||||
#define LOONGSON_PCIMAP_WIN(WIN, ADDR) \
|
||||
((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
|
||||
|
||||
#ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
|
||||
#include <linux/cpufreq.h>
|
||||
extern struct cpufreq_frequency_table loongson2_clockmod_table[];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* address windows configuration module
|
||||
*
|
||||
* loongson2e do not have this module
|
||||
*/
|
||||
#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
|
||||
|
||||
/* address window config module base address */
|
||||
#define LOONGSON_ADDRWINCFG_BASE 0x3ff00000ul
|
||||
#define LOONGSON_ADDRWINCFG_SIZE 0x180
|
||||
|
||||
extern unsigned long _loongson_addrwincfg_base;
|
||||
#define LOONGSON_ADDRWINCFG(offset) \
|
||||
(*(volatile u64 *)(_loongson_addrwincfg_base + (offset)))
|
||||
|
||||
#define CPU_WIN0_BASE LOONGSON_ADDRWINCFG(0x00)
|
||||
#define CPU_WIN1_BASE LOONGSON_ADDRWINCFG(0x08)
|
||||
#define CPU_WIN2_BASE LOONGSON_ADDRWINCFG(0x10)
|
||||
#define CPU_WIN3_BASE LOONGSON_ADDRWINCFG(0x18)
|
||||
|
||||
#define CPU_WIN0_MASK LOONGSON_ADDRWINCFG(0x20)
|
||||
#define CPU_WIN1_MASK LOONGSON_ADDRWINCFG(0x28)
|
||||
#define CPU_WIN2_MASK LOONGSON_ADDRWINCFG(0x30)
|
||||
#define CPU_WIN3_MASK LOONGSON_ADDRWINCFG(0x38)
|
||||
|
||||
#define CPU_WIN0_MMAP LOONGSON_ADDRWINCFG(0x40)
|
||||
#define CPU_WIN1_MMAP LOONGSON_ADDRWINCFG(0x48)
|
||||
#define CPU_WIN2_MMAP LOONGSON_ADDRWINCFG(0x50)
|
||||
#define CPU_WIN3_MMAP LOONGSON_ADDRWINCFG(0x58)
|
||||
|
||||
#define PCIDMA_WIN0_BASE LOONGSON_ADDRWINCFG(0x60)
|
||||
#define PCIDMA_WIN1_BASE LOONGSON_ADDRWINCFG(0x68)
|
||||
#define PCIDMA_WIN2_BASE LOONGSON_ADDRWINCFG(0x70)
|
||||
#define PCIDMA_WIN3_BASE LOONGSON_ADDRWINCFG(0x78)
|
||||
|
||||
#define PCIDMA_WIN0_MASK LOONGSON_ADDRWINCFG(0x80)
|
||||
#define PCIDMA_WIN1_MASK LOONGSON_ADDRWINCFG(0x88)
|
||||
#define PCIDMA_WIN2_MASK LOONGSON_ADDRWINCFG(0x90)
|
||||
#define PCIDMA_WIN3_MASK LOONGSON_ADDRWINCFG(0x98)
|
||||
|
||||
#define PCIDMA_WIN0_MMAP LOONGSON_ADDRWINCFG(0xa0)
|
||||
#define PCIDMA_WIN1_MMAP LOONGSON_ADDRWINCFG(0xa8)
|
||||
#define PCIDMA_WIN2_MMAP LOONGSON_ADDRWINCFG(0xb0)
|
||||
#define PCIDMA_WIN3_MMAP LOONGSON_ADDRWINCFG(0xb8)
|
||||
|
||||
#define ADDRWIN_WIN0 0
|
||||
#define ADDRWIN_WIN1 1
|
||||
#define ADDRWIN_WIN2 2
|
||||
#define ADDRWIN_WIN3 3
|
||||
|
||||
#define ADDRWIN_MAP_DST_DDR 0
|
||||
#define ADDRWIN_MAP_DST_PCI 1
|
||||
#define ADDRWIN_MAP_DST_LIO 1
|
||||
|
||||
/*
|
||||
* s: CPU, PCIDMA
|
||||
* d: DDR, PCI, LIO
|
||||
* win: 0, 1, 2, 3
|
||||
* src: map source
|
||||
* dst: map destination
|
||||
* size: ~mask + 1
|
||||
*/
|
||||
#define LOONGSON_ADDRWIN_CFG(s, d, w, src, dst, size) do {\
|
||||
s##_WIN##w##_BASE = (src); \
|
||||
s##_WIN##w##_MMAP = (dst) | ADDRWIN_MAP_DST_##d; \
|
||||
s##_WIN##w##_MASK = ~(size-1); \
|
||||
} while (0)
|
||||
|
||||
#define LOONGSON_ADDRWIN_CPUTOPCI(win, src, dst, size) \
|
||||
LOONGSON_ADDRWIN_CFG(CPU, PCI, win, src, dst, size)
|
||||
#define LOONGSON_ADDRWIN_CPUTODDR(win, src, dst, size) \
|
||||
LOONGSON_ADDRWIN_CFG(CPU, DDR, win, src, dst, size)
|
||||
#define LOONGSON_ADDRWIN_PCITODDR(win, src, dst, size) \
|
||||
LOONGSON_ADDRWIN_CFG(PCIDMA, DDR, win, src, dst, size)
|
||||
|
||||
#endif /* ! CONFIG_CPU_SUPPORTS_ADDRWINCFG */
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON2EF_LOONGSON_H */
|
|
@ -4,8 +4,8 @@
|
|||
* Author: Wu Zhangjin <wuzhangjin@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_LOONGSON64_MACHINE_H
|
||||
#define __ASM_MACH_LOONGSON64_MACHINE_H
|
||||
#ifndef __ASM_MACH_LOONGSON2EF_MACHINE_H
|
||||
#define __ASM_MACH_LOONGSON2EF_MACHINE_H
|
||||
|
||||
#ifdef CONFIG_LEMOTE_FULOONG2E
|
||||
|
||||
|
@ -20,10 +20,4 @@
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LOONGSON_MACH3X
|
||||
|
||||
#define LOONGSON_MACHTYPE MACH_LOONGSON_GENERIC
|
||||
|
||||
#endif /* CONFIG_LOONGSON_MACH3X */
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON64_MACHINE_H */
|
||||
#endif /* __ASM_MACH_LOONGSON2EF_MACHINE_H */
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 1998, 2001, 03, 07 by Ralf Baechle (ralf@linux-mips.org)
|
||||
*
|
||||
* RTC routines for PC style attached Dallas chip.
|
||||
*/
|
||||
#ifndef __ASM_MACH_LOONGSON2EF_MC146818RTC_H
|
||||
#define __ASM_MACH_LOONGSON2EF_MC146818RTC_H
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
#define RTC_PORT(x) (0x70 + (x))
|
||||
#define RTC_IRQ 8
|
||||
|
||||
static inline unsigned char CMOS_READ(unsigned long addr)
|
||||
{
|
||||
outb_p(addr, RTC_PORT(0));
|
||||
return inb_p(RTC_PORT(1));
|
||||
}
|
||||
|
||||
static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
|
||||
{
|
||||
outb_p(addr, RTC_PORT(0));
|
||||
outb_p(data, RTC_PORT(1));
|
||||
}
|
||||
|
||||
#define RTC_ALWAYS_BCD 0
|
||||
|
||||
#ifndef mc146818_decode_year
|
||||
#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON2EF_MC146818RTC_H */
|
|
@ -4,8 +4,8 @@
|
|||
* Author: Wu Zhangjin <wuzhangjin@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_LOONGSON64_MEM_H
|
||||
#define __ASM_MACH_LOONGSON64_MEM_H
|
||||
#ifndef __ASM_MACH_LOONGSON2EF_MEM_H
|
||||
#define __ASM_MACH_LOONGSON2EF_MEM_H
|
||||
|
||||
/*
|
||||
* high memory space
|
||||
|
@ -34,4 +34,4 @@
|
|||
#define LOONGSON_MMIO_MEM_END 0x80000000
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON64_MEM_H */
|
||||
#endif /* __ASM_MACH_LOONGSON2EF_MEM_H */
|
|
@ -0,0 +1,46 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2008 Zhang Le <r0bertz@gentoo.org>
|
||||
* Copyright (c) 2009 Wu Zhangjin <wuzhangjin@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_LOONGSON2EF_PCI_H_
|
||||
#define __ASM_MACH_LOONGSON2EF_PCI_H_
|
||||
|
||||
extern struct pci_ops loongson_pci_ops;
|
||||
|
||||
/* this is an offset from mips_io_port_base */
|
||||
#define LOONGSON_PCI_IO_START 0x00004000UL
|
||||
|
||||
#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
|
||||
|
||||
/*
|
||||
* we use address window2 to map cpu address space to pci space
|
||||
* window2: cpu [1G, 2G] -> pci [1G, 2G]
|
||||
* why not use window 0 & 1? because they are used by cpu when booting.
|
||||
* window0: cpu [0, 256M] -> ddr [0, 256M]
|
||||
* window1: cpu [256M, 512M] -> pci [256M, 512M]
|
||||
*/
|
||||
|
||||
/* the smallest LOONGSON_CPU_MEM_SRC can be 512M */
|
||||
#define LOONGSON_CPU_MEM_SRC 0x40000000ul /* 1G */
|
||||
#define LOONGSON_PCI_MEM_DST LOONGSON_CPU_MEM_SRC
|
||||
|
||||
#define LOONGSON_PCI_MEM_START LOONGSON_PCI_MEM_DST
|
||||
#define LOONGSON_PCI_MEM_END (0x80000000ul-1) /* 2G */
|
||||
|
||||
#define MMAP_CPUTOPCI_SIZE (LOONGSON_PCI_MEM_END - \
|
||||
LOONGSON_PCI_MEM_START + 1)
|
||||
|
||||
#else /* loongson2f/32bit & loongson2e */
|
||||
|
||||
/* this pci memory space is mapped by pcimap in pci.c */
|
||||
#define LOONGSON_PCI_MEM_START LOONGSON_PCILO1_BASE
|
||||
#define LOONGSON_PCI_MEM_END (LOONGSON_PCILO1_BASE + 0x04000000 * 2)
|
||||
|
||||
/* this is an offset from mips_io_port_base */
|
||||
#define LOONGSON_PCI_IO_START 0x00004000UL
|
||||
|
||||
#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
|
||||
|
||||
#endif /* !__ASM_MACH_LOONGSON2EF_PCI_H_ */
|
|
@ -0,0 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_MACH_LOONGSON2EF_SPACES_H_
|
||||
#define __ASM_MACH_LOONGSON2EF_SPACES_H_
|
||||
|
||||
#if defined(CONFIG_64BIT)
|
||||
#define CAC_BASE _AC(0x9800000000000000, UL)
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
#include <asm/mach-generic/spaces.h>
|
||||
#endif
|
|
@ -1,20 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __ASM_MACH_LOONGSON32_PROM_H
|
||||
#define __ASM_MACH_LOONGSON32_PROM_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
/* environment arguments from bootloader */
|
||||
extern unsigned long memsize, highmemsize;
|
||||
|
||||
/* loongson-specific command line, env and memory initialization */
|
||||
extern char *prom_getenv(char *name);
|
||||
extern void __init prom_init_cmdline(void);
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON32_PROM_H */
|
|
@ -43,11 +43,8 @@
|
|||
#define cpu_has_vint 0
|
||||
#define cpu_has_vtag_icache 0
|
||||
#define cpu_has_watch 1
|
||||
|
||||
#ifdef CONFIG_CPU_LOONGSON3
|
||||
#define cpu_has_wsbh 1
|
||||
#define cpu_has_ic_fills_f_dc 1
|
||||
#define cpu_hwrena_impl_bits 0xc0000000
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include <boot_param.h>
|
||||
|
||||
#ifdef CONFIG_CPU_LOONGSON3
|
||||
|
||||
/* cpu core interrupt numbers */
|
||||
#define MIPS_CPU_IRQ_BASE 56
|
||||
|
||||
|
@ -35,8 +33,6 @@
|
|||
|
||||
#define LOONGSON_INT_COREx_INTy(x, y) (1<<(x) | 1<<(y+4)) /* route to int y of core x */
|
||||
|
||||
#endif
|
||||
|
||||
extern void fixup_irqs(void);
|
||||
extern void loongson3_ipi_interrupt(struct pt_regs *regs);
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* Override macros used in arch/mips/kernel/head.S.
|
||||
*/
|
||||
.macro kernel_entry_setup
|
||||
#ifdef CONFIG_CPU_LOONGSON3
|
||||
.set push
|
||||
.set mips64
|
||||
/* Set LPA on LOONGSON3 config3 */
|
||||
|
@ -30,23 +29,29 @@
|
|||
mtc0 t0, CP0_PAGEGRAIN
|
||||
/* Enable STFill Buffer */
|
||||
mfc0 t0, CP0_PRID
|
||||
/* Loongson-3A R4+ */
|
||||
andi t1, t0, PRID_IMP_MASK
|
||||
li t2, PRID_IMP_LOONGSON_64G
|
||||
beq t1, t2, 1f
|
||||
nop
|
||||
/* Loongson-3A R2/R3 */
|
||||
andi t0, (PRID_IMP_MASK | PRID_REV_MASK)
|
||||
slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
|
||||
bnez t0, 1f
|
||||
slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
|
||||
bnez t0, 2f
|
||||
nop
|
||||
1:
|
||||
mfc0 t0, CP0_CONFIG6
|
||||
or t0, 0x100
|
||||
mtc0 t0, CP0_CONFIG6
|
||||
1:
|
||||
2:
|
||||
_ehb
|
||||
.set pop
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Do SMP slave processor setup.
|
||||
*/
|
||||
.macro smp_slave_setup
|
||||
#ifdef CONFIG_CPU_LOONGSON3
|
||||
.set push
|
||||
.set mips64
|
||||
/* Set LPA on LOONGSON3 config3 */
|
||||
|
@ -59,16 +64,23 @@
|
|||
mtc0 t0, CP0_PAGEGRAIN
|
||||
/* Enable STFill Buffer */
|
||||
mfc0 t0, CP0_PRID
|
||||
/* Loongson-3A R4+ */
|
||||
andi t1, t0, PRID_IMP_MASK
|
||||
li t2, PRID_IMP_LOONGSON_64G
|
||||
beq t1, t2, 1f
|
||||
nop
|
||||
/* Loongson-3A R2/R3 */
|
||||
andi t0, (PRID_IMP_MASK | PRID_REV_MASK)
|
||||
slti t0, (PRID_IMP_LOONGSON_64 | PRID_REV_LOONGSON3A_R2_0)
|
||||
bnez t0, 1f
|
||||
slti t0, (PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0)
|
||||
bnez t0, 2f
|
||||
nop
|
||||
1:
|
||||
mfc0 t0, CP0_CONFIG6
|
||||
or t0, 0x100
|
||||
mtc0 t0, CP0_CONFIG6
|
||||
1:
|
||||
2:
|
||||
_ehb
|
||||
.set pop
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON64_KERNEL_ENTRY_H */
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include <linux/irq.h>
|
||||
#include <boot_param.h>
|
||||
|
||||
/* loongson internal northbridge initialization */
|
||||
extern void bonito_irq_init(void);
|
||||
|
||||
/* machine-specific reboot/halt operation */
|
||||
extern void mach_prepare_reboot(void);
|
||||
|
@ -26,25 +24,9 @@ extern const struct plat_smp_ops loongson3_smp_ops;
|
|||
|
||||
/* loongson-specific command line, env and memory initialization */
|
||||
extern void __init prom_init_memory(void);
|
||||
extern void __init prom_init_cmdline(void);
|
||||
extern void __init prom_init_machtype(void);
|
||||
extern void __init prom_init_env(void);
|
||||
#ifdef CONFIG_LOONGSON_UART_BASE
|
||||
extern unsigned long _loongson_uart_base[], loongson_uart_base[];
|
||||
extern void prom_init_loongson_uart_base(void);
|
||||
#endif
|
||||
|
||||
static inline void prom_init_uart_base(void)
|
||||
{
|
||||
#ifdef CONFIG_LOONGSON_UART_BASE
|
||||
prom_init_loongson_uart_base();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* irq operation functions */
|
||||
extern void bonito_irqdispatch(void);
|
||||
extern void __init bonito_irq_init(void);
|
||||
extern void __init mach_init_irq(void);
|
||||
extern void mach_irq_dispatch(unsigned int pending);
|
||||
extern int mach_i8259_irq(void);
|
||||
|
||||
|
@ -64,17 +46,6 @@ extern int mach_i8259_irq(void);
|
|||
#define LOONGSON3_REG32(base, x) \
|
||||
(*(volatile u32 *)((char *)TO_UNCAC(base) + (x)))
|
||||
|
||||
#define LOONGSON_IRQ_BASE 32
|
||||
#define LOONGSON2_PERFCNT_IRQ (MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
static inline void do_perfcnt_IRQ(void)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_OPROFILE)
|
||||
do_IRQ(LOONGSON2_PERFCNT_IRQ);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define LOONGSON_FLASH_BASE 0x1c000000
|
||||
#define LOONGSON_FLASH_SIZE 0x02000000 /* 32M */
|
||||
#define LOONGSON_FLASH_TOP (LOONGSON_FLASH_BASE+LOONGSON_FLASH_SIZE-1)
|
||||
|
@ -109,11 +80,7 @@ static inline void do_perfcnt_IRQ(void)
|
|||
#define LOONGSON_PCICFG_SIZE 0x00000800 /* 2K */
|
||||
#define LOONGSON_PCICFG_TOP (LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
|
||||
|
||||
#ifdef CONFIG_CPU_LOONGSON3
|
||||
#define LOONGSON_PCIIO_BASE loongson_sysconf.pci_io_base
|
||||
#else
|
||||
#define LOONGSON_PCIIO_BASE 0x1fd00000
|
||||
#endif
|
||||
|
||||
#define LOONGSON_PCIIO_SIZE 0x00100000 /* 1M */
|
||||
#define LOONGSON_PCIIO_TOP (LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
|
||||
|
@ -270,86 +237,4 @@ extern u64 loongson_freqctrl[MAX_PACKAGES];
|
|||
#define LOONGSON_PCIMAP_WIN(WIN, ADDR) \
|
||||
((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
|
||||
|
||||
#ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
|
||||
#include <linux/cpufreq.h>
|
||||
extern struct cpufreq_frequency_table loongson2_clockmod_table[];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* address windows configuration module
|
||||
*
|
||||
* loongson2e do not have this module
|
||||
*/
|
||||
#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
|
||||
|
||||
/* address window config module base address */
|
||||
#define LOONGSON_ADDRWINCFG_BASE 0x3ff00000ul
|
||||
#define LOONGSON_ADDRWINCFG_SIZE 0x180
|
||||
|
||||
extern unsigned long _loongson_addrwincfg_base;
|
||||
#define LOONGSON_ADDRWINCFG(offset) \
|
||||
(*(volatile u64 *)(_loongson_addrwincfg_base + (offset)))
|
||||
|
||||
#define CPU_WIN0_BASE LOONGSON_ADDRWINCFG(0x00)
|
||||
#define CPU_WIN1_BASE LOONGSON_ADDRWINCFG(0x08)
|
||||
#define CPU_WIN2_BASE LOONGSON_ADDRWINCFG(0x10)
|
||||
#define CPU_WIN3_BASE LOONGSON_ADDRWINCFG(0x18)
|
||||
|
||||
#define CPU_WIN0_MASK LOONGSON_ADDRWINCFG(0x20)
|
||||
#define CPU_WIN1_MASK LOONGSON_ADDRWINCFG(0x28)
|
||||
#define CPU_WIN2_MASK LOONGSON_ADDRWINCFG(0x30)
|
||||
#define CPU_WIN3_MASK LOONGSON_ADDRWINCFG(0x38)
|
||||
|
||||
#define CPU_WIN0_MMAP LOONGSON_ADDRWINCFG(0x40)
|
||||
#define CPU_WIN1_MMAP LOONGSON_ADDRWINCFG(0x48)
|
||||
#define CPU_WIN2_MMAP LOONGSON_ADDRWINCFG(0x50)
|
||||
#define CPU_WIN3_MMAP LOONGSON_ADDRWINCFG(0x58)
|
||||
|
||||
#define PCIDMA_WIN0_BASE LOONGSON_ADDRWINCFG(0x60)
|
||||
#define PCIDMA_WIN1_BASE LOONGSON_ADDRWINCFG(0x68)
|
||||
#define PCIDMA_WIN2_BASE LOONGSON_ADDRWINCFG(0x70)
|
||||
#define PCIDMA_WIN3_BASE LOONGSON_ADDRWINCFG(0x78)
|
||||
|
||||
#define PCIDMA_WIN0_MASK LOONGSON_ADDRWINCFG(0x80)
|
||||
#define PCIDMA_WIN1_MASK LOONGSON_ADDRWINCFG(0x88)
|
||||
#define PCIDMA_WIN2_MASK LOONGSON_ADDRWINCFG(0x90)
|
||||
#define PCIDMA_WIN3_MASK LOONGSON_ADDRWINCFG(0x98)
|
||||
|
||||
#define PCIDMA_WIN0_MMAP LOONGSON_ADDRWINCFG(0xa0)
|
||||
#define PCIDMA_WIN1_MMAP LOONGSON_ADDRWINCFG(0xa8)
|
||||
#define PCIDMA_WIN2_MMAP LOONGSON_ADDRWINCFG(0xb0)
|
||||
#define PCIDMA_WIN3_MMAP LOONGSON_ADDRWINCFG(0xb8)
|
||||
|
||||
#define ADDRWIN_WIN0 0
|
||||
#define ADDRWIN_WIN1 1
|
||||
#define ADDRWIN_WIN2 2
|
||||
#define ADDRWIN_WIN3 3
|
||||
|
||||
#define ADDRWIN_MAP_DST_DDR 0
|
||||
#define ADDRWIN_MAP_DST_PCI 1
|
||||
#define ADDRWIN_MAP_DST_LIO 1
|
||||
|
||||
/*
|
||||
* s: CPU, PCIDMA
|
||||
* d: DDR, PCI, LIO
|
||||
* win: 0, 1, 2, 3
|
||||
* src: map source
|
||||
* dst: map destination
|
||||
* size: ~mask + 1
|
||||
*/
|
||||
#define LOONGSON_ADDRWIN_CFG(s, d, w, src, dst, size) do {\
|
||||
s##_WIN##w##_BASE = (src); \
|
||||
s##_WIN##w##_MMAP = (dst) | ADDRWIN_MAP_DST_##d; \
|
||||
s##_WIN##w##_MASK = ~(size-1); \
|
||||
} while (0)
|
||||
|
||||
#define LOONGSON_ADDRWIN_CPUTOPCI(win, src, dst, size) \
|
||||
LOONGSON_ADDRWIN_CFG(CPU, PCI, win, src, dst, size)
|
||||
#define LOONGSON_ADDRWIN_CPUTODDR(win, src, dst, size) \
|
||||
LOONGSON_ADDRWIN_CFG(CPU, DDR, win, src, dst, size)
|
||||
#define LOONGSON_ADDRWIN_PCITODDR(win, src, dst, size) \
|
||||
LOONGSON_ADDRWIN_CFG(PCIDMA, DDR, win, src, dst, size)
|
||||
|
||||
#endif /* ! CONFIG_CPU_SUPPORTS_ADDRWINCFG */
|
||||
|
||||
#endif /* __ASM_MACH_LOONGSON64_LOONGSON_H */
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Read/Write Loongson Extension Registers
|
||||
*/
|
||||
|
||||
#ifndef _LOONGSON_REGS_H_
|
||||
#define _LOONGSON_REGS_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/cpu.h>
|
||||
|
||||
static inline bool cpu_has_cfg(void)
|
||||
{
|
||||
return ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64G);
|
||||
}
|
||||
|
||||
static inline u32 read_cpucfg(u32 reg)
|
||||
{
|
||||
u32 __res;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"parse_r __res,%0\n\t"
|
||||
"parse_r reg,%1\n\t"
|
||||
".insn \n\t"
|
||||
".word (0xc8080118 | (reg << 21) | (__res << 11))\n\t"
|
||||
:"=r"(__res)
|
||||
:"r"(reg)
|
||||
:
|
||||
);
|
||||
return __res;
|
||||
}
|
||||
|
||||
/* Bit Domains for CFG registers */
|
||||
#define LOONGSON_CFG0 0x0
|
||||
#define LOONGSON_CFG0_PRID GENMASK(31, 0)
|
||||
|
||||
#define LOONGSON_CFG1 0x1
|
||||
#define LOONGSON_CFG1_FP BIT(0)
|
||||
#define LOONGSON_CFG1_FPREV GENMASK(3, 1)
|
||||
#define LOONGSON_CFG1_MMI BIT(4)
|
||||
#define LOONGSON_CFG1_MSA1 BIT(5)
|
||||
#define LOONGSON_CFG1_MSA2 BIT(6)
|
||||
#define LOONGSON_CFG1_CGP BIT(7)
|
||||
#define LOONGSON_CFG1_WRP BIT(8)
|
||||
#define LOONGSON_CFG1_LSX1 BIT(9)
|
||||
#define LOONGSON_CFG1_LSX2 BIT(10)
|
||||
#define LOONGSON_CFG1_LASX BIT(11)
|
||||
#define LOONGSON_CFG1_R6FXP BIT(12)
|
||||
#define LOONGSON_CFG1_R6CRCP BIT(13)
|
||||
#define LOONGSON_CFG1_R6FPP BIT(14)
|
||||
#define LOONGSON_CFG1_CNT64 BIT(15)
|
||||
#define LOONGSON_CFG1_LSLDR0 BIT(16)
|
||||
#define LOONGSON_CFG1_LSPREF BIT(17)
|
||||
#define LOONGSON_CFG1_LSPREFX BIT(18)
|
||||
#define LOONGSON_CFG1_LSSYNCI BIT(19)
|
||||
#define LOONGSON_CFG1_LSUCA BIT(20)
|
||||
#define LOONGSON_CFG1_LLSYNC BIT(21)
|
||||
#define LOONGSON_CFG1_TGTSYNC BIT(22)
|
||||
#define LOONGSON_CFG1_LLEXC BIT(23)
|
||||
#define LOONGSON_CFG1_SCRAND BIT(24)
|
||||
#define LOONGSON_CFG1_MUALP BIT(25)
|
||||
#define LOONGSON_CFG1_KMUALEN BIT(26)
|
||||
#define LOONGSON_CFG1_ITLBT BIT(27)
|
||||
#define LOONGSON_CFG1_LSUPERF BIT(28)
|
||||
#define LOONGSON_CFG1_SFBP BIT(29)
|
||||
#define LOONGSON_CFG1_CDMAP BIT(30)
|
||||
|
||||
#define LOONGSON_CFG2 0x2
|
||||
#define LOONGSON_CFG2_LEXT1 BIT(0)
|
||||
#define LOONGSON_CFG2_LEXT2 BIT(1)
|
||||
#define LOONGSON_CFG2_LEXT3 BIT(2)
|
||||
#define LOONGSON_CFG2_LSPW BIT(3)
|
||||
#define LOONGSON_CFG2_LBT1 BIT(4)
|
||||
#define LOONGSON_CFG2_LBT2 BIT(5)
|
||||
#define LOONGSON_CFG2_LBT3 BIT(6)
|
||||
#define LOONGSON_CFG2_LBTMMU BIT(7)
|
||||
#define LOONGSON_CFG2_LPMP BIT(8)
|
||||
#define LOONGSON_CFG2_LPMPREV GENMASK(11, 9)
|
||||
#define LOONGSON_CFG2_LAMO BIT(12)
|
||||
#define LOONGSON_CFG2_LPIXU BIT(13)
|
||||
#define LOONGSON_CFG2_LPIXUN BIT(14)
|
||||
#define LOONGSON_CFG2_LZVP BIT(15)
|
||||
#define LOONGSON_CFG2_LZVREV GENMASK(18, 16)
|
||||
#define LOONGSON_CFG2_LGFTP BIT(19)
|
||||
#define LOONGSON_CFG2_LGFTPREV GENMASK(22, 20)
|
||||
#define LOONGSON_CFG2_LLFTP BIT(23)
|
||||
#define LOONGSON_CFG2_LLFTPREV GENMASK(26, 24)
|
||||
#define LOONGSON_CFG2_LCSRP BIT(27)
|
||||
#define LOONGSON_CFG2_LDISBLIKELY BIT(28)
|
||||
|
||||
#define LOONGSON_CFG3 0x3
|
||||
#define LOONGSON_CFG3_LCAMP BIT(0)
|
||||
#define LOONGSON_CFG3_LCAMREV GENMASK(3, 1)
|
||||
#define LOONGSON_CFG3_LCAMNUM GENMASK(11, 4)
|
||||
#define LOONGSON_CFG3_LCAMKW GENMASK(19, 12)
|
||||
#define LOONGSON_CFG3_LCAMVW GENMASK(27, 20)
|
||||
|
||||
#define LOONGSON_CFG4 0x4
|
||||
#define LOONGSON_CFG4_CCFREQ GENMASK(31, 0)
|
||||
|
||||
#define LOONGSON_CFG5 0x5
|
||||
#define LOONGSON_CFG5_CFM GENMASK(15, 0)
|
||||
#define LOONGSON_CFG5_CFD GENMASK(31, 16)
|
||||
|
||||
#define LOONGSON_CFG6 0x6
|
||||
|
||||
#define LOONGSON_CFG7 0x7
|
||||
#define LOONGSON_CFG7_GCCAEQRP BIT(0)
|
||||
#define LOONGSON_CFG7_UCAWINP BIT(1)
|
||||
|
||||
static inline bool cpu_has_csr(void)
|
||||
{
|
||||
if (cpu_has_cfg())
|
||||
return (read_cpucfg(LOONGSON_CFG2) & LOONGSON_CFG2_LCSRP);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline u32 csr_readl(u32 reg)
|
||||
{
|
||||
u32 __res;
|
||||
|
||||
/* RDCSR reg, val */
|
||||
__asm__ __volatile__(
|
||||
"parse_r __res,%0\n\t"
|
||||
"parse_r reg,%1\n\t"
|
||||
".insn \n\t"
|
||||
".word (0xc8000118 | (reg << 21) | (__res << 11))\n\t"
|
||||
:"=r"(__res)
|
||||
:"r"(reg)
|
||||
:
|
||||
);
|
||||
return __res;
|
||||
}
|
||||
|
||||
static inline u64 csr_readq(u32 reg)
|
||||
{
|
||||
u64 __res;
|
||||
|
||||
/* DWRCSR reg, val */
|
||||
__asm__ __volatile__(
|
||||
"parse_r __res,%0\n\t"
|
||||
"parse_r reg,%1\n\t"
|
||||
".insn \n\t"
|
||||
".word (0xc8020118 | (reg << 21) | (__res << 11))\n\t"
|
||||
:"=r"(__res)
|
||||
:"r"(reg)
|
||||
:
|
||||
);
|
||||
return __res;
|
||||
}
|
||||
|
||||
static inline void csr_writel(u32 val, u32 reg)
|
||||
{
|
||||
/* WRCSR reg, val */
|
||||
__asm__ __volatile__(
|
||||
"parse_r reg,%0\n\t"
|
||||
"parse_r val,%1\n\t"
|
||||
".insn \n\t"
|
||||
".word (0xc8010118 | (reg << 21) | (val << 11))\n\t"
|
||||
:
|
||||
:"r"(reg),"r"(val)
|
||||
:
|
||||
);
|
||||
}
|
||||
|
||||
static inline void csr_writeq(u64 val, u32 reg)
|
||||
{
|
||||
/* DWRCSR reg, val */
|
||||
__asm__ __volatile__(
|
||||
"parse_r reg,%0\n\t"
|
||||
"parse_r val,%1\n\t"
|
||||
".insn \n\t"
|
||||
".word (0xc8030118 | (reg << 21) | (val << 11))\n\t"
|
||||
:
|
||||
:"r"(reg),"r"(val)
|
||||
:
|
||||
);
|
||||
}
|
||||
|
||||
/* Public CSR Register can also be accessed with regular addresses */
|
||||
#define CSR_PUBLIC_MMIO_BASE 0x1fe00000
|
||||
|
||||
#define MMIO_CSR(x) (void *)TO_UNCAC(CSR_PUBLIC_MMIO_BASE + x)
|
||||
|
||||
#define LOONGSON_CSR_FEATURES 0x8
|
||||
#define LOONGSON_CSRF_TEMP BIT(0)
|
||||
#define LOONGSON_CSRF_NODECNT BIT(1)
|
||||
#define LOONGSON_CSRF_MSI BIT(2)
|
||||
#define LOONGSON_CSRF_EXTIOI BIT(3)
|
||||
#define LOONGSON_CSRF_IPI BIT(4)
|
||||
#define LOONGSON_CSRF_FREQ BIT(5)
|
||||
|
||||
#define LOONGSON_CSR_VENDOR 0x10 /* Vendor name string, should be "Loongson" */
|
||||
#define LOONGSON_CSR_CPUNAME 0x20 /* Processor name string */
|
||||
#define LOONGSON_CSR_NODECNT 0x408
|
||||
#define LOONGSON_CSR_CPUTEMP 0x428
|
||||
|
||||
/* PerCore CSR, only accessable by local cores */
|
||||
#define LOONGSON_CSR_IPI_STATUS 0x1000
|
||||
#define LOONGSON_CSR_IPI_EN 0x1004
|
||||
#define LOONGSON_CSR_IPI_SET 0x1008
|
||||
#define LOONGSON_CSR_IPI_CLEAR 0x100c
|
||||
#define LOONGSON_CSR_IPI_SEND 0x1040
|
||||
#define CSR_IPI_SEND_IP_SHIFT 0
|
||||
#define CSR_IPI_SEND_CPU_SHIFT 16
|
||||
#define CSR_IPI_SEND_BLOCK BIT(31)
|
||||
|
||||
static inline u64 drdtime(void)
|
||||
{
|
||||
int rID = 0;
|
||||
u64 val = 0;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"parse_r rID,%0\n\t"
|
||||
"parse_r val,%1\n\t"
|
||||
".insn \n\t"
|
||||
".word (0xc8090118 | (rID << 21) | (val << 11))\n\t"
|
||||
:"=r"(rID),"=r"(val)
|
||||
:
|
||||
);
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -6,8 +6,8 @@
|
|||
* Huacai Chen, chenhc@lemote.com
|
||||
* Xiaofu Meng, Shuangshuang Zhang
|
||||
*/
|
||||
#ifndef _ASM_MACH_MMZONE_H
|
||||
#define _ASM_MACH_MMZONE_H
|
||||
#ifndef _ASM_MACH_LOONGSON64_MMZONE_H
|
||||
#define _ASM_MACH_LOONGSON64_MMZONE_H
|
||||
|
||||
#include <boot_param.h>
|
||||
#define NODE_ADDRSPACE_SHIFT 44
|
||||
|
@ -19,30 +19,9 @@
|
|||
#define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
|
||||
#define nid_to_addrbase(nid) ((nid) << NODE_ADDRSPACE_SHIFT)
|
||||
|
||||
#define LEVELS_PER_SLICE 128
|
||||
extern struct pglist_data *__node_data[];
|
||||
|
||||
struct slice_data {
|
||||
unsigned long irq_enable_mask[2];
|
||||
int level_to_irq[LEVELS_PER_SLICE];
|
||||
};
|
||||
|
||||
struct hub_data {
|
||||
cpumask_t h_cpus;
|
||||
unsigned long slice_map;
|
||||
unsigned long irq_alloc_mask[2];
|
||||
struct slice_data slice[2];
|
||||
};
|
||||
|
||||
struct node_data {
|
||||
struct pglist_data pglist;
|
||||
struct hub_data hub;
|
||||
cpumask_t cpumask;
|
||||
};
|
||||
|
||||
extern struct node_data *__node_data[];
|
||||
|
||||
#define NODE_DATA(n) (&__node_data[(n)]->pglist)
|
||||
#define hub_data(n) (&__node_data[(n)]->hub)
|
||||
#define NODE_DATA(n) (__node_data[n])
|
||||
|
||||
extern void setup_zero_pages(void);
|
||||
extern void __init prom_init_numa_memory(void);
|
||||
|
|
|
@ -12,39 +12,8 @@ extern struct pci_ops loongson_pci_ops;
|
|||
/* this is an offset from mips_io_port_base */
|
||||
#define LOONGSON_PCI_IO_START 0x00004000UL
|
||||
|
||||
#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
|
||||
|
||||
/*
|
||||
* we use address window2 to map cpu address space to pci space
|
||||
* window2: cpu [1G, 2G] -> pci [1G, 2G]
|
||||
* why not use window 0 & 1? because they are used by cpu when booting.
|
||||
* window0: cpu [0, 256M] -> ddr [0, 256M]
|
||||
* window1: cpu [256M, 512M] -> pci [256M, 512M]
|
||||
*/
|
||||
|
||||
/* the smallest LOONGSON_CPU_MEM_SRC can be 512M */
|
||||
#define LOONGSON_CPU_MEM_SRC 0x40000000ul /* 1G */
|
||||
#define LOONGSON_PCI_MEM_DST LOONGSON_CPU_MEM_SRC
|
||||
|
||||
#define LOONGSON_PCI_MEM_START LOONGSON_PCI_MEM_DST
|
||||
#define LOONGSON_PCI_MEM_END (0x80000000ul-1) /* 2G */
|
||||
|
||||
#define MMAP_CPUTOPCI_SIZE (LOONGSON_PCI_MEM_END - \
|
||||
LOONGSON_PCI_MEM_START + 1)
|
||||
|
||||
#else /* loongson2f/32bit & loongson2e */
|
||||
|
||||
/* this pci memory space is mapped by pcimap in pci.c */
|
||||
#ifdef CONFIG_CPU_LOONGSON3
|
||||
#define LOONGSON_PCI_MEM_START 0x40000000UL
|
||||
#define LOONGSON_PCI_MEM_END 0x7effffffUL
|
||||
#else
|
||||
#define LOONGSON_PCI_MEM_START LOONGSON_PCILO1_BASE
|
||||
#define LOONGSON_PCI_MEM_END (LOONGSON_PCILO1_BASE + 0x04000000 * 2)
|
||||
#endif
|
||||
/* this is an offset from mips_io_port_base */
|
||||
#define LOONGSON_PCI_IO_START 0x00004000UL
|
||||
|
||||
#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
|
||||
|
||||
#endif /* !__ASM_MACH_LOONGSON64_PCI_H_ */
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#ifdef CONFIG_NUMA
|
||||
|
||||
#define cpu_to_node(cpu) (cpu_logical_map(cpu) >> 2)
|
||||
#define cpumask_of_node(node) (&__node_data[(node)]->cpumask)
|
||||
|
||||
extern cpumask_t __node_cpumask[];
|
||||
#define cpumask_of_node(node) (&__node_cpumask[node])
|
||||
|
||||
struct pci_bus;
|
||||
extern int pcibus_to_node(struct pci_bus *);
|
||||
|
|
|
@ -689,6 +689,9 @@
|
|||
#define MIPS_CONF7_IAR (_ULCAST_(1) << 10)
|
||||
#define MIPS_CONF7_AR (_ULCAST_(1) << 16)
|
||||
|
||||
/* Ingenic HPTLB off bits */
|
||||
#define XBURST_PAGECTRL_HPTLB_DIS 0xa9000000
|
||||
|
||||
/* Ingenic Config7 bits */
|
||||
#define MIPS_CONF7_BTB_LOOP_EN (_ULCAST_(1) << 4)
|
||||
|
||||
|
@ -1971,6 +1974,9 @@ do { \
|
|||
#define read_c0_brcm_sleepcount() __read_32bit_c0_register($22, 7)
|
||||
#define write_c0_brcm_sleepcount(val) __write_32bit_c0_register($22, 7, val)
|
||||
|
||||
/* Ingenic page ctrl register */
|
||||
#define write_c0_page_ctrl(val) __write_32bit_c0_register($5, 4, val)
|
||||
|
||||
/*
|
||||
* Macros to access the guest system control coprocessor
|
||||
*/
|
||||
|
|
|
@ -119,12 +119,12 @@ search_module_dbetables(unsigned long addr)
|
|||
#define MODULE_PROC_FAMILY "RM7000 "
|
||||
#elif defined CONFIG_CPU_SB1
|
||||
#define MODULE_PROC_FAMILY "SB1 "
|
||||
#elif defined CONFIG_CPU_LOONGSON1
|
||||
#define MODULE_PROC_FAMILY "LOONGSON1 "
|
||||
#elif defined CONFIG_CPU_LOONGSON2
|
||||
#define MODULE_PROC_FAMILY "LOONGSON2 "
|
||||
#elif defined CONFIG_CPU_LOONGSON3
|
||||
#define MODULE_PROC_FAMILY "LOONGSON3 "
|
||||
#elif defined CONFIG_CPU_LOONGSON32
|
||||
#define MODULE_PROC_FAMILY "LOONGSON32 "
|
||||
#elif defined CONFIG_CPU_LOONGSON2EF
|
||||
#define MODULE_PROC_FAMILY "LOONGSON2EF "
|
||||
#elif defined CONFIG_CPU_LOONGSON64
|
||||
#define MODULE_PROC_FAMILY "LOONGSON64 "
|
||||
#elif defined CONFIG_CPU_CAVIUM_OCTEON
|
||||
#define MODULE_PROC_FAMILY "OCTEON "
|
||||
#elif defined CONFIG_CPU_XLR
|
||||
|
|
|
@ -807,6 +807,7 @@ struct bridge_controller {
|
|||
unsigned long intr_addr;
|
||||
struct irq_domain *domain;
|
||||
unsigned int pci_int[8];
|
||||
u32 ioc3_sid[8];
|
||||
nasid_t nasid;
|
||||
};
|
||||
|
||||
|
|
|
@ -96,9 +96,9 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
|
|||
free_pages((unsigned long)pud, PUD_ORDER);
|
||||
}
|
||||
|
||||
static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
|
||||
static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
|
||||
{
|
||||
set_pgd(pgd, __pgd((unsigned long)pud));
|
||||
set_p4d(p4d, __p4d((unsigned long)pud));
|
||||
}
|
||||
|
||||
#define __pud_free_tlb(tlb, x, addr) pud_free((tlb)->mm, x)
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <asm/cachectl.h>
|
||||
#include <asm/fixmap.h>
|
||||
|
||||
#define __ARCH_USE_5LEVEL_HACK
|
||||
#include <asm-generic/pgtable-nopmd.h>
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
|
@ -196,14 +195,11 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
|
|||
|
||||
#define pte_page(x) pfn_to_page(pte_pfn(x))
|
||||
|
||||
#define __pgd_offset(address) pgd_index(address)
|
||||
#define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
|
||||
#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
|
||||
|
||||
/* to find an entry in a kernel page-table-directory */
|
||||
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
|
||||
|
||||
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
|
||||
#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
|
||||
#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
|
||||
|
||||
/* to find an entry in a page-table-directory */
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
#include <asm/cachectl.h>
|
||||
#include <asm/fixmap.h>
|
||||
|
||||
#define __ARCH_USE_5LEVEL_HACK
|
||||
#if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48)
|
||||
#if CONFIG_PGTABLE_LEVELS == 2
|
||||
#include <asm-generic/pgtable-nopmd.h>
|
||||
#elif !(defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS_VA_BITS_48))
|
||||
#elif CONFIG_PGTABLE_LEVELS == 3
|
||||
#include <asm-generic/pgtable-nopud.h>
|
||||
#else
|
||||
#include <asm-generic/pgtable-nop4d.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -186,44 +187,49 @@ extern pud_t invalid_pud_table[PTRS_PER_PUD];
|
|||
/*
|
||||
* Empty pgd entries point to the invalid_pud_table.
|
||||
*/
|
||||
static inline int pgd_none(pgd_t pgd)
|
||||
static inline int p4d_none(p4d_t p4d)
|
||||
{
|
||||
return pgd_val(pgd) == (unsigned long)invalid_pud_table;
|
||||
return p4d_val(p4d) == (unsigned long)invalid_pud_table;
|
||||
}
|
||||
|
||||
static inline int pgd_bad(pgd_t pgd)
|
||||
static inline int p4d_bad(p4d_t p4d)
|
||||
{
|
||||
if (unlikely(pgd_val(pgd) & ~PAGE_MASK))
|
||||
if (unlikely(p4d_val(p4d) & ~PAGE_MASK))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pgd_present(pgd_t pgd)
|
||||
static inline int p4d_present(p4d_t p4d)
|
||||
{
|
||||
return pgd_val(pgd) != (unsigned long)invalid_pud_table;
|
||||
return p4d_val(p4d) != (unsigned long)invalid_pud_table;
|
||||
}
|
||||
|
||||
static inline void pgd_clear(pgd_t *pgdp)
|
||||
static inline void p4d_clear(p4d_t *p4dp)
|
||||
{
|
||||
pgd_val(*pgdp) = (unsigned long)invalid_pud_table;
|
||||
p4d_val(*p4dp) = (unsigned long)invalid_pud_table;
|
||||
}
|
||||
|
||||
#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
|
||||
|
||||
static inline unsigned long pgd_page_vaddr(pgd_t pgd)
|
||||
static inline unsigned long p4d_page_vaddr(p4d_t p4d)
|
||||
{
|
||||
return pgd_val(pgd);
|
||||
return p4d_val(p4d);
|
||||
}
|
||||
|
||||
static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
|
||||
#define p4d_phys(p4d) virt_to_phys((void *)p4d_val(p4d))
|
||||
#define p4d_page(p4d) (pfn_to_page(p4d_phys(p4d) >> PAGE_SHIFT))
|
||||
|
||||
#define p4d_index(address) (((address) >> P4D_SHIFT) & (PTRS_PER_P4D - 1))
|
||||
|
||||
static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
|
||||
{
|
||||
return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address);
|
||||
return (pud_t *)p4d_page_vaddr(*p4d) + pud_index(address);
|
||||
}
|
||||
|
||||
static inline void set_pgd(pgd_t *pgd, pgd_t pgdval)
|
||||
static inline void set_p4d(p4d_t *p4d, p4d_t p4dval)
|
||||
{
|
||||
*pgd = pgdval;
|
||||
*p4d = p4dval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -314,10 +320,6 @@ static inline void pud_clear(pud_t *pudp)
|
|||
#define pfn_pmd(pfn, prot) __pmd(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
|
||||
#endif
|
||||
|
||||
#define __pgd_offset(address) pgd_index(address)
|
||||
#define __pud_offset(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
|
||||
#define __pmd_offset(address) pmd_index(address)
|
||||
|
||||
/* to find an entry in a kernel page-table-directory */
|
||||
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
|
||||
|
||||
|
|
|
@ -643,17 +643,6 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
|
|||
|
||||
#include <asm-generic/pgtable.h>
|
||||
|
||||
/*
|
||||
* uncached accelerated TLB map for video memory access
|
||||
*/
|
||||
#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED
|
||||
#define __HAVE_PHYS_MEM_ACCESS_PROT
|
||||
|
||||
struct file;
|
||||
pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
|
||||
unsigned long size, pgprot_t vma_prot);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We provide our own get_unmapped area to cope with the virtual aliasing
|
||||
* constraints placed on us by the cache architecture.
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2004 by Ralf Baechle
|
||||
*
|
||||
* The cpustart method is a PMC-Sierra's function to start the secondary CPU.
|
||||
* Stock PMON 2000 has the smpfork, semlock and semunlock methods instead.
|
||||
*/
|
||||
#ifndef _ASM_PMON_H
|
||||
#define _ASM_PMON_H
|
||||
|
||||
struct callvectors {
|
||||
int (*open) (char*, int, int);
|
||||
int (*close) (int);
|
||||
int (*read) (int, void*, int);
|
||||
int (*write) (int, void*, int);
|
||||
off_t (*lseek) (int, off_t, int);
|
||||
int (*printf) (const char*, ...);
|
||||
void (*cacheflush) (void);
|
||||
char* (*gets) (char*);
|
||||
union {
|
||||
int (*smpfork) (unsigned long cp, char *sp);
|
||||
int (*cpustart) (long, void (*)(void), void *, long);
|
||||
} _s;
|
||||
int (*semlock) (int sem);
|
||||
void (*semunlock) (int sem);
|
||||
};
|
||||
|
||||
extern struct callvectors *debug_vectors;
|
||||
|
||||
#define pmon_open(name, flags, mode) debug_vectors->open(name, flage, mode)
|
||||
#define pmon_close(fd) debug_vectors->close(fd)
|
||||
#define pmon_read(fd, buf, count) debug_vectors->read(fd, buf, count)
|
||||
#define pmon_write(fd, buf, count) debug_vectors->write(fd, buf, count)
|
||||
#define pmon_lseek(fd, off, whence) debug_vectors->lseek(fd, off, whence)
|
||||
#define pmon_printf(fmt...) debug_vectors->printf(fmt)
|
||||
#define pmon_cacheflush() debug_vectors->cacheflush()
|
||||
#define pmon_gets(s) debug_vectors->gets(s)
|
||||
#define pmon_cpustart(n, f, sp, gp) debug_vectors->_s.cpustart(n, f, sp, gp)
|
||||
#define pmon_smpfork(cp, sp) debug_vectors->_s.smpfork(cp, sp)
|
||||
#define pmon_semlock(sem) debug_vectors->semlock(sem)
|
||||
#define pmon_semunlock(sem) debug_vectors->semunlock(sem)
|
||||
|
||||
#endif /* _ASM_PMON_H */
|
|
@ -385,7 +385,7 @@ unsigned long get_wchan(struct task_struct *p);
|
|||
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29])
|
||||
#define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status)
|
||||
|
||||
#ifdef CONFIG_CPU_LOONGSON3
|
||||
#ifdef CONFIG_CPU_LOONGSON64
|
||||
/*
|
||||
* Loongson-3's SFB (Store-Fill-Buffer) may buffer writes indefinitely when a
|
||||
* tight read loop is executed, because reads take priority over writes & the
|
||||
|
|
|
@ -15,12 +15,14 @@
|
|||
#include <linux/stringify.h>
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/asm-eva.h>
|
||||
#include <asm/cacheops.h>
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/cpu-type.h>
|
||||
#include <asm/mipsmtregs.h>
|
||||
#include <asm/mmzone.h>
|
||||
#include <asm/unroll.h>
|
||||
#include <linux/uaccess.h> /* for uaccess_kernel() */
|
||||
|
||||
extern void (*r4k_blast_dcache)(void);
|
||||
|
@ -39,16 +41,19 @@ extern void (*r4k_blast_icache)(void);
|
|||
*/
|
||||
#define INDEX_BASE CKSEG0
|
||||
|
||||
#define cache_op(op,addr) \
|
||||
#define _cache_op(insn, op, addr) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n" \
|
||||
" cache %0, %1 \n" \
|
||||
" " insn("%0", "%1") " \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "i" (op), "R" (*(unsigned char *)(addr)))
|
||||
|
||||
#define cache_op(op, addr) \
|
||||
_cache_op(kernel_cache, op, addr)
|
||||
|
||||
static inline void flush_icache_line_indexed(unsigned long addr)
|
||||
{
|
||||
cache_op(Index_Invalidate_I, addr);
|
||||
|
@ -67,7 +72,7 @@ static inline void flush_scache_line_indexed(unsigned long addr)
|
|||
static inline void flush_icache_line(unsigned long addr)
|
||||
{
|
||||
switch (boot_cpu_type()) {
|
||||
case CPU_LOONGSON2:
|
||||
case CPU_LOONGSON2EF:
|
||||
cache_op(Hit_Invalidate_I_Loongson2, addr);
|
||||
break;
|
||||
|
||||
|
@ -149,7 +154,7 @@ static inline void flush_scache_line(unsigned long addr)
|
|||
static inline int protected_flush_icache_line(unsigned long addr)
|
||||
{
|
||||
switch (boot_cpu_type()) {
|
||||
case CPU_LOONGSON2:
|
||||
case CPU_LOONGSON2EF:
|
||||
return protected_cache_op(Hit_Invalidate_I_Loongson2, addr);
|
||||
|
||||
default:
|
||||
|
@ -193,338 +198,10 @@ static inline void invalidate_tcache_page(unsigned long addr)
|
|||
cache_op(Page_Invalidate_T, addr);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CPU_MIPSR6
|
||||
#define cache16_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set mips3 \n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x010(%0) \n" \
|
||||
" cache %1, 0x020(%0); cache %1, 0x030(%0) \n" \
|
||||
" cache %1, 0x040(%0); cache %1, 0x050(%0) \n" \
|
||||
" cache %1, 0x060(%0); cache %1, 0x070(%0) \n" \
|
||||
" cache %1, 0x080(%0); cache %1, 0x090(%0) \n" \
|
||||
" cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) \n" \
|
||||
" cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) \n" \
|
||||
" cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) \n" \
|
||||
" cache %1, 0x100(%0); cache %1, 0x110(%0) \n" \
|
||||
" cache %1, 0x120(%0); cache %1, 0x130(%0) \n" \
|
||||
" cache %1, 0x140(%0); cache %1, 0x150(%0) \n" \
|
||||
" cache %1, 0x160(%0); cache %1, 0x170(%0) \n" \
|
||||
" cache %1, 0x180(%0); cache %1, 0x190(%0) \n" \
|
||||
" cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) \n" \
|
||||
" cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) \n" \
|
||||
" cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache32_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set mips3 \n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x020(%0) \n" \
|
||||
" cache %1, 0x040(%0); cache %1, 0x060(%0) \n" \
|
||||
" cache %1, 0x080(%0); cache %1, 0x0a0(%0) \n" \
|
||||
" cache %1, 0x0c0(%0); cache %1, 0x0e0(%0) \n" \
|
||||
" cache %1, 0x100(%0); cache %1, 0x120(%0) \n" \
|
||||
" cache %1, 0x140(%0); cache %1, 0x160(%0) \n" \
|
||||
" cache %1, 0x180(%0); cache %1, 0x1a0(%0) \n" \
|
||||
" cache %1, 0x1c0(%0); cache %1, 0x1e0(%0) \n" \
|
||||
" cache %1, 0x200(%0); cache %1, 0x220(%0) \n" \
|
||||
" cache %1, 0x240(%0); cache %1, 0x260(%0) \n" \
|
||||
" cache %1, 0x280(%0); cache %1, 0x2a0(%0) \n" \
|
||||
" cache %1, 0x2c0(%0); cache %1, 0x2e0(%0) \n" \
|
||||
" cache %1, 0x300(%0); cache %1, 0x320(%0) \n" \
|
||||
" cache %1, 0x340(%0); cache %1, 0x360(%0) \n" \
|
||||
" cache %1, 0x380(%0); cache %1, 0x3a0(%0) \n" \
|
||||
" cache %1, 0x3c0(%0); cache %1, 0x3e0(%0) \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache64_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set mips3 \n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x040(%0) \n" \
|
||||
" cache %1, 0x080(%0); cache %1, 0x0c0(%0) \n" \
|
||||
" cache %1, 0x100(%0); cache %1, 0x140(%0) \n" \
|
||||
" cache %1, 0x180(%0); cache %1, 0x1c0(%0) \n" \
|
||||
" cache %1, 0x200(%0); cache %1, 0x240(%0) \n" \
|
||||
" cache %1, 0x280(%0); cache %1, 0x2c0(%0) \n" \
|
||||
" cache %1, 0x300(%0); cache %1, 0x340(%0) \n" \
|
||||
" cache %1, 0x380(%0); cache %1, 0x3c0(%0) \n" \
|
||||
" cache %1, 0x400(%0); cache %1, 0x440(%0) \n" \
|
||||
" cache %1, 0x480(%0); cache %1, 0x4c0(%0) \n" \
|
||||
" cache %1, 0x500(%0); cache %1, 0x540(%0) \n" \
|
||||
" cache %1, 0x580(%0); cache %1, 0x5c0(%0) \n" \
|
||||
" cache %1, 0x600(%0); cache %1, 0x640(%0) \n" \
|
||||
" cache %1, 0x680(%0); cache %1, 0x6c0(%0) \n" \
|
||||
" cache %1, 0x700(%0); cache %1, 0x740(%0) \n" \
|
||||
" cache %1, 0x780(%0); cache %1, 0x7c0(%0) \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache128_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set mips3 \n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x080(%0) \n" \
|
||||
" cache %1, 0x100(%0); cache %1, 0x180(%0) \n" \
|
||||
" cache %1, 0x200(%0); cache %1, 0x280(%0) \n" \
|
||||
" cache %1, 0x300(%0); cache %1, 0x380(%0) \n" \
|
||||
" cache %1, 0x400(%0); cache %1, 0x480(%0) \n" \
|
||||
" cache %1, 0x500(%0); cache %1, 0x580(%0) \n" \
|
||||
" cache %1, 0x600(%0); cache %1, 0x680(%0) \n" \
|
||||
" cache %1, 0x700(%0); cache %1, 0x780(%0) \n" \
|
||||
" cache %1, 0x800(%0); cache %1, 0x880(%0) \n" \
|
||||
" cache %1, 0x900(%0); cache %1, 0x980(%0) \n" \
|
||||
" cache %1, 0xa00(%0); cache %1, 0xa80(%0) \n" \
|
||||
" cache %1, 0xb00(%0); cache %1, 0xb80(%0) \n" \
|
||||
" cache %1, 0xc00(%0); cache %1, 0xc80(%0) \n" \
|
||||
" cache %1, 0xd00(%0); cache %1, 0xd80(%0) \n" \
|
||||
" cache %1, 0xe00(%0); cache %1, 0xe80(%0) \n" \
|
||||
" cache %1, 0xf00(%0); cache %1, 0xf80(%0) \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#else
|
||||
/*
|
||||
* MIPS R6 changed the cache opcode and moved to a 8-bit offset field.
|
||||
* This means we now need to increment the base register before we flush
|
||||
* more cache lines
|
||||
*/
|
||||
#define cache16_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push\n" \
|
||||
" .set noreorder\n" \
|
||||
" .set mips64r6\n" \
|
||||
" .set noat\n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x010(%0)\n" \
|
||||
" cache %1, 0x020(%0); cache %1, 0x030(%0)\n" \
|
||||
" cache %1, 0x040(%0); cache %1, 0x050(%0)\n" \
|
||||
" cache %1, 0x060(%0); cache %1, 0x070(%0)\n" \
|
||||
" cache %1, 0x080(%0); cache %1, 0x090(%0)\n" \
|
||||
" cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)\n" \
|
||||
" cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)\n" \
|
||||
" cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x010($1)\n" \
|
||||
" cache %1, 0x020($1); cache %1, 0x030($1)\n" \
|
||||
" cache %1, 0x040($1); cache %1, 0x050($1)\n" \
|
||||
" cache %1, 0x060($1); cache %1, 0x070($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x090($1)\n" \
|
||||
" cache %1, 0x0a0($1); cache %1, 0x0b0($1)\n" \
|
||||
" cache %1, 0x0c0($1); cache %1, 0x0d0($1)\n" \
|
||||
" cache %1, 0x0e0($1); cache %1, 0x0f0($1)\n" \
|
||||
" .set pop\n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache32_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push\n" \
|
||||
" .set noreorder\n" \
|
||||
" .set mips64r6\n" \
|
||||
" .set noat\n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x020(%0)\n" \
|
||||
" cache %1, 0x040(%0); cache %1, 0x060(%0)\n" \
|
||||
" cache %1, 0x080(%0); cache %1, 0x0a0(%0)\n" \
|
||||
" cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x020($1)\n" \
|
||||
" cache %1, 0x040($1); cache %1, 0x060($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \
|
||||
" cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x020($1)\n" \
|
||||
" cache %1, 0x040($1); cache %1, 0x060($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \
|
||||
" cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100\n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x020($1)\n" \
|
||||
" cache %1, 0x040($1); cache %1, 0x060($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0a0($1)\n" \
|
||||
" cache %1, 0x0c0($1); cache %1, 0x0e0($1)\n" \
|
||||
" .set pop\n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache64_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push\n" \
|
||||
" .set noreorder\n" \
|
||||
" .set mips64r6\n" \
|
||||
" .set noat\n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x040(%0)\n" \
|
||||
" cache %1, 0x080(%0); cache %1, 0x0c0(%0)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x040($1)\n" \
|
||||
" cache %1, 0x080($1); cache %1, 0x0c0($1)\n" \
|
||||
" .set pop\n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache128_unroll32(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push\n" \
|
||||
" .set noreorder\n" \
|
||||
" .set mips64r6\n" \
|
||||
" .set noat\n" \
|
||||
" cache %1, 0x000(%0); cache %1, 0x080(%0)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, %0, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" "__stringify(LONG_ADDIU)" $1, $1, 0x100 \n" \
|
||||
" cache %1, 0x000($1); cache %1, 0x080($1)\n" \
|
||||
" .set pop\n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
#endif /* CONFIG_CPU_MIPSR6 */
|
||||
|
||||
/*
|
||||
* Perform the cache operation specified by op using a user mode virtual
|
||||
* address while in kernel mode.
|
||||
*/
|
||||
#define cache16_unroll32_user(base,op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set mips0 \n" \
|
||||
" .set eva \n" \
|
||||
" cachee %1, 0x000(%0); cachee %1, 0x010(%0) \n" \
|
||||
" cachee %1, 0x020(%0); cachee %1, 0x030(%0) \n" \
|
||||
" cachee %1, 0x040(%0); cachee %1, 0x050(%0) \n" \
|
||||
" cachee %1, 0x060(%0); cachee %1, 0x070(%0) \n" \
|
||||
" cachee %1, 0x080(%0); cachee %1, 0x090(%0) \n" \
|
||||
" cachee %1, 0x0a0(%0); cachee %1, 0x0b0(%0) \n" \
|
||||
" cachee %1, 0x0c0(%0); cachee %1, 0x0d0(%0) \n" \
|
||||
" cachee %1, 0x0e0(%0); cachee %1, 0x0f0(%0) \n" \
|
||||
" cachee %1, 0x100(%0); cachee %1, 0x110(%0) \n" \
|
||||
" cachee %1, 0x120(%0); cachee %1, 0x130(%0) \n" \
|
||||
" cachee %1, 0x140(%0); cachee %1, 0x150(%0) \n" \
|
||||
" cachee %1, 0x160(%0); cachee %1, 0x170(%0) \n" \
|
||||
" cachee %1, 0x180(%0); cachee %1, 0x190(%0) \n" \
|
||||
" cachee %1, 0x1a0(%0); cachee %1, 0x1b0(%0) \n" \
|
||||
" cachee %1, 0x1c0(%0); cachee %1, 0x1d0(%0) \n" \
|
||||
" cachee %1, 0x1e0(%0); cachee %1, 0x1f0(%0) \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache32_unroll32_user(base, op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set mips0 \n" \
|
||||
" .set eva \n" \
|
||||
" cachee %1, 0x000(%0); cachee %1, 0x020(%0) \n" \
|
||||
" cachee %1, 0x040(%0); cachee %1, 0x060(%0) \n" \
|
||||
" cachee %1, 0x080(%0); cachee %1, 0x0a0(%0) \n" \
|
||||
" cachee %1, 0x0c0(%0); cachee %1, 0x0e0(%0) \n" \
|
||||
" cachee %1, 0x100(%0); cachee %1, 0x120(%0) \n" \
|
||||
" cachee %1, 0x140(%0); cachee %1, 0x160(%0) \n" \
|
||||
" cachee %1, 0x180(%0); cachee %1, 0x1a0(%0) \n" \
|
||||
" cachee %1, 0x1c0(%0); cachee %1, 0x1e0(%0) \n" \
|
||||
" cachee %1, 0x200(%0); cachee %1, 0x220(%0) \n" \
|
||||
" cachee %1, 0x240(%0); cachee %1, 0x260(%0) \n" \
|
||||
" cachee %1, 0x280(%0); cachee %1, 0x2a0(%0) \n" \
|
||||
" cachee %1, 0x2c0(%0); cachee %1, 0x2e0(%0) \n" \
|
||||
" cachee %1, 0x300(%0); cachee %1, 0x320(%0) \n" \
|
||||
" cachee %1, 0x340(%0); cachee %1, 0x360(%0) \n" \
|
||||
" cachee %1, 0x380(%0); cachee %1, 0x3a0(%0) \n" \
|
||||
" cachee %1, 0x3c0(%0); cachee %1, 0x3e0(%0) \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
|
||||
#define cache64_unroll32_user(base, op) \
|
||||
__asm__ __volatile__( \
|
||||
" .set push \n" \
|
||||
" .set noreorder \n" \
|
||||
" .set mips0 \n" \
|
||||
" .set eva \n" \
|
||||
" cachee %1, 0x000(%0); cachee %1, 0x040(%0) \n" \
|
||||
" cachee %1, 0x080(%0); cachee %1, 0x0c0(%0) \n" \
|
||||
" cachee %1, 0x100(%0); cachee %1, 0x140(%0) \n" \
|
||||
" cachee %1, 0x180(%0); cachee %1, 0x1c0(%0) \n" \
|
||||
" cachee %1, 0x200(%0); cachee %1, 0x240(%0) \n" \
|
||||
" cachee %1, 0x280(%0); cachee %1, 0x2c0(%0) \n" \
|
||||
" cachee %1, 0x300(%0); cachee %1, 0x340(%0) \n" \
|
||||
" cachee %1, 0x380(%0); cachee %1, 0x3c0(%0) \n" \
|
||||
" cachee %1, 0x400(%0); cachee %1, 0x440(%0) \n" \
|
||||
" cachee %1, 0x480(%0); cachee %1, 0x4c0(%0) \n" \
|
||||
" cachee %1, 0x500(%0); cachee %1, 0x540(%0) \n" \
|
||||
" cachee %1, 0x580(%0); cachee %1, 0x5c0(%0) \n" \
|
||||
" cachee %1, 0x600(%0); cachee %1, 0x640(%0) \n" \
|
||||
" cachee %1, 0x680(%0); cachee %1, 0x6c0(%0) \n" \
|
||||
" cachee %1, 0x700(%0); cachee %1, 0x740(%0) \n" \
|
||||
" cachee %1, 0x780(%0); cachee %1, 0x7c0(%0) \n" \
|
||||
" .set pop \n" \
|
||||
: \
|
||||
: "r" (base), \
|
||||
"i" (op));
|
||||
#define cache_unroll(times, insn, op, addr, lsize) do { \
|
||||
int i = 0; \
|
||||
unroll(times, _cache_op, insn, op, (addr) + (i++ * (lsize))); \
|
||||
} while (0)
|
||||
|
||||
/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
|
||||
#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \
|
||||
|
@ -539,7 +216,8 @@ static inline void extra##blast_##pfx##cache##lsize(void) \
|
|||
\
|
||||
for (ws = 0; ws < ws_end; ws += ws_inc) \
|
||||
for (addr = start; addr < end; addr += lsize * 32) \
|
||||
cache##lsize##_unroll32(addr|ws, indexop); \
|
||||
cache_unroll(32, kernel_cache, indexop, \
|
||||
addr | ws, lsize); \
|
||||
} \
|
||||
\
|
||||
static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
|
||||
|
@ -548,7 +226,7 @@ static inline void extra##blast_##pfx##cache##lsize##_page(unsigned long page) \
|
|||
unsigned long end = page + PAGE_SIZE; \
|
||||
\
|
||||
do { \
|
||||
cache##lsize##_unroll32(start, hitop); \
|
||||
cache_unroll(32, kernel_cache, hitop, start, lsize); \
|
||||
start += lsize * 32; \
|
||||
} while (start < end); \
|
||||
} \
|
||||
|
@ -565,7 +243,8 @@ static inline void extra##blast_##pfx##cache##lsize##_page_indexed(unsigned long
|
|||
\
|
||||
for (ws = 0; ws < ws_end; ws += ws_inc) \
|
||||
for (addr = start; addr < end; addr += lsize * 32) \
|
||||
cache##lsize##_unroll32(addr|ws, indexop); \
|
||||
cache_unroll(32, kernel_cache, indexop, \
|
||||
addr | ws, lsize); \
|
||||
}
|
||||
|
||||
__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
|
||||
|
@ -596,7 +275,7 @@ static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \
|
|||
unsigned long end = page + PAGE_SIZE; \
|
||||
\
|
||||
do { \
|
||||
cache##lsize##_unroll32_user(start, hitop); \
|
||||
cache_unroll(32, user_cache, hitop, start, lsize); \
|
||||
start += lsize * 32; \
|
||||
} while (start < end); \
|
||||
}
|
||||
|
@ -688,7 +367,8 @@ static inline void blast_##pfx##cache##lsize##_node(long node) \
|
|||
\
|
||||
for (ws = 0; ws < ws_end; ws += ws_inc) \
|
||||
for (addr = start; addr < end; addr += lsize * 32) \
|
||||
cache##lsize##_unroll32(addr|ws, indexop); \
|
||||
cache_unroll(32, kernel_cache, indexop, \
|
||||
addr | ws, lsize); \
|
||||
}
|
||||
|
||||
__BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
|
||||
|
|
|
@ -0,0 +1,272 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* HEART chip definitions
|
||||
*
|
||||
* Copyright (C) 2004-2007 Stanislaw Skowronek <skylark@unaligned.org>
|
||||
* 2009 Johannes Dickgreber <tanzy@gmx.de>
|
||||
* 2007-2015 Joshua Kinard <kumba@gentoo.org>
|
||||
*/
|
||||
#ifndef __ASM_SGI_HEART_H
|
||||
#define __ASM_SGI_HEART_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
/*
|
||||
* There are 8 DIMM slots on an IP30 system
|
||||
* board, which are grouped into four banks
|
||||
*/
|
||||
#define HEART_MEMORY_BANKS 4
|
||||
|
||||
/* HEART can support up to four CPUs */
|
||||
#define HEART_MAX_CPUS 4
|
||||
|
||||
#define HEART_XKPHYS_BASE ((void *)(IO_BASE | 0x000000000ff00000ULL))
|
||||
|
||||
/**
|
||||
* struct ip30_heart_regs - struct that maps IP30 HEART registers.
|
||||
* @mode: HEART_MODE - Purpose Unknown, machine reset called from here.
|
||||
* @sdram_mode: HEART_SDRAM_MODE - purpose unknown.
|
||||
* @mem_refresh: HEART_MEM_REF - purpose unknown.
|
||||
* @mem_req_arb: HEART_MEM_REQ_ARB - purpose unknown.
|
||||
* @mem_cfg.q: union for 64bit access to HEART_MEMCFG - 4x 64bit registers.
|
||||
* @mem_cfg.l: union for 32bit access to HEART_MEMCFG - 8x 32bit registers.
|
||||
* @fc_mode: HEART_FC_MODE - Purpose Unknown, possibly for GFX flow control.
|
||||
* @fc_timer_limit: HEART_FC_TIMER_LIMIT - purpose unknown.
|
||||
* @fc_addr: HEART_FC0_ADDR, HEART_FC1_ADDR - purpose unknown.
|
||||
* @fc_credit_cnt: HEART_FC0_CR_CNT, HEART_FC1_CR_CNT - purpose unknown.
|
||||
* @fc_timer: HEART_FC0_TIMER, HEART_FC1_TIMER - purpose unknown.
|
||||
* @status: HEART_STATUS - HEART status information.
|
||||
* @bus_err_addr: HEART_BERR_ADDR - likely contains addr of recent SIGBUS.
|
||||
* @bus_err_misc: HEART_BERR_MISC - purpose unknown.
|
||||
* @mem_err_addr: HEART_MEMERR_ADDR - likely contains addr of recent mem err.
|
||||
* @mem_err_data: HEART_MEMERR_DATA - purpose unknown.
|
||||
* @piur_acc_err: HEART_PIUR_ACC_ERR - likely for access err to HEART regs.
|
||||
* @mlan_clock_div: HEART_MLAN_CLK_DIV - MicroLAN clock divider.
|
||||
* @mlan_ctrl: HEART_MLAN_CTL - MicroLAN control.
|
||||
* @__pad0: 0x0f40 bytes of padding -> next HEART register 0x01000.
|
||||
* @undefined: Undefined/diag register, write to it triggers PIUR_ACC_ERR.
|
||||
* @__pad1: 0xeff8 bytes of padding -> next HEART register 0x10000.
|
||||
* @imr: HEART_IMR0 to HEART_IMR3 - per-cpu interrupt mask register.
|
||||
* @set_isr: HEART_SET_ISR - set interrupt status register.
|
||||
* @clear_isr: HEART_CLR_ISR - clear interrupt status register.
|
||||
* @isr: HEART_ISR - interrupt status register (read-only).
|
||||
* @imsr: HEART_IMSR - purpose unknown.
|
||||
* @cause: HEART_CAUSE - HEART cause information.
|
||||
* @__pad2: 0xffb8 bytes of padding -> next HEART register 0x20000.
|
||||
* @count: HEART_COUNT - 52-bit counter.
|
||||
* @__pad3: 0xfff8 bytes of padding -> next HEART register 0x30000.
|
||||
* @compare: HEART_COMPARE - 24-bit compare.
|
||||
* @__pad4: 0xfff8 bytes of padding -> next HEART register 0x40000.
|
||||
* @trigger: HEART_TRIGGER - purpose unknown.
|
||||
* @__pad5: 0xfff8 bytes of padding -> next HEART register 0x50000.
|
||||
* @cpuid: HEART_PRID - contains CPU ID of CPU currently accessing HEART.
|
||||
* @__pad6: 0xfff8 bytes of padding -> next HEART register 0x60000.
|
||||
* @sync: HEART_SYNC - purpose unknown.
|
||||
*
|
||||
* HEART is the main system controller ASIC for IP30 system. It incorporates
|
||||
* a memory controller, interrupt status/cause/set/clear management, basic
|
||||
* timer with count/compare, and other functionality. For Linux, not all of
|
||||
* HEART's functions are fully understood.
|
||||
*
|
||||
* Implementation note: All HEART registers are 64bits-wide, but the mem_cfg
|
||||
* register only reports correct values if queried in 32bits. Hence the need
|
||||
* for a union. Even though mem_cfg.l has 8 array slots, we only ever query
|
||||
* up to 4 of those. IP30 has 8 DIMM slots arranged into 4 banks, w/ 2 DIMMs
|
||||
* per bank. Each 32bit read accesses one of these banks. Perhaps HEART was
|
||||
* designed to address up to 8 banks (16 DIMMs)? We may never know.
|
||||
*/
|
||||
struct ip30_heart_regs { /* 0x0ff00000 */
|
||||
u64 mode; /* + 0x00000 */
|
||||
/* Memory */
|
||||
u64 sdram_mode; /* + 0x00008 */
|
||||
u64 mem_refresh; /* + 0x00010 */
|
||||
u64 mem_req_arb; /* + 0x00018 */
|
||||
union {
|
||||
u64 q[HEART_MEMORY_BANKS]; /* readq() */
|
||||
u32 l[HEART_MEMORY_BANKS * 2]; /* readl() */
|
||||
} mem_cfg; /* + 0x00020 */
|
||||
/* Flow control (gfx?) */
|
||||
u64 fc_mode; /* + 0x00040 */
|
||||
u64 fc_timer_limit; /* + 0x00048 */
|
||||
u64 fc_addr[2]; /* + 0x00050 */
|
||||
u64 fc_credit_cnt[2]; /* + 0x00060 */
|
||||
u64 fc_timer[2]; /* + 0x00070 */
|
||||
/* Status */
|
||||
u64 status; /* + 0x00080 */
|
||||
/* Bus error */
|
||||
u64 bus_err_addr; /* + 0x00088 */
|
||||
u64 bus_err_misc; /* + 0x00090 */
|
||||
/* Memory error */
|
||||
u64 mem_err_addr; /* + 0x00098 */
|
||||
u64 mem_err_data; /* + 0x000a0 */
|
||||
/* Misc */
|
||||
u64 piur_acc_err; /* + 0x000a8 */
|
||||
u64 mlan_clock_div; /* + 0x000b0 */
|
||||
u64 mlan_ctrl; /* + 0x000b8 */
|
||||
u64 __pad0[0x01e8]; /* + 0x000c0 + 0x0f40 */
|
||||
/* Undefined */
|
||||
u64 undefined; /* + 0x01000 */
|
||||
u64 __pad1[0x1dff]; /* + 0x01008 + 0xeff8 */
|
||||
/* Interrupts */
|
||||
u64 imr[HEART_MAX_CPUS]; /* + 0x10000 */
|
||||
u64 set_isr; /* + 0x10020 */
|
||||
u64 clear_isr; /* + 0x10028 */
|
||||
u64 isr; /* + 0x10030 */
|
||||
u64 imsr; /* + 0x10038 */
|
||||
u64 cause; /* + 0x10040 */
|
||||
u64 __pad2[0x1ff7]; /* + 0x10048 + 0xffb8 */
|
||||
/* Timer */
|
||||
u64 count; /* + 0x20000 */
|
||||
u64 __pad3[0x1fff]; /* + 0x20008 + 0xfff8 */
|
||||
u64 compare; /* + 0x30000 */
|
||||
u64 __pad4[0x1fff]; /* + 0x30008 + 0xfff8 */
|
||||
u64 trigger; /* + 0x40000 */
|
||||
u64 __pad5[0x1fff]; /* + 0x40008 + 0xfff8 */
|
||||
/* Misc */
|
||||
u64 cpuid; /* + 0x50000 */
|
||||
u64 __pad6[0x1fff]; /* + 0x50008 + 0xfff8 */
|
||||
u64 sync; /* + 0x60000 */
|
||||
};
|
||||
|
||||
|
||||
/* For timer-related bits. */
|
||||
#define HEART_NS_PER_CYCLE 80
|
||||
#define HEART_CYCLES_PER_SEC (NSEC_PER_SEC / HEART_NS_PER_CYCLE)
|
||||
|
||||
|
||||
/*
|
||||
* XXX: Everything below this comment will either go away or be cleaned
|
||||
* up to fit in better with Linux. A lot of the bit definitions for
|
||||
* HEART were derived from IRIX's sys/RACER/heart.h header file.
|
||||
*/
|
||||
|
||||
/* HEART Masks */
|
||||
#define HEART_ATK_MASK 0x0007ffffffffffff /* HEART attack mask */
|
||||
#define HEART_ACK_ALL_MASK 0xffffffffffffffff /* Ack everything */
|
||||
#define HEART_CLR_ALL_MASK 0x0000000000000000 /* Clear all */
|
||||
#define HEART_BR_ERR_MASK 0x7ff8000000000000 /* BRIDGE error mask */
|
||||
#define HEART_CPU0_ERR_MASK 0x8ff8000000000000 /* CPU0 error mask */
|
||||
#define HEART_CPU1_ERR_MASK 0x97f8000000000000 /* CPU1 error mask */
|
||||
#define HEART_CPU2_ERR_MASK 0xa7f8000000000000 /* CPU2 error mask */
|
||||
#define HEART_CPU3_ERR_MASK 0xc7f8000000000000 /* CPU3 error mask */
|
||||
#define HEART_ERR_MASK 0x1ff /* HEART error mask */
|
||||
#define HEART_ERR_MASK_START 51 /* HEART error start */
|
||||
#define HEART_ERR_MASK_END 63 /* HEART error end */
|
||||
|
||||
/* Bits in the HEART_MODE register. */
|
||||
#define HM_PROC_DISABLE_SHFT 60
|
||||
#define HM_PROC_DISABLE_MSK (0xfUL << HM_PROC_DISABLE_SHFT)
|
||||
#define HM_PROC_DISABLE(x) (0x1UL << (x) + HM_PROC_DISABLE_SHFT)
|
||||
#define HM_MAX_PSR (0x7UL << 57)
|
||||
#define HM_MAX_IOSR (0x7UL << 54)
|
||||
#define HM_MAX_PEND_IOSR (0x7UL << 51)
|
||||
#define HM_TRIG_SRC_SEL_MSK (0x7UL << 48)
|
||||
#define HM_TRIG_HEART_EXC (0x0UL << 48)
|
||||
#define HM_TRIG_REG_BIT (0x1UL << 48)
|
||||
#define HM_TRIG_SYSCLK (0x2UL << 48)
|
||||
#define HM_TRIG_MEMCLK_2X (0x3UL << 48)
|
||||
#define HM_TRIG_MEMCLK (0x4UL << 48)
|
||||
#define HM_TRIG_IOCLK (0x5UL << 48)
|
||||
#define HM_PIU_TEST_MODE (0xfUL << 40)
|
||||
#define HM_GP_FLAG_MSK (0xfUL << 36)
|
||||
#define HM_GP_FLAG(x) BIT((x) + 36)
|
||||
#define HM_MAX_PROC_HYST (0xfUL << 32)
|
||||
#define HM_LLP_WRST_AFTER_RST BIT(28)
|
||||
#define HM_LLP_LINK_RST BIT(27)
|
||||
#define HM_LLP_WARM_RST BIT(26)
|
||||
#define HM_COR_ECC_LCK BIT(25)
|
||||
#define HM_REDUCED_PWR BIT(24)
|
||||
#define HM_COLD_RST BIT(23)
|
||||
#define HM_SW_RST BIT(22)
|
||||
#define HM_MEM_FORCE_WR BIT(21)
|
||||
#define HM_DB_ERR_GEN BIT(20)
|
||||
#define HM_SB_ERR_GEN BIT(19)
|
||||
#define HM_CACHED_PIO_EN BIT(18)
|
||||
#define HM_CACHED_PROM_EN BIT(17)
|
||||
#define HM_PE_SYS_COR_ERE BIT(16)
|
||||
#define HM_GLOBAL_ECC_EN BIT(15)
|
||||
#define HM_IO_COH_EN BIT(14)
|
||||
#define HM_INT_EN BIT(13)
|
||||
#define HM_DATA_CHK_EN BIT(12)
|
||||
#define HM_REF_EN BIT(11)
|
||||
#define HM_BAD_SYSWR_ERE BIT(10)
|
||||
#define HM_BAD_SYSRD_ERE BIT(9)
|
||||
#define HM_SYSSTATE_ERE BIT(8)
|
||||
#define HM_SYSCMD_ERE BIT(7)
|
||||
#define HM_NCOR_SYS_ERE BIT(6)
|
||||
#define HM_COR_SYS_ERE BIT(5)
|
||||
#define HM_DATA_ELMNT_ERE BIT(4)
|
||||
#define HM_MEM_ADDR_PROC_ERE BIT(3)
|
||||
#define HM_MEM_ADDR_IO_ERE BIT(2)
|
||||
#define HM_NCOR_MEM_ERE BIT(1)
|
||||
#define HM_COR_MEM_ERE BIT(0)
|
||||
|
||||
/* Bits in the HEART_MEM_REF register. */
|
||||
#define HEART_MEMREF_REFS(x) ((0xfUL & (x)) << 16)
|
||||
#define HEART_MEMREF_PERIOD(x) ((0xffffUL & (x)))
|
||||
#define HEART_MEMREF_REFS_VAL HEART_MEMREF_REFS(8)
|
||||
#define HEART_MEMREF_PERIOD_VAL HEART_MEMREF_PERIOD(0x4000)
|
||||
#define HEART_MEMREF_VAL (HEART_MEMREF_REFS_VAL | \
|
||||
HEART_MEMREF_PERIOD_VAL)
|
||||
|
||||
/* Bits in the HEART_MEM_REQ_ARB register. */
|
||||
#define HEART_MEMARB_IODIS (1 << 20)
|
||||
#define HEART_MEMARB_MAXPMWRQS (15 << 16)
|
||||
#define HEART_MEMARB_MAXPMRRQS (15 << 12)
|
||||
#define HEART_MEMARB_MAXPMRQS (15 << 8)
|
||||
#define HEART_MEMARB_MAXRRRQS (15 << 4)
|
||||
#define HEART_MEMARB_MAXGBRRQS (15)
|
||||
|
||||
/* Bits in the HEART_MEMCFG<x> registers. */
|
||||
#define HEART_MEMCFG_VALID 0x80000000 /* Bank is valid */
|
||||
#define HEART_MEMCFG_DENSITY 0x01c00000 /* Mem density */
|
||||
#define HEART_MEMCFG_SIZE_MASK 0x003f0000 /* Mem size mask */
|
||||
#define HEART_MEMCFG_ADDR_MASK 0x000001ff /* Base addr mask */
|
||||
#define HEART_MEMCFG_SIZE_SHIFT 16 /* Mem size shift */
|
||||
#define HEART_MEMCFG_DENSITY_SHIFT 22 /* Density Shift */
|
||||
#define HEART_MEMCFG_UNIT_SHIFT 25 /* Unit Shift, 32MB */
|
||||
|
||||
/* Bits in the HEART_STATUS register */
|
||||
#define HEART_STAT_HSTL_SDRV BIT(14)
|
||||
#define HEART_STAT_FC_CR_OUT(x) BIT((x) + 12)
|
||||
#define HEART_STAT_DIR_CNNCT BIT(11)
|
||||
#define HEART_STAT_TRITON BIT(10)
|
||||
#define HEART_STAT_R4K BIT(9)
|
||||
#define HEART_STAT_BIG_ENDIAN BIT(8)
|
||||
#define HEART_STAT_PROC_SHFT 4
|
||||
#define HEART_STAT_PROC_MSK (0xfUL << HEART_STAT_PROC_SHFT)
|
||||
#define HEART_STAT_PROC_ACTIVE(x) (0x1UL << ((x) + HEART_STAT_PROC_SHFT))
|
||||
#define HEART_STAT_WIDGET_ID 0xf
|
||||
|
||||
/* Bits in the HEART_CAUSE register */
|
||||
#define HC_PE_SYS_COR_ERR_MSK (0xfUL << 60)
|
||||
#define HC_PE_SYS_COR_ERR(x) BIT((x) + 60)
|
||||
#define HC_PIOWDB_OFLOW BIT(44)
|
||||
#define HC_PIORWRB_OFLOW BIT(43)
|
||||
#define HC_PIUR_ACC_ERR BIT(42)
|
||||
#define HC_BAD_SYSWR_ERR BIT(41)
|
||||
#define HC_BAD_SYSRD_ERR BIT(40)
|
||||
#define HC_SYSSTATE_ERR_MSK (0xfUL << 36)
|
||||
#define HC_SYSSTATE_ERR(x) BIT((x) + 36)
|
||||
#define HC_SYSCMD_ERR_MSK (0xfUL << 32)
|
||||
#define HC_SYSCMD_ERR(x) BIT((x) + 32)
|
||||
#define HC_NCOR_SYSAD_ERR_MSK (0xfUL << 28)
|
||||
#define HC_NCOR_SYSAD_ERR(x) BIT((x) + 28)
|
||||
#define HC_COR_SYSAD_ERR_MSK (0xfUL << 24)
|
||||
#define HC_COR_SYSAD_ERR(x) BIT((x) + 24)
|
||||
#define HC_DATA_ELMNT_ERR_MSK (0xfUL << 20)
|
||||
#define HC_DATA_ELMNT_ERR(x) BIT((x) + 20)
|
||||
#define HC_WIDGET_ERR BIT(16)
|
||||
#define HC_MEM_ADDR_ERR_PROC_MSK (0xfUL << 4)
|
||||
#define HC_MEM_ADDR_ERR_PROC(x) BIT((x) + 4)
|
||||
#define HC_MEM_ADDR_ERR_IO BIT(2)
|
||||
#define HC_NCOR_MEM_ERR BIT(1)
|
||||
#define HC_COR_MEM_ERR BIT(0)
|
||||
|
||||
extern struct ip30_heart_regs __iomem *heart_regs;
|
||||
|
||||
#define heart_read ____raw_readq
|
||||
#define heart_write ____raw_writeq
|
||||
|
||||
#endif /* __ASM_SGI_HEART_H */
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* sgi.h: Definitions specific to SGI machines.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (dm@sgi.com)
|
||||
*/
|
||||
#ifndef _ASM_SGI_SGI_H
|
||||
#define _ASM_SGI_SGI_H
|
||||
|
||||
/* UP=UniProcessor MP=MultiProcessor(capable) */
|
||||
enum sgi_mach {
|
||||
ip4, /* R2k UP */
|
||||
ip5, /* R2k MP */
|
||||
ip6, /* R3k UP */
|
||||
ip7, /* R3k MP */
|
||||
ip9, /* R3k UP */
|
||||
ip12, /* R3kA UP, Indigo */
|
||||
ip15, /* R3kA MP */
|
||||
ip17, /* R4K UP */
|
||||
ip19, /* R4K MP */
|
||||
ip20, /* R4K UP, Indigo */
|
||||
ip21, /* R8k/TFP MP */
|
||||
ip22, /* R4x00 UP, Indy, Indigo2 */
|
||||
ip25, /* R10k MP */
|
||||
ip26, /* R8k/TFP UP, Indigo2 */
|
||||
ip27, /* R10k MP, R12k MP, R14k MP, Origin 200/2k, Onyx2 */
|
||||
ip28, /* R10k UP, Indigo2 Impact R10k */
|
||||
ip30, /* R10k MP, R12k MP, R14k MP, Octane */
|
||||
ip32, /* R5k UP, RM5200 UP, RM7k UP, R10k UP, R12k UP, O2 */
|
||||
ip35, /* R14k MP, R16k MP, Origin 300/3k, Onyx3, Fuel, Tezro */
|
||||
};
|
||||
|
||||
extern enum sgi_mach sgimach;
|
||||
extern void sgi_sysinit(void);
|
||||
|
||||
/* Many I/O space registers are byte sized and are contained within
|
||||
* one byte per word, specifically the MSB, this macro helps out.
|
||||
*/
|
||||
#ifdef __MIPSEL__
|
||||
#define SGI_MSB(regaddr) (regaddr)
|
||||
#else
|
||||
#define SGI_MSB(regaddr) ((regaddr) | 0x3)
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_SGI_SGI_H */
|
|
@ -15,14 +15,6 @@
|
|||
#include <asm/sgiarcs.h>
|
||||
|
||||
extern struct linux_romvec *romvec;
|
||||
extern int prom_argc;
|
||||
|
||||
extern LONG *_prom_argv, *_prom_envp;
|
||||
|
||||
/* A 32-bit ARC PROM pass arguments and environment as 32-bit pointer.
|
||||
These macros take care of sign extension. */
|
||||
#define prom_argv(index) ((char *) (long) _prom_argv[(index)])
|
||||
#define prom_argc(index) ((char *) (long) _prom_argc[(index)])
|
||||
|
||||
extern int prom_flags;
|
||||
|
||||
|
@ -47,12 +39,6 @@ extern void prom_meminit(void);
|
|||
/* PROM device tree library routines. */
|
||||
#define PROM_NULL_COMPONENT ((pcomponent *) 0)
|
||||
|
||||
/* Get sibling component of THIS. */
|
||||
extern pcomponent *ArcGetPeer(pcomponent *this);
|
||||
|
||||
/* Get child component of THIS. */
|
||||
extern pcomponent *ArcGetChild(pcomponent *this);
|
||||
|
||||
/* This is called at prom_init time to identify the
|
||||
* ARC architecture we are running on
|
||||
*/
|
||||
|
@ -60,22 +46,16 @@ extern void prom_identify_arch(void);
|
|||
|
||||
/* Environment variable routines. */
|
||||
extern PCHAR ArcGetEnvironmentVariable(PCHAR name);
|
||||
extern LONG ArcSetEnvironmentVariable(PCHAR name, PCHAR value);
|
||||
|
||||
/* ARCS command line parsing. */
|
||||
extern void prom_init_cmdline(void);
|
||||
extern void prom_init_cmdline(int argc, LONG *argv);
|
||||
|
||||
/* File operations. */
|
||||
extern LONG ArcRead(ULONG fd, PVOID buf, ULONG num, PULONG cnt);
|
||||
extern LONG ArcWrite(ULONG fd, PVOID buf, ULONG num, PULONG cnt);
|
||||
|
||||
/* Misc. routines. */
|
||||
extern VOID ArcHalt(VOID) __noreturn;
|
||||
extern VOID ArcPowerDown(VOID) __noreturn;
|
||||
extern VOID ArcRestart(VOID) __noreturn;
|
||||
extern VOID ArcReboot(VOID) __noreturn;
|
||||
extern VOID ArcEnterInteractiveMode(VOID) __noreturn;
|
||||
extern VOID ArcFlushAllCaches(VOID);
|
||||
extern DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID);
|
||||
|
||||
#endif /* _ASM_SGIALIB_H */
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef _ASM_SGIARCS_H
|
||||
#define _ASM_SGIARCS_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <asm/fw/arc/types.h>
|
||||
|
||||
|
@ -368,110 +370,65 @@ struct linux_smonblock {
|
|||
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_FW_ARC32)
|
||||
|
||||
#define __arc_clobbers \
|
||||
"$2", "$3" /* ... */, "$8", "$9", "$10", "$11", \
|
||||
"$12", "$13", "$14", "$15", "$16", "$24", "$25", "$31"
|
||||
extern long call_o32(long vec, void *stack, ...);
|
||||
|
||||
extern u64 o32_stk[4096];
|
||||
#define O32_STK (&o32_stk[ARRAY_SIZE(o32_stk)])
|
||||
|
||||
#define ARC_CALL0(dest) \
|
||||
({ long __res; \
|
||||
long __vec = (long) romvec->dest; \
|
||||
__asm__ __volatile__( \
|
||||
"dsubu\t$29, 32\n\t" \
|
||||
"jalr\t%1\n\t" \
|
||||
"daddu\t$29, 32\n\t" \
|
||||
"move\t%0, $2" \
|
||||
: "=r" (__res), "=r" (__vec) \
|
||||
: "1" (__vec) \
|
||||
: __arc_clobbers, "$4", "$5", "$6", "$7"); \
|
||||
(unsigned long) __res; \
|
||||
__res = call_o32(__vec, O32_STK); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
#define ARC_CALL1(dest, a1) \
|
||||
({ long __res; \
|
||||
register signed int __a1 __asm__("$4") = (int) (long) (a1); \
|
||||
int __a1 = (int) (long) (a1); \
|
||||
long __vec = (long) romvec->dest; \
|
||||
__asm__ __volatile__( \
|
||||
"dsubu\t$29, 32\n\t" \
|
||||
"jalr\t%1\n\t" \
|
||||
"daddu\t$29, 32\n\t" \
|
||||
"move\t%0, $2" \
|
||||
: "=r" (__res), "=r" (__vec) \
|
||||
: "1" (__vec), "r" (__a1) \
|
||||
: __arc_clobbers, "$5", "$6", "$7"); \
|
||||
(unsigned long) __res; \
|
||||
__res = call_o32(__vec, O32_STK, __a1); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
#define ARC_CALL2(dest, a1, a2) \
|
||||
({ long __res; \
|
||||
register signed int __a1 __asm__("$4") = (int) (long) (a1); \
|
||||
register signed int __a2 __asm__("$5") = (int) (long) (a2); \
|
||||
int __a1 = (int) (long) (a1); \
|
||||
int __a2 = (int) (long) (a2); \
|
||||
long __vec = (long) romvec->dest; \
|
||||
__asm__ __volatile__( \
|
||||
"dsubu\t$29, 32\n\t" \
|
||||
"jalr\t%1\n\t" \
|
||||
"daddu\t$29, 32\n\t" \
|
||||
"move\t%0, $2" \
|
||||
: "=r" (__res), "=r" (__vec) \
|
||||
: "1" (__vec), "r" (__a1), "r" (__a2) \
|
||||
: __arc_clobbers, "$6", "$7"); \
|
||||
__res = call_o32(__vec, O32_STK, __a1, __a2); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
#define ARC_CALL3(dest, a1, a2, a3) \
|
||||
({ long __res; \
|
||||
register signed int __a1 __asm__("$4") = (int) (long) (a1); \
|
||||
register signed int __a2 __asm__("$5") = (int) (long) (a2); \
|
||||
register signed int __a3 __asm__("$6") = (int) (long) (a3); \
|
||||
int __a1 = (int) (long) (a1); \
|
||||
int __a2 = (int) (long) (a2); \
|
||||
int __a3 = (int) (long) (a3); \
|
||||
long __vec = (long) romvec->dest; \
|
||||
__asm__ __volatile__( \
|
||||
"dsubu\t$29, 32\n\t" \
|
||||
"jalr\t%1\n\t" \
|
||||
"daddu\t$29, 32\n\t" \
|
||||
"move\t%0, $2" \
|
||||
: "=r" (__res), "=r" (__vec) \
|
||||
: "1" (__vec), "r" (__a1), "r" (__a2), "r" (__a3) \
|
||||
: __arc_clobbers, "$7"); \
|
||||
__res = call_o32(__vec, O32_STK, __a1, __a2, __a3); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
#define ARC_CALL4(dest, a1, a2, a3, a4) \
|
||||
({ long __res; \
|
||||
register signed int __a1 __asm__("$4") = (int) (long) (a1); \
|
||||
register signed int __a2 __asm__("$5") = (int) (long) (a2); \
|
||||
register signed int __a3 __asm__("$6") = (int) (long) (a3); \
|
||||
register signed int __a4 __asm__("$7") = (int) (long) (a4); \
|
||||
int __a1 = (int) (long) (a1); \
|
||||
int __a2 = (int) (long) (a2); \
|
||||
int __a3 = (int) (long) (a3); \
|
||||
int __a4 = (int) (long) (a4); \
|
||||
long __vec = (long) romvec->dest; \
|
||||
__asm__ __volatile__( \
|
||||
"dsubu\t$29, 32\n\t" \
|
||||
"jalr\t%1\n\t" \
|
||||
"daddu\t$29, 32\n\t" \
|
||||
"move\t%0, $2" \
|
||||
: "=r" (__res), "=r" (__vec) \
|
||||
: "1" (__vec), "r" (__a1), "r" (__a2), "r" (__a3), \
|
||||
"r" (__a4) \
|
||||
: __arc_clobbers); \
|
||||
__res = call_o32(__vec, O32_STK, __a1, __a2, __a3, __a4); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
#define ARC_CALL5(dest, a1, a2, a3, a4, a5) \
|
||||
#define ARC_CALL5(dest, a1, a2, a3, a4, a5) \
|
||||
({ long __res; \
|
||||
register signed int __a1 __asm__("$4") = (int) (long) (a1); \
|
||||
register signed int __a2 __asm__("$5") = (int) (long) (a2); \
|
||||
register signed int __a3 __asm__("$6") = (int) (long) (a3); \
|
||||
register signed int __a4 __asm__("$7") = (int) (long) (a4); \
|
||||
register signed int __a5 = (int) (long) (a5); \
|
||||
int __a1 = (int) (long) (a1); \
|
||||
int __a2 = (int) (long) (a2); \
|
||||
int __a3 = (int) (long) (a3); \
|
||||
int __a4 = (int) (long) (a4); \
|
||||
int __a5 = (int) (long) (a5); \
|
||||
long __vec = (long) romvec->dest; \
|
||||
__asm__ __volatile__( \
|
||||
"dsubu\t$29, 32\n\t" \
|
||||
"sw\t%7, 16($29)\n\t" \
|
||||
"jalr\t%1\n\t" \
|
||||
"daddu\t$29, 32\n\t" \
|
||||
"move\t%0, $2" \
|
||||
: "=r" (__res), "=r" (__vec) \
|
||||
: "1" (__vec), \
|
||||
"r" (__a1), "r" (__a2), "r" (__a3), "r" (__a4), \
|
||||
"r" (__a5) \
|
||||
: __arc_clobbers); \
|
||||
__res = call_o32(__vec, O32_STK, __a1, __a2, __a3, __a4, __a5); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#if defined(CONFIG_SGI_IP27)
|
||||
#define HUB_NIC_ADDR(_cpuid) \
|
||||
REMOTE_HUB_ADDR(COMPACT_TO_NASID_NODEID(cpu_to_node(_cpuid)), \
|
||||
REMOTE_HUB_ADDR(cpu_to_node(_cpuid), \
|
||||
MD_MLAN_CTL)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -19,44 +19,13 @@
|
|||
|
||||
#define cputonasid(cpu) (sn_cpu_info[(cpu)].p_nasid)
|
||||
#define cputoslice(cpu) (sn_cpu_info[(cpu)].p_slice)
|
||||
#define makespnum(_nasid, _slice) \
|
||||
(((_nasid) << CPUS_PER_NODE_SHFT) | (_slice))
|
||||
|
||||
#define INVALID_NASID (nasid_t)-1
|
||||
#define INVALID_CNODEID (cnodeid_t)-1
|
||||
#define INVALID_PNODEID (pnodeid_t)-1
|
||||
#define INVALID_MODULE (moduleid_t)-1
|
||||
#define INVALID_PARTID (partid_t)-1
|
||||
|
||||
extern nasid_t get_nasid(void);
|
||||
extern cnodeid_t get_cpu_cnode(cpuid_t);
|
||||
extern int get_cpu_slice(cpuid_t);
|
||||
|
||||
/*
|
||||
* NO ONE should access these arrays directly. The only reason we refer to
|
||||
* them here is to avoid the procedure call that would be required in the
|
||||
* macros below. (Really want private data members here :-)
|
||||
*/
|
||||
extern cnodeid_t nasid_to_compact_node[MAX_NASIDS];
|
||||
extern nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
|
||||
|
||||
/*
|
||||
* These macros are used by various parts of the kernel to convert
|
||||
* between the three different kinds of node numbering. At least some
|
||||
* of them may change to procedure calls in the future, but the macros
|
||||
* will continue to work. Don't use the arrays above directly.
|
||||
*/
|
||||
|
||||
#define NASID_TO_REGION(nnode) \
|
||||
((nnode) >> \
|
||||
(is_fine_dirmode() ? NASID_TO_FINEREG_SHFT : NASID_TO_COARSEREG_SHFT))
|
||||
|
||||
extern cnodeid_t nasid_to_compact_node[MAX_NASIDS];
|
||||
extern nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
|
||||
extern cnodeid_t cpuid_to_compact_node[MAXCPUS];
|
||||
|
||||
#define NASID_TO_COMPACT_NODEID(nnode) (nasid_to_compact_node[nnode])
|
||||
#define COMPACT_TO_NASID_NODEID(cnode) (compact_to_nasid_node[cnode])
|
||||
#define CPUID_TO_COMPACT_NODEID(cpu) (cpuid_to_compact_node[(cpu)])
|
||||
|
||||
#endif /* _ASM_SN_ARCH_H */
|
||||
|
|
|
@ -60,9 +60,7 @@ typedef struct gda {
|
|||
/* Pointer to a mask of nodes with copies
|
||||
* of the kernel. */
|
||||
char g_padding[56]; /* pad out to 128 bytes */
|
||||
nasid_t g_nasidtable[MAX_COMPACT_NODES]; /* NASID of each node,
|
||||
* indexed by cnodeid.
|
||||
*/
|
||||
nasid_t g_nasidtable[MAX_NUMNODES]; /* NASID of each node */
|
||||
} gda_t;
|
||||
|
||||
#define GDA ((gda_t*) GDA_ADDR(get_nasid()))
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#include <asm/xtalk/xtalk.h>
|
||||
|
||||
/* ip27-hubio.c */
|
||||
extern unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
|
||||
extern unsigned long hub_pio_map(nasid_t nasid, xwidgetnum_t widget,
|
||||
unsigned long xtalk_addr, size_t size);
|
||||
extern void hub_pio_init(cnodeid_t cnode);
|
||||
extern void hub_pio_init(nasid_t nasid);
|
||||
|
||||
#endif /* __ASM_SN_HUB_H */
|
||||
|
|
|
@ -590,4 +590,13 @@ struct ioc3_etxd {
|
|||
|
||||
#define MIDR_DATA_MASK 0x0000ffff
|
||||
|
||||
/* subsystem IDs supplied by card detection in pci-xtalk-bridge */
|
||||
#define IOC3_SUBSYS_IP27_BASEIO6G 0xc300
|
||||
#define IOC3_SUBSYS_IP27_MIO 0xc301
|
||||
#define IOC3_SUBSYS_IP27_BASEIO 0xc302
|
||||
#define IOC3_SUBSYS_IP29_SYSBOARD 0xc303
|
||||
#define IOC3_SUBSYS_IP30_SYSBOARD 0xc304
|
||||
#define IOC3_SUBSYS_MENET 0xc305
|
||||
#define IOC3_SUBSYS_MENET4 0xc306
|
||||
|
||||
#endif /* MIPS_SN_IOC3_H */
|
||||
|
|
|
@ -37,10 +37,10 @@
|
|||
|
||||
#define MAPPED_KERN_RO_TO_PHYS(x) \
|
||||
((unsigned long)MAPPED_ADDR_RO_TO_PHYS(x) | \
|
||||
MAPPED_KERN_RO_PHYSBASE(get_compact_nodeid()))
|
||||
MAPPED_KERN_RO_PHYSBASE(get_nasid()))
|
||||
#define MAPPED_KERN_RW_TO_PHYS(x) \
|
||||
((unsigned long)MAPPED_ADDR_RW_TO_PHYS(x) | \
|
||||
MAPPED_KERN_RW_PHYSBASE(get_compact_nodeid()))
|
||||
MAPPED_KERN_RW_PHYSBASE(get_nasid()))
|
||||
|
||||
#else /* CONFIG_MAPPED_KERNEL */
|
||||
|
||||
|
|
|
@ -12,25 +12,11 @@
|
|||
#define _ASM_SN_SN0_ARCH_H
|
||||
|
||||
|
||||
#ifndef SN0XXL /* 128 cpu SMP max */
|
||||
/*
|
||||
* This is the maximum number of nodes that can be part of a kernel.
|
||||
* Effectively, it's the maximum number of compact node ids (cnodeid_t).
|
||||
*/
|
||||
#define MAX_COMPACT_NODES 64
|
||||
|
||||
/*
|
||||
* MAXCPUS refers to the maximum number of CPUs in a single kernel.
|
||||
* This is not necessarily the same as MAXNODES * CPUS_PER_NODE
|
||||
*/
|
||||
#define MAXCPUS 128
|
||||
|
||||
#else /* SN0XXL system */
|
||||
|
||||
#define MAX_COMPACT_NODES 128
|
||||
#define MAXCPUS 256
|
||||
|
||||
#endif /* SN0XXL */
|
||||
#define MAXCPUS (MAX_NUMNODES * CPUS_PER_NODE)
|
||||
|
||||
/*
|
||||
* This is the maximum number of NASIDS that can be present in a system.
|
||||
|
@ -66,7 +52,5 @@
|
|||
#define SLOT_MIN_MEM_SIZE (32*1024*1024)
|
||||
|
||||
#define CPUS_PER_NODE 2 /* CPUs on a single hub */
|
||||
#define CPUS_PER_NODE_SHFT 1 /* Bits to shift in the node number */
|
||||
#define CPUS_PER_SUBNODE 2 /* CPUs on a single hub PI */
|
||||
|
||||
#endif /* _ASM_SN_SN0_ARCH_H */
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
extern nasid_t master_nasid;
|
||||
|
||||
extern void cpu_node_probe(void);
|
||||
extern cnodeid_t get_compact_nodeid(void);
|
||||
extern void hub_rtc_init(cnodeid_t);
|
||||
extern void hub_rtc_init(nasid_t nasid);
|
||||
extern void cpu_time_init(void);
|
||||
extern void per_cpu_init(void);
|
||||
extern void install_cpu_nmi_handler(int slice);
|
||||
extern void install_ipi(void);
|
||||
extern void setup_replication_mask(void);
|
||||
extern void replicate_kernel_text(void);
|
||||
extern unsigned long node_getfirstfree(cnodeid_t);
|
||||
extern unsigned long node_getfirstfree(nasid_t nasid);
|
||||
|
||||
#endif /* __ASM_SN_SN_PRIVATE_H */
|
||||
|
|
|
@ -12,13 +12,9 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
typedef unsigned long cpuid_t;
|
||||
typedef unsigned long cnodemask_t;
|
||||
typedef signed short nasid_t; /* node id in numa-as-id space */
|
||||
typedef signed short cnodeid_t; /* node id in compact-id space */
|
||||
typedef signed char partid_t; /* partition ID type */
|
||||
typedef signed short moduleid_t; /* user-visible module number type */
|
||||
typedef signed short cmoduleid_t; /* kernel compact module id type */
|
||||
typedef unsigned char clusterid_t; /* Clusterid of the cell */
|
||||
|
||||
typedef dev_t vertex_hdl_t; /* hardware graph vertex handle */
|
||||
|
||||
|
|
|
@ -10,127 +10,6 @@
|
|||
#ifndef _ASM_STRING_H
|
||||
#define _ASM_STRING_H
|
||||
|
||||
|
||||
/*
|
||||
* Most of the inline functions are rather naive implementations so I just
|
||||
* didn't bother updating them for 64-bit ...
|
||||
*/
|
||||
#ifdef CONFIG_32BIT
|
||||
|
||||
#ifndef IN_STRING_C
|
||||
|
||||
#define __HAVE_ARCH_STRCPY
|
||||
static __inline__ char *strcpy(char *__dest, __const__ char *__src)
|
||||
{
|
||||
char *__xdest = __dest;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".set\tnoreorder\n\t"
|
||||
".set\tnoat\n"
|
||||
"1:\tlbu\t$1,(%1)\n\t"
|
||||
"addiu\t%1,1\n\t"
|
||||
"sb\t$1,(%0)\n\t"
|
||||
"bnez\t$1,1b\n\t"
|
||||
"addiu\t%0,1\n\t"
|
||||
".set\tat\n\t"
|
||||
".set\treorder"
|
||||
: "=r" (__dest), "=r" (__src)
|
||||
: "0" (__dest), "1" (__src)
|
||||
: "memory");
|
||||
|
||||
return __xdest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRNCPY
|
||||
static __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n)
|
||||
{
|
||||
char *__xdest = __dest;
|
||||
|
||||
if (__n == 0)
|
||||
return __xdest;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".set\tnoreorder\n\t"
|
||||
".set\tnoat\n"
|
||||
"1:\tlbu\t$1,(%1)\n\t"
|
||||
"subu\t%2,1\n\t"
|
||||
"sb\t$1,(%0)\n\t"
|
||||
"beqz\t$1,2f\n\t"
|
||||
"addiu\t%0,1\n\t"
|
||||
"bnez\t%2,1b\n\t"
|
||||
"addiu\t%1,1\n"
|
||||
"2:\n\t"
|
||||
".set\tat\n\t"
|
||||
".set\treorder"
|
||||
: "=r" (__dest), "=r" (__src), "=r" (__n)
|
||||
: "0" (__dest), "1" (__src), "2" (__n)
|
||||
: "memory");
|
||||
|
||||
return __xdest;
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_STRCMP
|
||||
static __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct)
|
||||
{
|
||||
int __res;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".set\tnoreorder\n\t"
|
||||
".set\tnoat\n\t"
|
||||
"lbu\t%2,(%0)\n"
|
||||
"1:\tlbu\t$1,(%1)\n\t"
|
||||
"addiu\t%0,1\n\t"
|
||||
"bne\t$1,%2,2f\n\t"
|
||||
"addiu\t%1,1\n\t"
|
||||
"bnez\t%2,1b\n\t"
|
||||
"lbu\t%2,(%0)\n\t"
|
||||
#if defined(CONFIG_CPU_R3000)
|
||||
"nop\n\t"
|
||||
#endif
|
||||
"move\t%2,$1\n"
|
||||
"2:\tsubu\t%2,$1\n"
|
||||
"3:\t.set\tat\n\t"
|
||||
".set\treorder"
|
||||
: "=r" (__cs), "=r" (__ct), "=r" (__res)
|
||||
: "0" (__cs), "1" (__ct));
|
||||
|
||||
return __res;
|
||||
}
|
||||
|
||||
#endif /* !defined(IN_STRING_C) */
|
||||
|
||||
#define __HAVE_ARCH_STRNCMP
|
||||
static __inline__ int
|
||||
strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count)
|
||||
{
|
||||
int __res;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".set\tnoreorder\n\t"
|
||||
".set\tnoat\n"
|
||||
"1:\tlbu\t%3,(%0)\n\t"
|
||||
"beqz\t%2,2f\n\t"
|
||||
"lbu\t$1,(%1)\n\t"
|
||||
"subu\t%2,1\n\t"
|
||||
"bne\t$1,%3,3f\n\t"
|
||||
"addiu\t%0,1\n\t"
|
||||
"bnez\t%3,1b\n\t"
|
||||
"addiu\t%1,1\n"
|
||||
"2:\n\t"
|
||||
#if defined(CONFIG_CPU_R3000)
|
||||
"nop\n\t"
|
||||
#endif
|
||||
"move\t%3,$1\n"
|
||||
"3:\tsubu\t%3,$1\n\t"
|
||||
".set\tat\n\t"
|
||||
".set\treorder"
|
||||
: "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res)
|
||||
: "0" (__cs), "1" (__ct), "2" (__count));
|
||||
|
||||
return __res;
|
||||
}
|
||||
#endif /* CONFIG_32BIT */
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
extern void *memset(void *__s, int __c, size_t __count);
|
||||
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __MIPS_ASM_SYNC_H__
|
||||
#define __MIPS_ASM_SYNC_H__
|
||||
|
||||
/*
|
||||
* sync types are defined by the MIPS64 Instruction Set documentation in Volume
|
||||
* II-A of the MIPS Architecture Reference Manual, which can be found here:
|
||||
*
|
||||
* https://www.mips.com/?do-download=the-mips64-instruction-set-v6-06
|
||||
*
|
||||
* Two types of barrier are provided:
|
||||
*
|
||||
* 1) Completion barriers, which ensure that a memory operation has actually
|
||||
* completed & often involve stalling the CPU pipeline to do so.
|
||||
*
|
||||
* 2) Ordering barriers, which only ensure that affected memory operations
|
||||
* won't be reordered in the CPU pipeline in a manner that violates the
|
||||
* restrictions imposed by the barrier.
|
||||
*
|
||||
* Ordering barriers can be more efficient than completion barriers, since:
|
||||
*
|
||||
* a) Ordering barriers only require memory access instructions which preceed
|
||||
* them in program order (older instructions) to reach a point in the
|
||||
* load/store datapath beyond which reordering is not possible before
|
||||
* allowing memory access instructions which follow them (younger
|
||||
* instructions) to be performed. That is, older instructions don't
|
||||
* actually need to complete - they just need to get far enough that all
|
||||
* other coherent CPUs will observe their completion before they observe
|
||||
* the effects of younger instructions.
|
||||
*
|
||||
* b) Multiple variants of ordering barrier are provided which allow the
|
||||
* effects to be restricted to different combinations of older or younger
|
||||
* loads or stores. By way of example, if we only care that stores older
|
||||
* than a barrier are observed prior to stores that are younger than a
|
||||
* barrier & don't care about the ordering of loads then the 'wmb'
|
||||
* ordering barrier can be used. Limiting the barrier's effects to stores
|
||||
* allows loads to continue unaffected & potentially allows the CPU to
|
||||
* make progress faster than if younger loads had to wait for older stores
|
||||
* to complete.
|
||||
*/
|
||||
|
||||
/*
|
||||
* No sync instruction at all; used to allow code to nullify the effect of the
|
||||
* __SYNC() macro without needing lots of #ifdefery.
|
||||
*/
|
||||
#define __SYNC_none -1
|
||||
|
||||
/*
|
||||
* A full completion barrier; all memory accesses appearing prior to this sync
|
||||
* instruction in program order must complete before any memory accesses
|
||||
* appearing after this sync instruction in program order.
|
||||
*/
|
||||
#define __SYNC_full 0x00
|
||||
|
||||
/*
|
||||
* For now we use a full completion barrier to implement all sync types, until
|
||||
* we're satisfied that lightweight ordering barriers defined by MIPSr6 are
|
||||
* sufficient to uphold our desired memory model.
|
||||
*/
|
||||
#define __SYNC_aq __SYNC_full
|
||||
#define __SYNC_rl __SYNC_full
|
||||
#define __SYNC_mb __SYNC_full
|
||||
|
||||
/*
|
||||
* ...except on Cavium Octeon CPUs, which have been using the 'wmb' ordering
|
||||
* barrier since 2010 & omit 'rmb' barriers because the CPUs don't perform
|
||||
* speculative reads.
|
||||
*/
|
||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||
# define __SYNC_rmb __SYNC_none
|
||||
# define __SYNC_wmb 0x04
|
||||
#else
|
||||
# define __SYNC_rmb __SYNC_full
|
||||
# define __SYNC_wmb __SYNC_full
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A GINV sync is a little different; it doesn't relate directly to loads or
|
||||
* stores, but instead causes synchronization of an icache or TLB global
|
||||
* invalidation operation triggered by the ginvi or ginvt instructions
|
||||
* respectively. In cases where we need to know that a ginvi or ginvt operation
|
||||
* has been performed by all coherent CPUs, we must issue a sync instruction of
|
||||
* this type. Once this instruction graduates all coherent CPUs will have
|
||||
* observed the invalidation.
|
||||
*/
|
||||
#define __SYNC_ginv 0x14
|
||||
|
||||
/* Trivial; indicate that we always need this sync instruction. */
|
||||
#define __SYNC_always (1 << 0)
|
||||
|
||||
/*
|
||||
* Indicate that we need this sync instruction only on systems with weakly
|
||||
* ordered memory access. In general this is most MIPS systems, but there are
|
||||
* exceptions which provide strongly ordered memory.
|
||||
*/
|
||||
#ifdef CONFIG_WEAK_ORDERING
|
||||
# define __SYNC_weak_ordering (1 << 1)
|
||||
#else
|
||||
# define __SYNC_weak_ordering 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Indicate that we need this sync instruction only on systems where LL/SC
|
||||
* don't implicitly provide a memory barrier. In general this is most MIPS
|
||||
* systems.
|
||||
*/
|
||||
#ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC
|
||||
# define __SYNC_weak_llsc (1 << 2)
|
||||
#else
|
||||
# define __SYNC_weak_llsc 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some Loongson 3 CPUs have a bug wherein execution of a memory access (load,
|
||||
* store or prefetch) in between an LL & SC can cause the SC instruction to
|
||||
* erroneously succeed, breaking atomicity. Whilst it's unusual to write code
|
||||
* containing such sequences, this bug bites harder than we might otherwise
|
||||
* expect due to reordering & speculation:
|
||||
*
|
||||
* 1) A memory access appearing prior to the LL in program order may actually
|
||||
* be executed after the LL - this is the reordering case.
|
||||
*
|
||||
* In order to avoid this we need to place a memory barrier (ie. a SYNC
|
||||
* instruction) prior to every LL instruction, in between it and any earlier
|
||||
* memory access instructions.
|
||||
*
|
||||
* This reordering case is fixed by 3A R2 CPUs, ie. 3A2000 models and later.
|
||||
*
|
||||
* 2) If a conditional branch exists between an LL & SC with a target outside
|
||||
* of the LL-SC loop, for example an exit upon value mismatch in cmpxchg()
|
||||
* or similar, then misprediction of the branch may allow speculative
|
||||
* execution of memory accesses from outside of the LL-SC loop.
|
||||
*
|
||||
* In order to avoid this we need a memory barrier (ie. a SYNC instruction)
|
||||
* at each affected branch target.
|
||||
*
|
||||
* This case affects all current Loongson 3 CPUs.
|
||||
*
|
||||
* The above described cases cause an error in the cache coherence protocol;
|
||||
* such that the Invalidate of a competing LL-SC goes 'missing' and SC
|
||||
* erroneously observes its core still has Exclusive state and lets the SC
|
||||
* proceed.
|
||||
*
|
||||
* Therefore the error only occurs on SMP systems.
|
||||
*/
|
||||
#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS
|
||||
# define __SYNC_loongson3_war (1 << 31)
|
||||
#else
|
||||
# define __SYNC_loongson3_war 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some Cavium Octeon CPUs suffer from a bug that causes a single wmb ordering
|
||||
* barrier to be ineffective, requiring the use of 2 in sequence to provide an
|
||||
* effective barrier as noted by commit 6b07d38aaa52 ("MIPS: Octeon: Use
|
||||
* optimized memory barrier primitives."). Here we specify that the affected
|
||||
* sync instructions should be emitted twice.
|
||||
*/
|
||||
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||
# define __SYNC_rpt(type) (1 + (type == __SYNC_wmb))
|
||||
#else
|
||||
# define __SYNC_rpt(type) 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The main event. Here we actually emit a sync instruction of a given type, if
|
||||
* reason is non-zero.
|
||||
*
|
||||
* In future we have the option of emitting entries in a fixups-style table
|
||||
* here that would allow us to opportunistically remove some sync instructions
|
||||
* when we detect at runtime that we're running on a CPU that doesn't need
|
||||
* them.
|
||||
*/
|
||||
#ifdef CONFIG_CPU_HAS_SYNC
|
||||
# define ____SYNC(_type, _reason, _else) \
|
||||
.if (( _type ) != -1) && ( _reason ); \
|
||||
.set push; \
|
||||
.set MIPS_ISA_LEVEL_RAW; \
|
||||
.rept __SYNC_rpt(_type); \
|
||||
sync _type; \
|
||||
.endr; \
|
||||
.set pop; \
|
||||
.else; \
|
||||
_else; \
|
||||
.endif
|
||||
#else
|
||||
# define ____SYNC(_type, _reason, _else)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Preprocessor magic to expand macros used as arguments before we insert them
|
||||
* into assembly code.
|
||||
*/
|
||||
#ifdef __ASSEMBLY__
|
||||
# define ___SYNC(type, reason, else) \
|
||||
____SYNC(type, reason, else)
|
||||
#else
|
||||
# define ___SYNC(type, reason, else) \
|
||||
__stringify(____SYNC(type, reason, else))
|
||||
#endif
|
||||
|
||||
#define __SYNC(type, reason) \
|
||||
___SYNC(__SYNC_##type, __SYNC_##reason, )
|
||||
#define __SYNC_ELSE(type, reason, else) \
|
||||
___SYNC(__SYNC_##type, __SYNC_##reason, else)
|
||||
|
||||
#endif /* __MIPS_ASM_SYNC_H__ */
|
|
@ -0,0 +1,77 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __ASM_UNROLL_H__
|
||||
#define __ASM_UNROLL_H__
|
||||
|
||||
/*
|
||||
* Explicitly unroll a loop, for use in cases where doing so is performance
|
||||
* critical.
|
||||
*
|
||||
* Ideally we'd rely upon the compiler to provide this but there's no commonly
|
||||
* available means to do so. For example GCC's "#pragma GCC unroll"
|
||||
* functionality would be ideal but is only available from GCC 8 onwards. Using
|
||||
* -funroll-loops is an option but GCC tends to make poor choices when
|
||||
* compiling our string functions. -funroll-all-loops leads to massive code
|
||||
* bloat, even if only applied to the string functions.
|
||||
*/
|
||||
#define unroll(times, fn, ...) do { \
|
||||
extern void bad_unroll(void) \
|
||||
__compiletime_error("Unsupported unroll"); \
|
||||
\
|
||||
/* \
|
||||
* We can't unroll if the number of iterations isn't \
|
||||
* compile-time constant. Unfortunately GCC versions \
|
||||
* up until 4.6 tend to miss obvious constants & cause \
|
||||
* this check to fail, even though they go on to \
|
||||
* generate reasonable code for the switch statement, \
|
||||
* so we skip the sanity check for those compilers. \
|
||||
*/ \
|
||||
BUILD_BUG_ON((CONFIG_GCC_VERSION >= 40700 || \
|
||||
CONFIG_CLANG_VERSION >= 80000) && \
|
||||
!__builtin_constant_p(times)); \
|
||||
\
|
||||
switch (times) { \
|
||||
case 32: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 31: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 30: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 29: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 28: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 27: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 26: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 25: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 24: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 23: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 22: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 21: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 20: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 19: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 18: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 17: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 16: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 15: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 14: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 13: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 12: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 11: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 10: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 9: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 8: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 7: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 6: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 5: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 4: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 3: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 2: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 1: fn(__VA_ARGS__); /* fall through */ \
|
||||
case 0: break; \
|
||||
\
|
||||
default: \
|
||||
/* \
|
||||
* Either the iteration count is unreasonable \
|
||||
* or we need to add more cases above. \
|
||||
*/ \
|
||||
bad_unroll(); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* __ASM_UNROLL_H__ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue