Skip to contentSkip to conversation

Add Cavium OCTEON processor support (v2).

PATCH In review David Daney 8 participants 84 messages Oct 27, 2008 – Nov 4, 2008 Page 1 of 2

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover Add Cavium OCTEON processor support (v2).

This patch set introduces preliminary support for Cavium Networks' OCTEON processor family. More information about these processors may be obtained here:

http://www.caviumnetworks.com/OCTEON_MIPS64.html

This initial patch set adds support for booting an initramfs to a serial console. Follow-on patch sets will add support for the on-chip ethernet, USB, PCI, PCIe, I2c and other peripherals.

With this second version of the patches I think we have fixed or removed the parts flagged as objectionable in the first round of reviews. In addition to more general cleanups I fixed the following issues:

* externs declared in mm/fault.c moved to fpu_emulator.h

* Corrected spelling of hazard in patch commentary.

* Useless checking in pmd_none removed.

* ebase calculation generalized.

* ST0_KX setting for 32bit kernel removed (there is now no 32bit kernel support)

Without further ado, I will reply with the following 36 patches (5 of which will also go to linux-serial):

01 - Add Cavium OCTEON processor support files to arch/mips/cavium-octeon. 02 - Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon 03 - Add Cavium OCTEON processor support files to arch/mips/kernel. 04 - Add Cavium OCTEON processor support files to arch/mips/mm. 05 - Add Cavium OCTEON processor support files to and
arch/mips/cavium-octeon/executive
06 - Add Cavium OCTEON processor CSR definitions
07 - Don't assume boot CPU is CPU0 if MIPS_DISABLE_BOOT_CPU_ZERO set. 08 - For Cavium OCTEON handle hazards as per the R10000 handling. 09 - Enable mips32 style bitops for Cavium OCTEON.
10 - Cavium OCTEON: Set hwrena and lazily restore CP2 state. 11 - MIPSR2 ebase isn't just CAC_BASE
12 - Add Cavium OCTEON to arch/mips/Kconfig
13 - Add Cavium OCTEON processor constants.
14 - Rewrite cpu_to_name so it has one statement per line.
15 - Probe for Cavium OCTEON CPUs.
16 - MIPS: Hook Cavium OCTEON cache init into cache.c
17 - cavium: Hook Cavium specifics into main arch/mips dir
18 - Cavium OCTEON modify core io.h macros to account for the Octeon
Errata Core-301.
19 - Cavium OCTEON: increase MAX_DMA address.
20 - Cavium OCTEON: add in icache and dcache error functions. 21 - Cavium OCTEON: Add cop2/cvmseg state entries to processor.h. 22 - Add Cavium OCTEON specific registers to ptrace.h and asm-offsets.c 23 - Add SMP_ICACHE_FLUSH for the Cavium CPU family.
24 - Cavium OCTEON: PT vs MFC0 reorder, multiplier state preservation. 25 - Add Cavium OCTEON irq hazard in asmmacro.h.
26 - Compute branch returns for Cavium OCTEON specific branch
instructions.
27 - Add Cavium OCTEON slot into proper tlb category.
28 - MIPS: move FPU emulator externs to fpu_emulator.h
29 - Cavium OCTEON FPU EMU exception as TLB exception

These five to linux-serial, linux-kernel, and akpm as well:
30 - Don't clobber spinlocks in 8250.
31 - Generic 8250 serial driver changes to support future OCTEON serial
patches.
32 - Allow port type to be specified when calling
serial8250_register_port.
33 - Allow port type to specify bugs that are not probed for. 34 - 8250 serial driver changes for Cavium OCTEON.

35 - Adjust the dma-common.c platform hooks.
36 - Add defconfig for Cavium OCTEON.

arch/mips/Kconfig                                  |   74 +-
arch/mips/Makefile                                 |   13 +
arch/mips/cavium-octeon/Kconfig                    |   85 +
arch/mips/cavium-octeon/Makefile                   |   21 +
arch/mips/cavium-octeon/console.c                  |   34 +
arch/mips/cavium-octeon/dma-octeon.c               |  324 +
arch/mips/cavium-octeon/executive/Makefile         |   26 +
arch/mips/cavium-octeon/executive/cvmx-asm.h       |  427 +
arch/mips/cavium-octeon/executive/cvmx-bootinfo.h  |  238 +
arch/mips/cavium-octeon/executive/cvmx-bootmem.c   |  897 +
arch/mips/cavium-octeon/executive/cvmx-bootmem.h   |  403 +
.../cavium-octeon/executive/cvmx-csr-addresses.h   | 8391 ++++++
arch/mips/cavium-octeon/executive/cvmx-csr-enums.h |   86 +
.../cavium-octeon/executive/cvmx-csr-typedefs.h    |27517 ++++++++++++++++++++
arch/mips/cavium-octeon/executive/cvmx-csr.h       |  199 +
arch/mips/cavium-octeon/executive/cvmx-interrupt.h |  255 +
arch/mips/cavium-octeon/executive/cvmx-l2c.c       |  711 +
arch/mips/cavium-octeon/executive/cvmx-l2c.h       |  328 +
.../executive/cvmx-linux-kernel-exports.c          |   30 +
arch/mips/cavium-octeon/executive/cvmx-packet.h    |   64 +
arch/mips/cavium-octeon/executive/cvmx-platform.h  |   56 +
arch/mips/cavium-octeon/executive/cvmx-spinlock.h  |  376 +
arch/mips/cavium-octeon/executive/cvmx-sysinfo.c   |  113 +
arch/mips/cavium-octeon/executive/cvmx-sysinfo.h   |  144 +
arch/mips/cavium-octeon/executive/cvmx-warn.c      |   44 +
arch/mips/cavium-octeon/executive/cvmx-warn.h      |   46 +
arch/mips/cavium-octeon/executive/cvmx.h           |  772 +
arch/mips/cavium-octeon/executive/octeon-feature.h |  120 +
arch/mips/cavium-octeon/executive/octeon-model.c   |  328 +
arch/mips/cavium-octeon/executive/octeon-model.h   |  225 +
arch/mips/cavium-octeon/flash_setup.c              |   76 +
arch/mips/cavium-octeon/hal.c                      |  496 +
arch/mips/cavium-octeon/hal.h                      |  190 +
arch/mips/cavium-octeon/i8259.c                    |  180 +
arch/mips/cavium-octeon/irq.c                      |   61 +
arch/mips/cavium-octeon/octeon-memcpy.S            |  521 +
arch/mips/cavium-octeon/serial.c                   |  187 +
arch/mips/cavium-octeon/setup.c                    |  387 +
arch/mips/cavium-octeon/smp.c                      |  231 +
arch/mips/cavium-octeon/userio.c                   |  156 +
arch/mips/configs/cavium-octeon_defconfig          | 1160 +
arch/mips/include/asm/asmmacro.h                   |   10 +
arch/mips/include/asm/bitops.h                     |    3 +-
arch/mips/include/asm/cpu-features.h               |    7 +
arch/mips/include/asm/cpu.h                        |   14 +
arch/mips/include/asm/dma.h                        |    7 +
arch/mips/include/asm/fpu_emulator.h               |    5 +
arch/mips/include/asm/hazards.h                    |    4 +-
arch/mips/include/asm/io.h                         |   14 +
.../asm/mach-cavium-octeon/cpu-feature-overrides.h |   63 +
.../include/asm/mach-cavium-octeon/dma-coherence.h |   64 +
arch/mips/include/asm/mach-cavium-octeon/irq.h     |  253 +
.../asm/mach-cavium-octeon/kernel-entry-init.h     |  140 +
.../asm/mach-cavium-octeon/octeon-hal-read-write.h |   38 +
arch/mips/include/asm/mach-cavium-octeon/war.h     |   26 +
arch/mips/include/asm/mach-generic/dma-coherence.h |   26 +-
arch/mips/include/asm/mach-ip27/dma-coherence.h    |   26 +-
arch/mips/include/asm/mach-ip32/dma-coherence.h    |   26 +-
arch/mips/include/asm/mach-jazz/dma-coherence.h    |   26 +-
arch/mips/include/asm/mach-lemote/dma-coherence.h  |   26 +-
arch/mips/include/asm/mipsregs.h                   |    5 +
arch/mips/include/asm/module.h                     |    2 +
arch/mips/include/asm/processor.h                  |   69 +
arch/mips/include/asm/ptrace.h                     |    4 +
arch/mips/include/asm/smp.h                        |    3 +
arch/mips/include/asm/stackframe.h                 |   46 +
arch/mips/kernel/Makefile                          |    9 +
arch/mips/kernel/asm-offsets.c                     |   31 +
arch/mips/kernel/branch.c                          |   33 +
arch/mips/kernel/cpu-probe.c                       |  182 +-
arch/mips/kernel/irq-octeon.c                      |  464 +
arch/mips/kernel/octeon_switch.S                   |  506 +
arch/mips/kernel/smp.c                             |    2 +
arch/mips/kernel/traps.c                           |   34 +-
arch/mips/kernel/unaligned.c                       |    2 +-
arch/mips/lib/Makefile                             |    1 +
arch/mips/math-emu/dsemul.h                        |    1 -
arch/mips/mm/Makefile                              |    5 +
arch/mips/mm/c-octeon.c                            |  309 +
arch/mips/mm/cache.c                               |    6 +
arch/mips/mm/cex-oct.S                             |   70 +
arch/mips/mm/dma-default.c                         |   24 +-
arch/mips/mm/fault.c                               |   16 +
arch/mips/mm/tlbex.c                               |    1 +
drivers/serial/8250.c                              |  233 +-
drivers/serial/8250.h                              |    3 +
drivers/serial/serial_core.c                       |    7 +-
include/linux/serial_8250.h                        |    2 +
include/linux/serial_core.h                        |    7 +-
include/linux/serial_reg.h                         |    6 +
90 files changed, 48682 insertions(+), 171 deletions(-)

create mode 100644 arch/mips/cavium-octeon/Kconfig
create mode 100644 arch/mips/cavium-octeon/Makefile
create mode 100644 arch/mips/cavium-octeon/console.c
create mode 100644 arch/mips/cavium-octeon/dma-octeon.c
create mode 100644 arch/mips/cavium-octeon/executive/Makefile
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-asm.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootinfo.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.c create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-addresses.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-enums.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-typedefs.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-interrupt.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-linux-kernel-exports.c create mode 100644 arch/mips/cavium-octeon/executive/cvmx-packet.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-platform.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-spinlock.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.c create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.h create mode 100644 arch/mips/cavium-octeon/executive/cvmx.h
create mode 100644 arch/mips/cavium-octeon/executive/octeon-feature.h create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.c create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.h create mode 100644 arch/mips/cavium-octeon/flash_setup.c
create mode 100644 arch/mips/cavium-octeon/hal.c
create mode 100644 arch/mips/cavium-octeon/hal.h
create mode 100644 arch/mips/cavium-octeon/i8259.c
create mode 100644 arch/mips/cavium-octeon/irq.c
create mode 100644 arch/mips/cavium-octeon/octeon-memcpy.S
create mode 100644 arch/mips/cavium-octeon/serial.c
create mode 100644 arch/mips/cavium-octeon/setup.c
create mode 100644 arch/mips/cavium-octeon/smp.c
create mode 100644 arch/mips/cavium-octeon/userio.c
create mode 100644 arch/mips/configs/cavium-octeon_defconfig
create mode 100644 arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h create mode 100644 arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h create mode 100644 arch/mips/include/asm/mach-cavium-octeon/irq.h create mode 100644 arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h create mode 100644 arch/mips/include/asm/mach-cavium-octeon/octeon-hal-read-write.h create mode 100644 arch/mips/include/asm/mach-cavium-octeon/war.h create mode 100644 arch/mips/kernel/irq-octeon.c
create mode 100644 arch/mips/kernel/octeon_switch.S
create mode 100644 arch/mips/mm/c-octeon.c
create mode 100644 arch/mips/mm/cex-oct.S

#1 lore raw

PATCH 1/36 Add Cavium OCTEON processor support files to arch/mips/cavium-octeon.

---
 arch/mips/cavium-octeon/Kconfig         |   85 +++++
 arch/mips/cavium-octeon/Makefile        |   21 ++
 arch/mips/cavium-octeon/console.c       |   34 ++
 arch/mips/cavium-octeon/dma-octeon.c    |  324 +++++++++++++++++++
 arch/mips/cavium-octeon/flash_setup.c   |   76 +++++
 arch/mips/cavium-octeon/hal.c           |  496 +++++++++++++++++++++++++++++
 arch/mips/cavium-octeon/hal.h           |  190 +++++++++++
 arch/mips/cavium-octeon/i8259.c         |  180 +++++++++++
 arch/mips/cavium-octeon/irq.c           |   61 ++++
 arch/mips/cavium-octeon/octeon-memcpy.S |  521 +++++++++++++++++++++++++++++++
 arch/mips/cavium-octeon/serial.c        |  187 +++++++++++
 arch/mips/cavium-octeon/setup.c         |  387 +++++++++++++++++++++++
 arch/mips/cavium-octeon/smp.c           |  231 ++++++++++++++
 arch/mips/cavium-octeon/userio.c        |  156 +++++++++
 14 files changed, 2949 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/cavium-octeon/Kconfig
 create mode 100644 arch/mips/cavium-octeon/Makefile
 create mode 100644 arch/mips/cavium-octeon/console.c
 create mode 100644 arch/mips/cavium-octeon/dma-octeon.c
 create mode 100644 arch/mips/cavium-octeon/flash_setup.c
 create mode 100644 arch/mips/cavium-octeon/hal.c
 create mode 100644 arch/mips/cavium-octeon/hal.h
 create mode 100644 arch/mips/cavium-octeon/i8259.c
 create mode 100644 arch/mips/cavium-octeon/irq.c
 create mode 100644 arch/mips/cavium-octeon/octeon-memcpy.S
 create mode 100644 arch/mips/cavium-octeon/serial.c
 create mode 100644 arch/mips/cavium-octeon/setup.c
 create mode 100644 arch/mips/cavium-octeon/smp.c
 create mode 100644 arch/mips/cavium-octeon/userio.c
arch/mips/cavium-octeon/Kconfig new file +85 -0
new file mode 100644
index 0000000..094c17e
@@ -0,0 +1,85 @@
+config CAVIUM_OCTEON_SPECIFIC_OPTIONS
+	bool "Enable Octeon specific options"
+	depends on CPU_CAVIUM_OCTEON
+	default "y"
+
+config CAVIUM_OCTEON_2ND_KERNEL
+	bool "Build the kernel to be used as a 2nd kernel on the same chip"
+	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+	default "n"
+	help
+	  This option configures this kernel to be linked at a different
+	  address and use the 2nd uart for output. This allows a kernel built
+	  with this option to be run at the same time as one built without this
+	  option.
+
+config CAVIUM_OCTEON_HW_FIX_UNALIGNED
+	bool "Enable hardware fixups of unaligned loads and stores"
+	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+	default "y"
+	help
+	  Configure the Octeon hardware to automatically fix unaligned loads
+	  and stores. Normally unaligned accesses are fixed using a kernel
+	  exception handler. This option enables the hardware automatic fixups,
+	  which requires only an extra 3 cycles. Disable this option if you
+	  are running code that relies on address exceptions on unaligned
+	  accesses.
+
+config CAVIUM_OCTEON_CVMSEG_SIZE
+	int "Number of L1 cache lines reserved for CVMSEG memory"
+	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+	range 0 54
+	default 1
+	help
+	  CVMSEG LM is a segment that accesses portions of the dcache as a
+	  local memory; the larger CVMSEG is, the smaller the cache is.
+	  This selects the size of CVMSEG LM, which is in cache blocks. The
+	  legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
+	  between zero and 6192 bytes).
+
+config CAVIUM_OCTEON_LOCK_L2
+	bool "Lock often used kernel code in the L2"
+	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+	default "y"
+	help
+	  Enable locking parts of the kernel into the L2 cache.
+
+config CAVIUM_OCTEON_LOCK_L2_TLB
+	bool "Lock the TLB handler in L2"
+	depends on CAVIUM_OCTEON_LOCK_L2
+	default "y"
+	help
+	  Lock the low level TLB fast path into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_EXCEPTION
+	bool "Lock the exception handler in L2"
+	depends on CAVIUM_OCTEON_LOCK_L2
+	default "y"
+	help
+	  Lock the low level exception handler into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT
+	bool "Lock the interrupt handler in L2"
+	depends on CAVIUM_OCTEON_LOCK_L2
+	default "y"
+	help
+	  Lock the low level interrupt handler into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_INTERRUPT
+	bool "Lock the 2nd level interrupt handler in L2"
+	depends on CAVIUM_OCTEON_LOCK_L2
+	default "y"
+	help
+	  Lock the 2nd level interrupt handler in L2.
+
+config CAVIUM_OCTEON_LOCK_L2_MEMCPY
+	bool "Lock memcpy() in L2"
+	depends on CAVIUM_OCTEON_LOCK_L2
+	default "y"
+	help
+	  Lock the kernel's implementation of memcpy() into L2.
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	select SPARSEMEM_STATIC
+	depends on CPU_CAVIUM_OCTEON
arch/mips/cavium-octeon/Makefile new file +21 -0
new file mode 100644
index 0000000..43d5a98
@@ -0,0 +1,21 @@
+#
+# Makefile for the Cavium Octeon specific kernel interface routines
+# under Linux.
+#
+# 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) 2005-2007 Cavium Networks
+#
+
+OCTEON_ROOT = $(srctree)/arch/mips/cavium-octeon
+EXTRA_CFLAGS +=	-I$(OCTEON_ROOT)/executive/config \
+		-I$(OCTEON_ROOT)/executive
+
+obj-y := setup.o serial.o irq.o hal.o
+obj-y += dma-octeon.o userio.o flash_setup.o
+obj-y += octeon-memcpy.o
+obj-y += console.o
+
+obj-$(CONFIG_SMP)                     += smp.o
arch/mips/cavium-octeon/console.c new file +34 -0
new file mode 100644
index 0000000..492a190
@@ -0,0 +1,34 @@
+/*
+ * Carsten Langgaard, [email protected]
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include "hal.h"
+
+int prom_putchar(char c)
+{
+	uint64_t lsrval;
+
+	/* Spin until there is room */
+	do {
+		lsrval = cvmx_read_csr(CVMX_MIO_UARTX_LSR(0));
+	} while ((lsrval & 0x20) == 0);
+
+	/* Write the byte */
+	cvmx_write_csr(CVMX_MIO_UARTX_THR(0), c);
+	return 1;
+}
arch/mips/cavium-octeon/dma-octeon.c new file +324 -0

324 lines not on this page · raw message

arch/mips/cavium-octeon/flash_setup.c new file +76 -0

76 lines not on this page · raw message

arch/mips/cavium-octeon/hal.c new file +496 -0

496 lines not on this page · raw message

arch/mips/cavium-octeon/hal.h new file +190 -0

190 lines not on this page · raw message

arch/mips/cavium-octeon/i8259.c new file +180 -0

180 lines not on this page · raw message

arch/mips/cavium-octeon/irq.c new file +61 -0

61 lines not on this page · raw message

arch/mips/cavium-octeon/octeon-memcpy.S new file +521 -0

521 lines not on this page · raw message

arch/mips/cavium-octeon/serial.c new file +187 -0

187 lines not on this page · raw message

arch/mips/cavium-octeon/setup.c new file +387 -0

387 lines not on this page · raw message

arch/mips/cavium-octeon/smp.c new file +231 -0

231 lines not on this page · raw message

arch/mips/cavium-octeon/userio.c new file +156 -0

156 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#2 lore raw

PATCH 2/36 Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

---
 .../asm/mach-cavium-octeon/cpu-feature-overrides.h |   63 +++++
 .../include/asm/mach-cavium-octeon/dma-coherence.h |   64 +++++
 arch/mips/include/asm/mach-cavium-octeon/irq.h     |  253 ++++++++++++++++++++
 .../asm/mach-cavium-octeon/kernel-entry-init.h     |  140 +++++++++++
 .../asm/mach-cavium-octeon/octeon-hal-read-write.h |   38 +++
 arch/mips/include/asm/mach-cavium-octeon/war.h     |   26 ++
 6 files changed, 584 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
 create mode 100644 arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
 create mode 100644 arch/mips/include/asm/mach-cavium-octeon/irq.h
 create mode 100644 arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
 create mode 100644 arch/mips/include/asm/mach-cavium-octeon/octeon-hal-read-write.h
 create mode 100644 arch/mips/include/asm/mach-cavium-octeon/war.h
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h new file +63 -0
new file mode 100644
index 0000000..2b85565
@@ -0,0 +1,63 @@
+/*
+ * 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 Cavium Networks
+ */
+#ifndef __ASM_MACH_CAVIUM_OCTEON_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_CAVIUM_OCTEON_CPU_FEATURE_OVERRIDES_H
+
+#include <linux/types.h>
+#include <asm/mipsregs.h>
+
+/*
+ * Cavium Octeons are MIPS64v2 processors
+ */
+#define cpu_dcache_line_size()	128
+#define cpu_icache_line_size()	128
+
+#ifdef CONFIG_SMP
+#define cpu_has_llsc		1
+#else
+/* Disable LL/SC on non SMP systems. It is faster to disable interrupts for
+   atomic access than a LL/SC */
+#define cpu_has_llsc		0
+#endif
+#define cpu_has_prefetch  	1
+#define cpu_has_dc_aliases      0
+#define cpu_has_fpu             0
+#define cpu_has_64bits          1
+#define cpu_has_octeon_cache    1
+#define cpu_has_4k_cache	0
+#define cpu_has_saa             octeon_has_saa()
+#define cpu_has_mips64r2        1
+#define cpu_has_counter         1
+#define ARCH_HAS_READ_CURRENT_TIMER 1
+#define ARCH_HAS_IRQ_PER_CPU 1
+#define ARCH_HAS_SPINLOCK_PREFETCH 1
+#define spin_lock_prefetch(x) prefetch(x)
+#define PREFETCH_STRIDE 128
+
+static inline int read_current_timer(unsigned long *result)
+{
+	asm volatile ("rdhwr %0,$31\n"
+#ifndef CONFIG_64BIT
+		      "sll %0, 0\n"
+#endif
+		      : "=r" (*result));
+	return 0;
+}
+
+static inline int octeon_has_saa(void)
+{
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+	int id;
+	asm volatile ("mfc0 %0, $15,0" : "=r" (id));
+	return id >= 0x000d0300;
+#else
+	return 0;
+#endif
+}
+
+#endif
arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h new file +64 -0

64 lines not on this page · raw message

arch/mips/include/asm/mach-cavium-octeon/irq.h new file +253 -0

253 lines not on this page · raw message

arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h new file +140 -0

140 lines not on this page · raw message

arch/mips/include/asm/mach-cavium-octeon/octeon-hal-read-write.h new file +38 -0
new file mode 100644
index 0000000..8c1dfc8
@@ -0,0 +1,38 @@
+/*
+ * 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-2007 Cavium Networks
+ */
+#ifndef __CAVIUM_OCTEON_HAL_READ_WRITE_H__
+#define __CAVIUM_OCTEON_HAL_READ_WRITE_H__
+
+#include "cvmx.h"
+
+
+/**
+ * Write a 32bit value to the Octeon NPI register space
+ *
+ * @param address Address to write to
+ * @param val     Value to write
+ */
+static inline void octeon_npi_write32(uint64_t address, uint32_t val)
+{
+	cvmx_write64_uint32(address ^ 4, val);
+	cvmx_read64_uint32(address ^ 4);
+}
+
+
+/**
+ * Read a 32bit value from the Octeon NPI register space
+ *
+ * @param address Address to read
+ * @return The result
+ */
+static inline uint32_t octeon_npi_read32(uint64_t address)
+{
+	return cvmx_read64_uint32(address ^ 4);
+}
+
+#endif
arch/mips/include/asm/mach-cavium-octeon/war.h new file +26 -0
new file mode 100644
index 0000000..c4712d7
@@ -0,0 +1,26 @@
+/*
+ * 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) 2002, 2004, 2007 by Ralf Baechle <[email protected]>
+ * Copyright (C) 2008 Cavium Networks <[email protected]>
+ */
+#ifndef __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H
+#define __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#define R4600_V1_HIT_CACHEOP_WAR	0
+#define R4600_V2_HIT_CACHEOP_WAR	0
+#define R5432_CP0_INTERRUPT_WAR		0
+#define BCM1250_M3_WAR			0
+#define SIBYTE_1956_WAR			0
+#define MIPS4K_ICACHE_REFILL_WAR	0
+#define MIPS_CACHE_SYNC_WAR		0
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#define RM9000_CDEX_SMP_WAR		0
+#define ICACHE_REFILLS_WORKAROUND_WAR	0
+#define R10000_LLSC_WAR			0
+#define MIPS34K_MISSED_ITLB_WAR		0
+
+#endif /* __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H */
Signature · 1 line
1.5.6.5
#3 lore raw

PATCH 3/36 Add Cavium OCTEON processor support files to arch/mips/kernel.

---
 arch/mips/kernel/irq-octeon.c    |  464 ++++++++++++++++++++++++++++++++++
 arch/mips/kernel/octeon_switch.S |  506 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 970 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/kernel/irq-octeon.c
 create mode 100644 arch/mips/kernel/octeon_switch.S
arch/mips/kernel/irq-octeon.c new file +464 -0
new file mode 100644
index 0000000..738f3c6
@@ -0,0 +1,464 @@
+/*
+ * 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-2007 Cavium Networks
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include "../cavium-octeon/hal.h"
+
+DEFINE_RWLOCK(octeon_irq_ciu0_rwlock);
+DEFINE_RWLOCK(octeon_irq_ciu1_rwlock);
+DEFINE_SPINLOCK(octeon_irq_msi_lock);
+
+static void octeon_irq_core_ack(unsigned int irq)
+{
+	/* We don't need to disable IRQs to make these atomic since they are
+	   already disabled earlier in the low level interrupt code */
+	clear_c0_status(0x100 << irq);
+	/* The two user interrupts must be cleared manually */
+	if (irq < 2)
+		clear_c0_cause(0x100 << irq);
+}
+
+static void octeon_irq_core_eoi(unsigned int irq)
+{
+	irq_desc_t *desc = irq_desc + irq;
+	/* If an IRQ is being processed while we are disabling it the handler
+	   will attempt to unmask the interrupt after it has been disabled */
+	if (desc->status & IRQ_DISABLED)
+		return;
+	/* We don't need to disable IRQs to make these atomic since they are
+	   already disabled earlier in the low level interrupt code */
+	set_c0_status(0x100 << irq);
+}
+
+static void octeon_irq_core_enable(unsigned int irq)
+{
+	/* We need to disable interrupts to make sure our updates are atomic */
+	unsigned long flags;
+	local_irq_save(flags);
+	set_c0_status(0x100 << irq);
+	local_irq_restore(flags);
+}
+
+static void octeon_irq_core_disable_local(unsigned int irq)
+{
+	/* We need to disable interrupts to make sure our updates are atomic */
+	unsigned long flags;
+	local_irq_save(flags);
+	clear_c0_status(0x100 << irq);
+	local_irq_restore(flags);
+}
+
+static void octeon_irq_core_disable(unsigned int irq)
+{
+#ifdef CONFIG_SMP
+	on_each_cpu((void (*)(void *)) octeon_irq_core_disable_local,
+		    (void *) (long) irq, 1);
+#else
+	octeon_irq_core_disable_local(irq);
+#endif
+}
+
+struct irq_chip octeon_irq_chip_core = {
+	.name = "Core",
+	.enable = octeon_irq_core_enable,
+	.disable = octeon_irq_core_disable,
+	.ack = octeon_irq_core_ack,
+	.eoi = octeon_irq_core_eoi,
+};
+
+
+static void octeon_irq_ciu0_ack(unsigned int irq)
+{
+	/* In order to avoid any locking accessing the CIU, we acknowledge CIU
+	   interrupts by disabling all of them. This way we can use a per core
+	   register and avoid any out of core locking requirements. This has
+	   the side affect that CIU interrupts can't be processed recursively */
+	/* We don't need to disable IRQs to make these atomic since they are
+	   already disabled earlier in the low level interrupt code */
+	clear_c0_status(0x100 << 2);
+}
+
+static void octeon_irq_ciu0_eoi(unsigned int irq)
+{
+	/* Enable all CIU interrupts again */
+	/* We don't need to disable IRQs to make these atomic since they are
+	   already disabled earlier in the low level interrupt code */
+	set_c0_status(0x100 << 2);
+}
+
+static void octeon_irq_ciu0_enable(unsigned int irq)
+{
+	int coreid = cvmx_get_core_num();
+	unsigned long flags;
+	uint64_t en0;
+	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
+
+	/* A read lock is used here to make sure only one core is ever updating
+	   the CIU enable bits at a time. During an enable the cores don't
+	   interfere with each other. During a disable the write lock stops any
+	   enables that might cause a problem */
+	read_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
+	en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+	en0 |= 1ull << bit;
+	cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+	cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+	read_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
+}
+
+static void octeon_irq_ciu0_disable(unsigned int irq)
+{
+	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
+	unsigned long flags;
+	uint64_t en0;
+#ifdef CONFIG_SMP
+	int cpu;
+	write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		if (cpu_present(cpu)) {
+			int coreid = cpu_logical_map(cpu);
+			en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+			en0 &= ~(1ull << bit);
+			cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+		}
+	}
+	/* We need to do a read after the last update to make sure all of them
+	   are done */
+	cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
+	write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
+#else
+	int coreid = cvmx_get_core_num();
+	local_irq_save(flags);
+	en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+	en0 &= ~(1ull << bit);
+	cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+	cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+	local_irq_restore(flags);
+#endif
+}
+
+#ifdef CONFIG_SMP
+static void octeon_irq_ciu0_set_affinity(unsigned int irq, cpumask_t dest)
+{
+	int cpu;
+	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
+
+	write_lock(&octeon_irq_ciu0_rwlock);
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		if (cpu_present(cpu)) {
+			int coreid = cpu_logical_map(cpu);
+			uint64_t en0 =
+				cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+			if (cpu_isset(cpu, dest))
+				en0 |= 1ull << bit;
+			else
+				en0 &= ~(1ull << bit);
+			cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+		}
+	}
+	/* We need to do a read after the last update to make sure all of them
+	   are done */
+	cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
+	write_unlock(&octeon_irq_ciu0_rwlock);
+}
+#endif
+
+struct irq_chip octeon_irq_chip_ciu0 = {
+	.name = "CIU0",
+	.enable = octeon_irq_ciu0_enable,
+	.disable = octeon_irq_ciu0_disable,
+	.ack = octeon_irq_ciu0_ack,
+	.eoi = octeon_irq_ciu0_eoi,
+#ifdef CONFIG_SMP
+	.set_affinity = octeon_irq_ciu0_set_affinity,
+#endif
+};
+
+
+static void octeon_irq_ciu1_ack(unsigned int irq)
+{
+	/* In order to avoid any locking accessing the CIU, we acknowledge CIU
+	   interrupts by disabling all of them. This way we can use a per core
+	   register and avoid any out of core locking requirements. This has
+	   the side affect that CIU interrupts can't be processed recursively */
+	/* We don't need to disable IRQs to make these atomic since they are
+	   already disabled earlier in the low level interrupt code */
+	clear_c0_status(0x100 << 3);
+}
+
+static void octeon_irq_ciu1_eoi(unsigned int irq)
+{
+	/* Enable all CIU interrupts again */
+	/* We don't need to disable IRQs to make these atomic since they are
+	   already disabled earlier in the low level interrupt code */
+	set_c0_status(0x100 << 3);
+}
+
+static void octeon_irq_ciu1_enable(unsigned int irq)
+{
+	int coreid = cvmx_get_core_num();
+	unsigned long flags;
+	uint64_t en1;
+	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
+
+	/* A read lock is used here to make sure only one core is ever updating
+	   the CIU enable bits at a time. During an enable the cores don't
+	   interfere with each other. During a disable the write lock stops any
+	   enables that might cause a problem */
+	read_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
+	en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+	en1 |= 1ull << bit;
+	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+	cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+	read_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
+}
+
+static void octeon_irq_ciu1_disable(unsigned int irq)
+{
+	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
+	unsigned long flags;
+	uint64_t en1;
+#ifdef CONFIG_SMP
+	int cpu;
+	write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		if (cpu_present(cpu)) {
+			int coreid = cpu_logical_map(cpu);
+			en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+			en1 &= ~(1ull << bit);
+			cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+		}
+	}
+	/* We need to do a read after the last update to make sure all of them
+	   are done */
+	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
+	write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
+#else
+	int coreid = cvmx_get_core_num();
+	local_irq_save(flags);
+	en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+	en1 &= ~(1ull << bit);
+	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+	cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+	local_irq_restore(flags);
+#endif
+}
+
+#ifdef CONFIG_SMP
+static void octeon_irq_ciu1_set_affinity(unsigned int irq, cpumask_t dest)
+{
+	int cpu;
+	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
+
+	write_lock(&octeon_irq_ciu1_rwlock);
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		if (cpu_present(cpu)) {
+			int coreid = cpu_logical_map(cpu);
+			uint64_t en1 =
+				cvmx_read_csr(CVMX_CIU_INTX_EN1
+					      (coreid * 2 + 1));
+			if (cpu_isset(cpu, dest))
+				en1 |= 1ull << bit;
+			else
+				en1 &= ~(1ull << bit);
+			cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+		}
+	}
+	/* We need to do a read after the last update to make sure all of them
+	   are done */
+	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
+	write_unlock(&octeon_irq_ciu1_rwlock);
+}
+#endif
+
+struct irq_chip octeon_irq_chip_ciu1 = {
+	.name = "CIU1",
+	.enable = octeon_irq_ciu1_enable,
+	.disable = octeon_irq_ciu1_disable,
+	.ack = octeon_irq_ciu1_ack,
+	.eoi = octeon_irq_ciu1_eoi,
+#ifdef CONFIG_SMP
+	.set_affinity = octeon_irq_ciu1_set_affinity,
+#endif
+};
+
+
+static void octeon_irq_i8289_master_unmask(unsigned int irq)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	outb(inb(0x21) & ~(1 << (irq - OCTEON_IRQ_I8259M0)), 0x21);
+	local_irq_restore(flags);
+}
+
+static void octeon_irq_i8289_master_mask(unsigned int irq)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	outb(inb(0x21) | (1 << (irq - OCTEON_IRQ_I8259M0)), 0x21);
+	local_irq_restore(flags);
+}
+
+struct irq_chip octeon_irq_chip_i8259_master = {
+	.name = "i8259M",
+	.mask = octeon_irq_i8289_master_mask,
+	.mask_ack = octeon_irq_i8289_master_mask,
+	.unmask = octeon_irq_i8289_master_unmask,
+	.eoi = octeon_irq_i8289_master_unmask,
+};
+
+
+static void octeon_irq_i8289_slave_unmask(unsigned int irq)
+{
+	outb(inb(0xa1) & ~(1 << (irq - OCTEON_IRQ_I8259S0)), 0xa1);
+}
+
+static void octeon_irq_i8289_slave_mask(unsigned int irq)
+{
+	outb(inb(0xa1) | (1 << (irq - OCTEON_IRQ_I8259S0)), 0xa1);
+}
+
+struct irq_chip octeon_irq_chip_i8259_slave = {
+	.name = "i8259S",
+	.mask = octeon_irq_i8289_slave_mask,
+	.mask_ack = octeon_irq_i8289_slave_mask,
+	.unmask = octeon_irq_i8289_slave_unmask,
+	.eoi = octeon_irq_i8289_slave_unmask,
+};
+
+#ifdef CONFIG_PCI_MSI
+
+static void octeon_irq_msi_ack(unsigned int irq)
+{
+	if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+		/* These chips have PCI */
+		cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV,
+			       1ull << (irq - OCTEON_IRQ_MSI_BIT0));
+	} else {
+		/* These chips have PCIe. Thankfully the ACK doesn't need any
+		   locking */
+		cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0,
+			       1ull << (irq - OCTEON_IRQ_MSI_BIT0));
+	}
+}
+
+static void octeon_irq_msi_eoi(unsigned int irq)
+{
+	/* Nothing needed */
+}
+
+static void octeon_irq_msi_enable(unsigned int irq)
+{
+	if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+		/* Octeon PCI doesn't have the ability to mask/unmask MSI
+		   interrupts individually. Instead of masking/unmasking them
+		   in groups of 16, we simple assume MSI devices are well
+		   behaved. MSI interrupts are always enable and the ACK is
+		   assumed to be enough */
+	} else {
+		/* These chips have PCIe. Note that we only support the first
+		   64 MSI interrupts. Unfortunately all the MSI enables are in
+		   the same register. We use MSI0's lock to control access to
+		   them all. */
+		uint64_t en;
+		unsigned long flags;
+		spin_lock_irqsave(&octeon_irq_msi_lock, flags);
+		en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+		en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0);
+		cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en);
+		cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+		spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
+	}
+}
+
+static void octeon_irq_msi_disable(unsigned int irq)
+{
+	if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+		/* See comment in enable */
+	} else {
+		/* These chips have PCIe. Note that we only support the first
+		   64 MSI interrupts. Unfortunately all the MSI enables are in
+		   the same register. We use MSI0's lock to control access to
+		   them all. */
+		uint64_t en;
+		unsigned long flags;
+		spin_lock_irqsave(&octeon_irq_msi_lock, flags);
+		en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+		en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0));
+		cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en);
+		cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+		spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
+	}
+}
+
+struct irq_chip octeon_irq_chip_msi = {
+	.name = "MSI",
+	.enable = octeon_irq_msi_enable,
+	.disable = octeon_irq_msi_disable,
+	.ack = octeon_irq_msi_ack,
+	.eoi = octeon_irq_msi_eoi,
+};
+#endif
+
+void __init arch_init_irq(void)
+{
+	int irq;
+
+	if (NR_IRQS < OCTEON_IRQ_LAST)
+		pr_err("octeon_irq_init: NR_IRQS is set too low\n");
+
+	/* 0-7 Mips internal */
+	for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) {
+		set_irq_chip_and_handler(irq, &octeon_irq_chip_core,
+					 handle_percpu_irq);
+	}
+
+	/* 8-71 CIU_INT_SUM0 */
+	for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
+		set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu0,
+					 handle_percpu_irq);
+	}
+
+	/* 72-135 CIU_INT_SUM1 */
+	for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_RESERVED135; irq++) {
+		set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu1,
+					 handle_percpu_irq);
+	}
+
+	/* 136 - 143 are reserved to align the i8259 in a multiple of 16. This
+	   alignment is necessary since old style ISA interrupts hanging off
+	   the i8259 have internal alignment assumptions */
+
+	/* 144-151 i8259 master controller */
+	for (irq = OCTEON_IRQ_I8259M0; irq <= OCTEON_IRQ_I8259M7; irq++) {
+		set_irq_chip_and_handler(irq, &octeon_irq_chip_i8259_master,
+					 handle_level_irq);
+	}
+
+	/* 152-159 i8259 slave controller */
+	for (irq = OCTEON_IRQ_I8259S0; irq <= OCTEON_IRQ_I8259S7; irq++) {
+		set_irq_chip_and_handler(irq, &octeon_irq_chip_i8259_slave,
+					 handle_level_irq);
+	}
+
+#ifdef CONFIG_PCI_MSI
+	/* 160-223 PCI/PCIe MSI interrupts */
+	for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_BIT63; irq++) {
+		set_irq_chip_and_handler(irq, &octeon_irq_chip_msi,
+					 handle_percpu_irq);
+	}
+#endif
+
+	set_c0_status(0x300 << 2);
+}
arch/mips/kernel/octeon_switch.S new file +506 -0

506 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#4 lore raw

PATCH 4/36 Add Cavium OCTEON processor support files to arch/mips/mm.

---
 arch/mips/mm/c-octeon.c |  309 +++++++++++++++++++++++++++++++++++++++++++++++
 arch/mips/mm/cex-oct.S  |   70 +++++++++++
 2 files changed, 379 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/mm/c-octeon.c
 create mode 100644 arch/mips/mm/cex-oct.S
arch/mips/mm/c-octeon.c new file +309 -0
new file mode 100644
index 0000000..6c96c1a
@@ -0,0 +1,309 @@
+/*
+ * 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) 2005-2007 Cavium Networks
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/bitops.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
+
+#include <asm/bcache.h>
+#include <asm/bootinfo.h>
+#include <asm/cacheops.h>
+#include <asm/cpu-features.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/r4kcache.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/war.h>
+#include "../cavium-octeon/hal.h"
+
+unsigned long long cache_err_dcache[NR_CPUS];
+
+/**
+ * Octeon automatically flushes the dcache on tlb changes, so
+ * from Linux's viewpoint it acts much like a physically
+ * tagged cache. No flushing is needed
+ *
+ * @param addr
+ */
+static void octeon_flush_data_cache_page(unsigned long addr)
+{
+    /* Nothing to do */
+}
+
+/* Flush local I-cache for the specified range.
+ */
+static inline void local_octeon_flush_icache_range(unsigned long start,
+						   unsigned long end)
+{
+	asm volatile ("synci 0($0)\n");
+}
+
+/**
+ * Flush caches as necessary for all cores affected by a
+ * vma. If no vma is supplied, all cores are flushed.
+ *
+ * @param vma    VMA to flush or NULL to flush all icaches.
+ */
+static void octeon_flush_icache_all_cores(struct vm_area_struct *vma)
+{
+	extern struct plat_smp_ops *mp_ops;	/* private */
+#ifdef CONFIG_SMP
+	int i;
+	int cpu;
+#endif
+
+	preempt_disable();
+#ifdef CONFIG_SMP
+	cpu = smp_processor_id();
+#endif
+	mb();
+
+	/* If we have a vma structure, we only need to worry about cores it
+	   has been used on */
+	if (vma) {
+#ifdef CONFIG_SMP
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_isset(i, vma->vm_mm->cpu_vm_mask) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");
+	} else {
+		/* No extra info available. Flush the icache on all cores that
+		   are online */
+#ifdef CONFIG_SMP
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_online(i) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");
+	}
+	preempt_enable();
+}
+
+
+/**
+ * Called to flush the icache on all cores
+ */
+static void octeon_flush_icache_all(void)
+{
+	octeon_flush_icache_all_cores(NULL);
+}
+
+
+/**
+ * Called to flush all memory associated with a memory
+ * context.
+ *
+ * @param mm     Memory context to flush
+ */
+static void octeon_flush_cache_mm(struct mm_struct *mm)
+{
+	/* According to the R4K version of this file, CPUs without
+	   dcache aliases don't need to do anything here */
+}
+
+
+/**
+ * Flush a range of kernel addresses out of the icache
+ *
+ * @param start
+ * @param end
+ */
+static void octeon_flush_icache_range(unsigned long start, unsigned long end)
+{
+	octeon_flush_icache_all_cores(NULL);
+}
+
+
+/**
+ * Flush the icache for a trampoline. These are used for interrupt
+ * and exception hooking.
+ *
+ * @param addr   Address to flush
+ */
+static void octeon_flush_cache_sigtramp(unsigned long addr)
+{
+	/* Only flush trampolines on the current core */
+	mb();
+	asm volatile ("synci 0(%0)\n" : : "r" (addr));
+}
+
+
+/**
+ * Flush a range out of a vma
+ *
+ * @param vma    VMA to flush
+ * @param start
+ * @param end
+ */
+static void octeon_flush_cache_range(struct vm_area_struct *vma,
+				     unsigned long start, unsigned long end)
+{
+	if (vma->vm_flags & (VM_EXEC|VM_EXECUTABLE))
+		octeon_flush_icache_all_cores(vma);
+}
+
+
+/**
+ * Flush a specific page of a vma
+ *
+ * @param vma    VMA to flush page for
+ * @param page   Page to flush
+ * @param pfn
+ */
+static void octeon_flush_cache_page(struct vm_area_struct *vma,
+				    unsigned long page, unsigned long pfn)
+{
+	if (vma->vm_flags & (VM_EXEC|VM_EXECUTABLE))
+		octeon_flush_icache_all_cores(vma);
+}
+
+
+/**
+ * Probe Octeon's caches
+ *
+ * @return
+ */
+static void __devinit probe_octeon(void)
+{
+	unsigned long icache_size;
+	unsigned long dcache_size;
+	unsigned int config1;
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	switch (c->cputype) {
+	case CPU_CAVIUM_OCTEON:
+		config1 = read_c0_config1();
+		c->icache.linesz = 2 << ((config1 >> 19) & 7);
+		c->icache.sets = 64 << ((config1 >> 22) & 7);
+		c->icache.ways = 1 + ((config1 >> 16) & 7);
+		c->icache.flags |= MIPS_CACHE_VTAG;
+		icache_size =
+			c->icache.sets * c->icache.ways * c->icache.linesz;
+		c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
+		c->dcache.linesz = 128;
+		if (OCTEON_IS_MODEL(OCTEON_CN3XXX))
+			c->dcache.sets = 1; /* CN3XXX has one Dcache set */
+		else
+			c->dcache.sets = 2; /* CN5XXX has two Dcache sets */
+		c->dcache.ways = 64;
+		dcache_size =
+			c->dcache.sets * c->dcache.ways * c->dcache.linesz;
+		c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+		c->options |= MIPS_CPU_PREFETCH;
+		break;
+
+	default:
+		panic("Unsupported Cavium Networks CPU type\n");
+		break;
+	}
+
+	/* compute a couple of other cache variables */
+	c->icache.waysize = icache_size / c->icache.ways;
+	c->dcache.waysize = dcache_size / c->dcache.ways;
+
+	c->icache.sets = icache_size / (c->icache.linesz * c->icache.ways);
+	c->dcache.sets = dcache_size / (c->dcache.linesz * c->dcache.ways);
+
+	if (smp_processor_id() == 0) {
+		pr_notice("Primary instruction cache %ldkB, %s, %d way, "
+			  "%d sets, linesize %d bytes.\n",
+			  icache_size >> 10,
+			  cpu_has_vtag_icache ?
+				"virtually tagged" : "physically tagged",
+			  c->icache.ways, c->icache.sets, c->icache.linesz);
+
+		pr_notice("Primary data cache %ldkB, %d-way, %d sets, "
+			  "linesize %d bytes.\n",
+			  dcache_size >> 10, c->dcache.ways,
+			  c->dcache.sets, c->dcache.linesz);
+	}
+}
+
+
+/**
+ * Setup the Octeon cache flush routines
+ *
+ * @return
+ */
+void __devinit octeon_cache_init(void)
+{
+	extern unsigned long ebase;
+	extern char except_vec2_octeon;
+
+	memcpy((void *)(ebase + 0x100), &except_vec2_octeon, 0x80);
+	octeon_flush_cache_sigtramp(ebase + 0x100);
+
+	probe_octeon();
+
+	shm_align_mask = PAGE_SIZE - 1;
+
+	flush_cache_all			= octeon_flush_icache_all;
+	__flush_cache_all		= octeon_flush_icache_all;
+	flush_cache_mm			= octeon_flush_cache_mm;
+	flush_cache_page		= octeon_flush_cache_page;
+	flush_cache_range		= octeon_flush_cache_range;
+	flush_cache_sigtramp		= octeon_flush_cache_sigtramp;
+	flush_icache_all		= octeon_flush_icache_all;
+	flush_data_cache_page		= octeon_flush_data_cache_page;
+	flush_icache_range		= octeon_flush_icache_range;
+	local_flush_icache_range	= local_octeon_flush_icache_range;
+
+	build_clear_page();
+	build_copy_page();
+}
+
+/**
+ * Handle a cache error exception
+ */
+
+static void  cache_parity_error_octeon(int non_recoverable)
+{
+	unsigned long coreid = cvmx_get_core_num();
+	uint64_t icache_err = read_c0_cacheerr();
+
+	pr_err("Cache error exception:\n");
+	pr_err("cp0_errorepc == %lx\n", read_c0_errorepc());
+	if (icache_err & 1) {
+		pr_err("CacheErr (Icache) == %llx\n",
+		       (unsigned long long)icache_err);
+		write_c0_cacheerr(0);
+	}
+	if (cache_err_dcache[coreid] & 1) {
+		pr_err("CacheErr (Dcache) == %llx\n",
+		       (unsigned long long)cache_err_dcache[coreid]);
+		cache_err_dcache[coreid] = 0;
+	}
+
+
+	if (non_recoverable)
+		panic("Can't handle cache error: nested exception");
+}
+
+/**
+ * Called when the the exception is not recoverable
+ */
+
+asmlinkage void cache_parity_error_octeon_recoverable(void)
+{
+	cache_parity_error_octeon(0);
+}
+
+/**
+ * Called when the the exception is recoverable
+ */
+
+asmlinkage void cache_parity_error_octeon_non_recoverable(void)
+{
+	cache_parity_error_octeon(1);
+}
+
arch/mips/mm/cex-oct.S new file +70 -0

70 lines not on this page · raw message

Signature · 1 line
1.5.6.5
#5 lore raw

PATCH 5/36 Add Cavium OCTEON processor support files to and arch/mips/cavium-octeon/executive

---
 arch/mips/cavium-octeon/executive/Makefile         |   26 +
 arch/mips/cavium-octeon/executive/cvmx-asm.h       |  427 ++++++++++
 arch/mips/cavium-octeon/executive/cvmx-bootinfo.h  |  238 ++++++
 arch/mips/cavium-octeon/executive/cvmx-bootmem.c   |  897 ++++++++++++++++++++
 arch/mips/cavium-octeon/executive/cvmx-bootmem.h   |  403 +++++++++
 arch/mips/cavium-octeon/executive/cvmx-interrupt.h |  255 ++++++
 arch/mips/cavium-octeon/executive/cvmx-l2c.c       |  711 ++++++++++++++++
 arch/mips/cavium-octeon/executive/cvmx-l2c.h       |  328 +++++++
 .../executive/cvmx-linux-kernel-exports.c          |   30 +
 arch/mips/cavium-octeon/executive/cvmx-packet.h    |   64 ++
 arch/mips/cavium-octeon/executive/cvmx-platform.h  |   56 ++
 arch/mips/cavium-octeon/executive/cvmx-spinlock.h  |  376 ++++++++
 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c   |  113 +++
 arch/mips/cavium-octeon/executive/cvmx-sysinfo.h   |  144 ++++
 arch/mips/cavium-octeon/executive/cvmx-warn.c      |   44 +
 arch/mips/cavium-octeon/executive/cvmx-warn.h      |   46 +
 arch/mips/cavium-octeon/executive/cvmx.h           |  772 +++++++++++++++++
 arch/mips/cavium-octeon/executive/octeon-feature.h |  120 +++
 arch/mips/cavium-octeon/executive/octeon-model.c   |  328 +++++++
 arch/mips/cavium-octeon/executive/octeon-model.h   |  225 +++++
 20 files changed, 5603 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/cavium-octeon/executive/Makefile
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-asm.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootinfo.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-interrupt.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-linux-kernel-exports.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-packet.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-platform.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-spinlock.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx.h
 create mode 100644 arch/mips/cavium-octeon/executive/octeon-feature.h
 create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.c
 create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.h
arch/mips/cavium-octeon/executive/Makefile new file +26 -0
new file mode 100644
index 0000000..cb51c58
@@ -0,0 +1,26 @@
+#
+# Makefile for the Cavium Octeon specific kernel interface routines
+# under Linux.
+#
+# 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) 2005-2007 Cavium Networks
+#
+
+
+source:=$(srctree)/$(src)
+EXTRA_CFLAGS	+= -I$(source) -I$(source)/config
+
+executive-files := cvmx-bootmem.o
+executive-files += cvmx-l2c.o
+executive-files += cvmx-sysinfo.o
+executive-files += cvmx-warn.o
+executive-files += octeon-model.o
+executive-files += cvmx-linux-kernel-exports.o
+obj-y := $(executive-files)
+
+executive-obj-files := $(executive-files:%=$(obj)/%)
+executive-src-files := $(executive-obj-files:%.o=%.c)
+
arch/mips/cavium-octeon/executive/cvmx-asm.h new file +427 -0

427 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-bootinfo.h new file +238 -0

238 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-bootmem.c new file +897 -0

897 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-bootmem.h new file +403 -0

403 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-interrupt.h new file +255 -0

255 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-l2c.c new file +711 -0

711 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-l2c.h new file +328 -0

43 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-linux-kernel-exports.c new file +30 -0
new file mode 100644
index 0000000..1384717

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-packet.h new file +64 -0

64 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-platform.h new file +56 -0

56 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-spinlock.h new file +376 -0

376 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-sysinfo.c new file +113 -0

113 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-sysinfo.h new file +144 -0

144 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-warn.c new file +44 -0

44 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-warn.h new file +46 -0

46 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx.h new file +772 -0

772 lines not on this page · raw message

arch/mips/cavium-octeon/executive/octeon-feature.h new file +120 -0

120 lines not on this page · raw message

arch/mips/cavium-octeon/executive/octeon-model.c new file +328 -0

328 lines not on this page · raw message

arch/mips/cavium-octeon/executive/octeon-model.h new file +225 -0

225 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.5.6.5

Part of the diff is not shown here. View the raw message.

#6 lore raw

PATCH 6/36 Add Cavium OCTEON processor CSR definitions

---
 .../cavium-octeon/executive/cvmx-csr-addresses.h   | 8391 ++++++
 arch/mips/cavium-octeon/executive/cvmx-csr-enums.h |   86 +
 .../cavium-octeon/executive/cvmx-csr-typedefs.h    |27517 ++++++++++++++++++++
 arch/mips/cavium-octeon/executive/cvmx-csr.h       |  199 +
 4 files changed, 36193 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-addresses.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-enums.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-typedefs.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr.h
arch/mips/cavium-octeon/executive/cvmx-csr-addresses.h new file +8391 -0
new file mode 100644
index 0000000..04bfdaf
@@ -0,0 +1,8391 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ *
+ * Configuration and status register (CSR) address and for
+ * Octeon. Include cvmx-csr.h instead of this file directly.
+ *
+ * This file is auto generated. Do not edit.
+ *
+ *
+ */
+#ifndef __CVMX_CSR_ADDRESSES_H__
+#define __CVMX_CSR_ADDRESSES_H__
+
+
+#define CVMX_AGL_GMX_BAD_REG CVMX_AGL_GMX_BAD_REG_FUNC()
+static inline uint64_t CVMX_AGL_GMX_BAD_REG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000518ull);
+}
+
+#define CVMX_AGL_GMX_BIST CVMX_AGL_GMX_BIST_FUNC()
+static inline uint64_t CVMX_AGL_GMX_BIST_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000400ull);
+}
+
+#define CVMX_AGL_GMX_DRV_CTL CVMX_AGL_GMX_DRV_CTL_FUNC()
+static inline uint64_t CVMX_AGL_GMX_DRV_CTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00007F0ull);
+}
+
+#define CVMX_AGL_GMX_INF_MODE CVMX_AGL_GMX_INF_MODE_FUNC()
+static inline uint64_t CVMX_AGL_GMX_INF_MODE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00007F8ull);
+}
+
+static inline uint64_t CVMX_AGL_GMX_PRTX_CFG(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000010ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CAM0(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000180ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CAM1(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000188ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CAM2(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000190ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CAM3(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000198ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CAM4(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00001A0ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CAM5(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00001A8ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CAM_EN(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000108ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_ADR_CTL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000100ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_DECISION(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000040ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_FRM_CHK(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000020ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_FRM_CTL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000018ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_FRM_MAX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000030ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_FRM_MIN(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000028ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_IFG(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000058ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_INT_EN(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000008ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_INT_REG(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000000ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_JABBER(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000038ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_PAUSE_DROP_TIME(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000068ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_CTL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000050ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_OCTS(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000088ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_OCTS_CTL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000098ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_OCTS_DMAC(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00000A8ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_OCTS_DRP(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00000B8ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_PKTS(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000080ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00000C0ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_PKTS_CTL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000090ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_PKTS_DMAC(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00000A0ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00000B0ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RXX_UDD_SKP(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000048ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RX_BP_DROPX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000420ull) + (offset & 1) * 8;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RX_BP_OFFX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000460ull) + (offset & 1) * 8;
+}
+
+static inline uint64_t CVMX_AGL_GMX_RX_BP_ONX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000440ull) + (offset & 1) * 8;
+}
+
+#define CVMX_AGL_GMX_RX_PRT_INFO CVMX_AGL_GMX_RX_PRT_INFO_FUNC()
+static inline uint64_t CVMX_AGL_GMX_RX_PRT_INFO_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00004E8ull);
+}
+
+#define CVMX_AGL_GMX_RX_TX_STATUS CVMX_AGL_GMX_RX_TX_STATUS_FUNC()
+static inline uint64_t CVMX_AGL_GMX_RX_TX_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00007E8ull);
+}
+
+static inline uint64_t CVMX_AGL_GMX_SMACX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000230ull) + (offset & 1) * 2048;
+}
+
+#define CVMX_AGL_GMX_STAT_BP CVMX_AGL_GMX_STAT_BP_FUNC()
+static inline uint64_t CVMX_AGL_GMX_STAT_BP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000520ull);
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_APPEND(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000218ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_CTL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000270ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_MIN_PKT(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000240ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_PAUSE_PKT_INTERVAL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000248ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_PAUSE_PKT_TIME(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000238ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_PAUSE_TOGO(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000258ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_PAUSE_ZERO(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000260ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_SOFT_PAUSE(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000250ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT0(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000280ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT1(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000288ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT2(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000290ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT3(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000298ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT4(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00002A0ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT5(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00002A8ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT6(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00002B0ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT7(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00002B8ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT8(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00002C0ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STAT9(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00002C8ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_STATS_CTL(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000268ull) + (offset & 1) * 2048;
+}
+
+static inline uint64_t CVMX_AGL_GMX_TXX_THRESH(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000210ull) + (offset & 1) * 2048;
+}
+
+#define CVMX_AGL_GMX_TX_BP CVMX_AGL_GMX_TX_BP_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_BP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00004D0ull);
+}
+
+#define CVMX_AGL_GMX_TX_COL_ATTEMPT CVMX_AGL_GMX_TX_COL_ATTEMPT_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_COL_ATTEMPT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000498ull);
+}
+
+#define CVMX_AGL_GMX_TX_IFG CVMX_AGL_GMX_TX_IFG_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_IFG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000488ull);
+}
+
+#define CVMX_AGL_GMX_TX_INT_EN CVMX_AGL_GMX_TX_INT_EN_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_INT_EN_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000508ull);
+}
+
+#define CVMX_AGL_GMX_TX_INT_REG CVMX_AGL_GMX_TX_INT_REG_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_INT_REG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000500ull);
+}
+
+#define CVMX_AGL_GMX_TX_JAM CVMX_AGL_GMX_TX_JAM_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_JAM_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E0000490ull);
+}
+
+#define CVMX_AGL_GMX_TX_LFSR CVMX_AGL_GMX_TX_LFSR_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_LFSR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00004F8ull);
+}
+
+#define CVMX_AGL_GMX_TX_OVR_BP CVMX_AGL_GMX_TX_OVR_BP_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_OVR_BP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00004C8ull);
+}
+
+#define CVMX_AGL_GMX_TX_PAUSE_PKT_DMAC CVMX_AGL_GMX_TX_PAUSE_PKT_DMAC_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_PAUSE_PKT_DMAC_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00004A0ull);
+}
+
+#define CVMX_AGL_GMX_TX_PAUSE_PKT_TYPE CVMX_AGL_GMX_TX_PAUSE_PKT_TYPE_FUNC()
+static inline uint64_t CVMX_AGL_GMX_TX_PAUSE_PKT_TYPE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800E00004A8ull);
+}
+
+#define CVMX_ASX0_DBG_DATA_DRV CVMX_ASX0_DBG_DATA_DRV_FUNC()
+static inline uint64_t CVMX_ASX0_DBG_DATA_DRV_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000208ull);
+}
+
+#define CVMX_ASX0_DBG_DATA_ENABLE CVMX_ASX0_DBG_DATA_ENABLE_FUNC()
+static inline uint64_t CVMX_ASX0_DBG_DATA_ENABLE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000200ull);
+}
+
+static inline uint64_t CVMX_ASXX_GMII_RX_CLK_SET(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000180ull) +
+	    (block_id & 0) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_GMII_RX_DAT_SET(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000188ull) +
+	    (block_id & 0) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_INT_EN(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000018ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_INT_REG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000010ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_MII_RX_DAT_SET(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000190ull) +
+	    (block_id & 0) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_PRT_LOOP(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000040ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_BYPASS(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000248ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_BYPASS_SETTING(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000250ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_COMP(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000220ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_DATA_DRV(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000218ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_FCRAM_MODE(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000210ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_NCTL_STRONG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000230ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_NCTL_WEAK(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000240ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_PCTL_STRONG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000228ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_PCTL_WEAK(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000238ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RLD_SETTING(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000258ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RX_CLK_SETX(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000020ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_ASXX_RX_PRT_EN(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000000ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RX_WOL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000100ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RX_WOL_MSK(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000108ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RX_WOL_POWOK(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000118ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_RX_WOL_SIG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000110ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_TX_CLK_SETX(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000048ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_ASXX_TX_COMP_BYP(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000068ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_ASXX_TX_HI_WATERX(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000080ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_ASXX_TX_PRT_EN(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800B0000008ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+#define CVMX_CIU_BIST CVMX_CIU_BIST_FUNC()
+static inline uint64_t CVMX_CIU_BIST_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000730ull);
+}
+
+#define CVMX_CIU_DINT CVMX_CIU_DINT_FUNC()
+static inline uint64_t CVMX_CIU_DINT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000720ull);
+}
+
+#define CVMX_CIU_FUSE CVMX_CIU_FUSE_FUNC()
+static inline uint64_t CVMX_CIU_FUSE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000728ull);
+}
+
+#define CVMX_CIU_GSTOP CVMX_CIU_GSTOP_FUNC()
+static inline uint64_t CVMX_CIU_GSTOP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000710ull);
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN0(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000200ull) + (offset & 63) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN0_W1C(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000002200ull) + (offset & 63) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN0_W1S(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000006200ull) + (offset & 63) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN1(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000208ull) + (offset & 63) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN1_W1C(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000002208ull) + (offset & 63) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN1_W1S(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000006208ull) + (offset & 63) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN4_0(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000C80ull) + (offset & 15) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN4_0_W1C(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000002C80ull) + (offset & 15) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN4_0_W1S(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000006C80ull) + (offset & 15) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN4_1(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000C88ull) + (offset & 15) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN4_1_W1C(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000002C88ull) + (offset & 15) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_EN4_1_W1S(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000006C88ull) + (offset & 15) * 16;
+}
+
+static inline uint64_t CVMX_CIU_INTX_SUM0(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000000ull) + (offset & 63) * 8;
+}
+
+static inline uint64_t CVMX_CIU_INTX_SUM4(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000C00ull) + (offset & 15) * 8;
+}
+
+#define CVMX_CIU_INT_SUM1 CVMX_CIU_INT_SUM1_FUNC()
+static inline uint64_t CVMX_CIU_INT_SUM1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000108ull);
+}
+
+static inline uint64_t CVMX_CIU_MBOX_CLRX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000680ull) + (offset & 15) * 8;
+}
+
+static inline uint64_t CVMX_CIU_MBOX_SETX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000600ull) + (offset & 15) * 8;
+}
+
+#define CVMX_CIU_NMI CVMX_CIU_NMI_FUNC()
+static inline uint64_t CVMX_CIU_NMI_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000718ull);
+}
+
+#define CVMX_CIU_PCI_INTA CVMX_CIU_PCI_INTA_FUNC()
+static inline uint64_t CVMX_CIU_PCI_INTA_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000750ull);
+}
+
+#define CVMX_CIU_PP_DBG CVMX_CIU_PP_DBG_FUNC()
+static inline uint64_t CVMX_CIU_PP_DBG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000708ull);
+}
+
+static inline uint64_t CVMX_CIU_PP_POKEX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000580ull) + (offset & 15) * 8;
+}
+
+#define CVMX_CIU_PP_RST CVMX_CIU_PP_RST_FUNC()
+static inline uint64_t CVMX_CIU_PP_RST_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000700ull);
+}
+
+#define CVMX_CIU_QLM_DCOK CVMX_CIU_QLM_DCOK_FUNC()
+static inline uint64_t CVMX_CIU_QLM_DCOK_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000760ull);
+}
+
+#define CVMX_CIU_QLM_JTGC CVMX_CIU_QLM_JTGC_FUNC()
+static inline uint64_t CVMX_CIU_QLM_JTGC_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000768ull);
+}
+
+#define CVMX_CIU_QLM_JTGD CVMX_CIU_QLM_JTGD_FUNC()
+static inline uint64_t CVMX_CIU_QLM_JTGD_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000770ull);
+}
+
+#define CVMX_CIU_SOFT_BIST CVMX_CIU_SOFT_BIST_FUNC()
+static inline uint64_t CVMX_CIU_SOFT_BIST_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000738ull);
+}
+
+#define CVMX_CIU_SOFT_PRST CVMX_CIU_SOFT_PRST_FUNC()
+static inline uint64_t CVMX_CIU_SOFT_PRST_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000748ull);
+}
+
+#define CVMX_CIU_SOFT_PRST1 CVMX_CIU_SOFT_PRST1_FUNC()
+static inline uint64_t CVMX_CIU_SOFT_PRST1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000758ull);
+}
+
+#define CVMX_CIU_SOFT_RST CVMX_CIU_SOFT_RST_FUNC()
+static inline uint64_t CVMX_CIU_SOFT_RST_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000740ull);
+}
+
+static inline uint64_t CVMX_CIU_TIMX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000480ull) + (offset & 3) * 8;
+}
+
+static inline uint64_t CVMX_CIU_WDOGX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000500ull) + (offset & 15) * 8;
+}
+
+#define CVMX_DBG_DATA CVMX_DBG_DATA_FUNC()
+static inline uint64_t CVMX_DBG_DATA_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011F00000001E8ull);
+}
+
+#define CVMX_DFA_BST0 CVMX_DFA_BST0_FUNC()
+static inline uint64_t CVMX_DFA_BST0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800300007F0ull);
+}
+
+#define CVMX_DFA_BST1 CVMX_DFA_BST1_FUNC()
+static inline uint64_t CVMX_DFA_BST1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800300007F8ull);
+}
+
+#define CVMX_DFA_CFG CVMX_DFA_CFG_FUNC()
+static inline uint64_t CVMX_DFA_CFG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000000ull);
+}
+
+#define CVMX_DFA_DBELL CVMX_DFA_DBELL_FUNC()
+static inline uint64_t CVMX_DFA_DBELL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001370000000000ull);
+}
+
+#define CVMX_DFA_DDR2_ADDR CVMX_DFA_DDR2_ADDR_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_ADDR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000210ull);
+}
+
+#define CVMX_DFA_DDR2_BUS CVMX_DFA_DDR2_BUS_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_BUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000080ull);
+}
+
+#define CVMX_DFA_DDR2_CFG CVMX_DFA_DDR2_CFG_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_CFG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000208ull);
+}
+
+#define CVMX_DFA_DDR2_COMP CVMX_DFA_DDR2_COMP_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_COMP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000090ull);
+}
+
+#define CVMX_DFA_DDR2_EMRS CVMX_DFA_DDR2_EMRS_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_EMRS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000268ull);
+}
+
+#define CVMX_DFA_DDR2_FCNT CVMX_DFA_DDR2_FCNT_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_FCNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000078ull);
+}
+
+#define CVMX_DFA_DDR2_MRS CVMX_DFA_DDR2_MRS_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_MRS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000260ull);
+}
+
+#define CVMX_DFA_DDR2_OPT CVMX_DFA_DDR2_OPT_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_OPT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000070ull);
+}
+
+#define CVMX_DFA_DDR2_PLL CVMX_DFA_DDR2_PLL_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_PLL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000088ull);
+}
+
+#define CVMX_DFA_DDR2_TMG CVMX_DFA_DDR2_TMG_FUNC()
+static inline uint64_t CVMX_DFA_DDR2_TMG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000218ull);
+}
+
+#define CVMX_DFA_DIFCTL CVMX_DFA_DIFCTL_FUNC()
+static inline uint64_t CVMX_DFA_DIFCTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001370600000000ull);
+}
+
+#define CVMX_DFA_DIFRDPTR CVMX_DFA_DIFRDPTR_FUNC()
+static inline uint64_t CVMX_DFA_DIFRDPTR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001370200000000ull);
+}
+
+#define CVMX_DFA_ECLKCFG CVMX_DFA_ECLKCFG_FUNC()
+static inline uint64_t CVMX_DFA_ECLKCFG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000200ull);
+}
+
+#define CVMX_DFA_ERR CVMX_DFA_ERR_FUNC()
+static inline uint64_t CVMX_DFA_ERR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000028ull);
+}
+
+#define CVMX_DFA_MEMCFG0 CVMX_DFA_MEMCFG0_FUNC()
+static inline uint64_t CVMX_DFA_MEMCFG0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000008ull);
+}
+
+#define CVMX_DFA_MEMCFG1 CVMX_DFA_MEMCFG1_FUNC()
+static inline uint64_t CVMX_DFA_MEMCFG1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000010ull);
+}
+
+#define CVMX_DFA_MEMCFG2 CVMX_DFA_MEMCFG2_FUNC()
+static inline uint64_t CVMX_DFA_MEMCFG2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000060ull);
+}
+
+#define CVMX_DFA_MEMFADR CVMX_DFA_MEMFADR_FUNC()
+static inline uint64_t CVMX_DFA_MEMFADR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000030ull);
+}
+
+#define CVMX_DFA_MEMFCR CVMX_DFA_MEMFCR_FUNC()
+static inline uint64_t CVMX_DFA_MEMFCR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000038ull);
+}
+
+#define CVMX_DFA_MEMRLD CVMX_DFA_MEMRLD_FUNC()
+static inline uint64_t CVMX_DFA_MEMRLD_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000018ull);
+}
+
+#define CVMX_DFA_NCBCTL CVMX_DFA_NCBCTL_FUNC()
+static inline uint64_t CVMX_DFA_NCBCTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000020ull);
+}
+
+#define CVMX_DFA_RODT_COMP_CTL CVMX_DFA_RODT_COMP_CTL_FUNC()
+static inline uint64_t CVMX_DFA_RODT_COMP_CTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000068ull);
+}
+
+#define CVMX_DFA_SBD_DBG0 CVMX_DFA_SBD_DBG0_FUNC()
+static inline uint64_t CVMX_DFA_SBD_DBG0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000040ull);
+}
+
+#define CVMX_DFA_SBD_DBG1 CVMX_DFA_SBD_DBG1_FUNC()
+static inline uint64_t CVMX_DFA_SBD_DBG1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000048ull);
+}
+
+#define CVMX_DFA_SBD_DBG2 CVMX_DFA_SBD_DBG2_FUNC()
+static inline uint64_t CVMX_DFA_SBD_DBG2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000050ull);
+}
+
+#define CVMX_DFA_SBD_DBG3 CVMX_DFA_SBD_DBG3_FUNC()
+static inline uint64_t CVMX_DFA_SBD_DBG3_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180030000058ull);
+}
+
+#define CVMX_FPA_BIST_STATUS CVMX_FPA_BIST_STATUS_FUNC()
+static inline uint64_t CVMX_FPA_BIST_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800280000E8ull);
+}
+
+#define CVMX_FPA_CTL_STATUS CVMX_FPA_CTL_STATUS_FUNC()
+static inline uint64_t CVMX_FPA_CTL_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000050ull);
+}
+
+#define CVMX_FPA_FPF0_MARKS CVMX_FPA_FPF0_MARKS_FUNC()
+static inline uint64_t CVMX_FPA_FPF0_MARKS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000000ull);
+}
+
+#define CVMX_FPA_FPF0_SIZE CVMX_FPA_FPF0_SIZE_FUNC()
+static inline uint64_t CVMX_FPA_FPF0_SIZE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000058ull);
+}
+
+#define CVMX_FPA_FPF1_MARKS CVMX_FPA_FPFX_MARKS(1)
+#define CVMX_FPA_FPF2_MARKS CVMX_FPA_FPFX_MARKS(2)
+#define CVMX_FPA_FPF3_MARKS CVMX_FPA_FPFX_MARKS(3)
+#define CVMX_FPA_FPF4_MARKS CVMX_FPA_FPFX_MARKS(4)
+#define CVMX_FPA_FPF5_MARKS CVMX_FPA_FPFX_MARKS(5)
+#define CVMX_FPA_FPF6_MARKS CVMX_FPA_FPFX_MARKS(6)
+#define CVMX_FPA_FPF7_MARKS CVMX_FPA_FPFX_MARKS(7)
+static inline uint64_t CVMX_FPA_FPFX_MARKS(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000008ull) + (offset & 7) * 8 -
+	    8 * 1;
+}
+
+static inline uint64_t CVMX_FPA_FPFX_SIZE(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000060ull) + (offset & 7) * 8 -
+	    8 * 1;
+}
+
+#define CVMX_FPA_INT_ENB CVMX_FPA_INT_ENB_FUNC()
+static inline uint64_t CVMX_FPA_INT_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000048ull);
+}
+
+#define CVMX_FPA_INT_SUM CVMX_FPA_INT_SUM_FUNC()
+static inline uint64_t CVMX_FPA_INT_SUM_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000040ull);
+}
+
+#define CVMX_FPA_QUE0_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(0)
+#define CVMX_FPA_QUE1_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(1)
+#define CVMX_FPA_QUE2_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(2)
+#define CVMX_FPA_QUE3_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(3)
+#define CVMX_FPA_QUE4_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(4)
+#define CVMX_FPA_QUE5_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(5)
+#define CVMX_FPA_QUE6_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(6)
+#define CVMX_FPA_QUE7_PAGE_INDEX CVMX_FPA_QUEX_PAGE_INDEX(7)
+static inline uint64_t CVMX_FPA_QUEX_AVAILABLE(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000098ull) + (offset & 7) * 8;
+}
+
+static inline uint64_t CVMX_FPA_QUEX_PAGE_INDEX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00011800280000F0ull) + (offset & 7) * 8;
+}
+
+#define CVMX_FPA_QUE_ACT CVMX_FPA_QUE_ACT_FUNC()
+static inline uint64_t CVMX_FPA_QUE_ACT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000138ull);
+}
+
+#define CVMX_FPA_QUE_EXP CVMX_FPA_QUE_EXP_FUNC()
+static inline uint64_t CVMX_FPA_QUE_EXP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180028000130ull);
+}
+
+#define CVMX_FPA_WART_CTL CVMX_FPA_WART_CTL_FUNC()
+static inline uint64_t CVMX_FPA_WART_CTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800280000D8ull);
+}
+
+#define CVMX_FPA_WART_STATUS CVMX_FPA_WART_STATUS_FUNC()
+static inline uint64_t CVMX_FPA_WART_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800280000E0ull);
+}
+
+static inline uint64_t CVMX_GMXX_BAD_REG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000518ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_BIST(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000400ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_CLK_EN(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080007F0ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_HG2_CONTROL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000550ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_INF_MODE(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080007F8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_NXA_ADR(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000510ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_PRTX_CBFC_CTL(unsigned long offset,
+					       unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000580ull) + ((offset & 0) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_PRTX_CFG(unsigned long offset,
+					  unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000010ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CAM0(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000180ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CAM1(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000188ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CAM2(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000190ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CAM3(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000198ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CAM4(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080001A0ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CAM5(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080001A8ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CAM_EN(unsigned long offset,
+						unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000108ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_ADR_CTL(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000100ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_DECISION(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000040ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_FRM_CHK(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000020ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_FRM_CTL(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000018ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_FRM_MAX(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000030ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_FRM_MIN(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000028ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_IFG(unsigned long offset,
+					 unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000058ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_INT_EN(unsigned long offset,
+					    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000008ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_INT_REG(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000000ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_JABBER(unsigned long offset,
+					    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000038ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_PAUSE_DROP_TIME(unsigned long offset,
+						     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000068ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_RX_INBND(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000060ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_CTL(unsigned long offset,
+					       unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000050ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_OCTS(unsigned long offset,
+						unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000088ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_OCTS_CTL(unsigned long offset,
+						    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000098ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_OCTS_DMAC(unsigned long offset,
+						     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080000A8ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_OCTS_DRP(unsigned long offset,
+						    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080000B8ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_PKTS(unsigned long offset,
+						unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000080ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_PKTS_BAD(unsigned long offset,
+						    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080000C0ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_PKTS_CTL(unsigned long offset,
+						    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000090ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_PKTS_DMAC(unsigned long offset,
+						     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080000A0ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_STATS_PKTS_DRP(unsigned long offset,
+						    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080000B0ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RXX_UDD_SKP(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000048ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_RX_BP_DROPX(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000420ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_RX_BP_OFFX(unsigned long offset,
+					    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000460ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_RX_BP_ONX(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000440ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_RX_HG2_STATUS(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000548ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_RX_PASS_EN(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080005F8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_RX_PASS_MAPX(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000600ull) + ((offset & 15) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_RX_PRTS(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000410ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_RX_PRT_INFO(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004E8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_RX_TX_STATUS(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080007E8ull) +
+	    (block_id & 0) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_RX_XAUI_BAD_COL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000538ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_RX_XAUI_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000530ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_SMACX(unsigned long offset,
+				       unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000230ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_STAT_BP(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000520ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_APPEND(unsigned long offset,
+					    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000218ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_BURST(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000228ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_CBFC_XOFF(unsigned long offset,
+					       unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080005A0ull) + ((offset & 0) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_CBFC_XON(unsigned long offset,
+					      unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080005C0ull) + ((offset & 0) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_CLK(unsigned long offset,
+					 unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000208ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_CTL(unsigned long offset,
+					 unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000270ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_MIN_PKT(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000240ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL(unsigned long offset,
+							unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000248ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_PAUSE_PKT_TIME(unsigned long offset,
+						    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000238ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_PAUSE_TOGO(unsigned long offset,
+						unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000258ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_PAUSE_ZERO(unsigned long offset,
+						unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000260ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_SGMII_CTL(unsigned long offset,
+					       unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000300ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_SLOT(unsigned long offset,
+					  unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000220ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_SOFT_PAUSE(unsigned long offset,
+						unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000250ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT0(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000280ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT1(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000288ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT2(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000290ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT3(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000298ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT4(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080002A0ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT5(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080002A8ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT6(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080002B0ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT7(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080002B8ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT8(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080002C0ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STAT9(unsigned long offset,
+					   unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080002C8ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_STATS_CTL(unsigned long offset,
+					       unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000268ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TXX_THRESH(unsigned long offset,
+					    unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000210ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0x10000ull) * 2048;
+}
+
+static inline uint64_t CVMX_GMXX_TX_BP(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004D0ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_CLK_MSKX(unsigned long offset,
+					     unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000780ull) + ((offset & 1) +
+							 (block_id & 0) *
+							 0x0ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_TX_COL_ATTEMPT(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000498ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_CORRUPT(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004D8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_HG2_REG1(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000558ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_HG2_REG2(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000560ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_IFG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000488ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_INT_EN(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000508ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_INT_REG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000500ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_JAM(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000490ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_LFSR(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004F8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_OVR_BP(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004C8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_PAUSE_PKT_DMAC(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004A0ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_PAUSE_PKT_TYPE(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004A8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_PRTS(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000480ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_SPI_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004C0ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_SPI_DRAIN(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004E0ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_SPI_MAX(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004B0ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_SPI_ROUNDX(unsigned long offset,
+					       unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000680ull) + ((offset & 31) +
+							 (block_id & 1) *
+							 0x1000000ull) * 8;
+}
+
+static inline uint64_t CVMX_GMXX_TX_SPI_THRESH(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800080004B8ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_TX_XAUI_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000528ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GMXX_XAUI_EXT_LOOPBACK(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180008000540ull) +
+	    (block_id & 1) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_GPIO_BIT_CFGX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000800ull) + (offset & 15) * 8;
+}
+
+#define CVMX_GPIO_BOOT_ENA CVMX_GPIO_BOOT_ENA_FUNC()
+static inline uint64_t CVMX_GPIO_BOOT_ENA_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00010700000008A8ull);
+}
+
+static inline uint64_t CVMX_GPIO_CLK_GENX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00010700000008C0ull) + (offset & 3) * 8;
+}
+
+#define CVMX_GPIO_DBG_ENA CVMX_GPIO_DBG_ENA_FUNC()
+static inline uint64_t CVMX_GPIO_DBG_ENA_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00010700000008A0ull);
+}
+
+#define CVMX_GPIO_INT_CLR CVMX_GPIO_INT_CLR_FUNC()
+static inline uint64_t CVMX_GPIO_INT_CLR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000898ull);
+}
+
+#define CVMX_GPIO_RX_DAT CVMX_GPIO_RX_DAT_FUNC()
+static inline uint64_t CVMX_GPIO_RX_DAT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000880ull);
+}
+
+#define CVMX_GPIO_TX_CLR CVMX_GPIO_TX_CLR_FUNC()
+static inline uint64_t CVMX_GPIO_TX_CLR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000890ull);
+}
+
+#define CVMX_GPIO_TX_SET CVMX_GPIO_TX_SET_FUNC()
+static inline uint64_t CVMX_GPIO_TX_SET_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000888ull);
+}
+
+static inline uint64_t CVMX_GPIO_XBIT_CFGX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001070000000900ull) + (offset & 31) * 8 -
+	    8 * 16;
+}
+
+#define CVMX_IOB_BIST_STATUS CVMX_IOB_BIST_STATUS_FUNC()
+static inline uint64_t CVMX_IOB_BIST_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F00007F8ull);
+}
+
+#define CVMX_IOB_CTL_STATUS CVMX_IOB_CTL_STATUS_FUNC()
+static inline uint64_t CVMX_IOB_CTL_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000050ull);
+}
+
+#define CVMX_IOB_DWB_PRI_CNT CVMX_IOB_DWB_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_DWB_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000028ull);
+}
+
+#define CVMX_IOB_FAU_TIMEOUT CVMX_IOB_FAU_TIMEOUT_FUNC()
+static inline uint64_t CVMX_IOB_FAU_TIMEOUT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000000ull);
+}
+
+#define CVMX_IOB_I2C_PRI_CNT CVMX_IOB_I2C_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_I2C_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000010ull);
+}
+
+#define CVMX_IOB_INB_CONTROL_MATCH CVMX_IOB_INB_CONTROL_MATCH_FUNC()
+static inline uint64_t CVMX_IOB_INB_CONTROL_MATCH_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000078ull);
+}
+
+#define CVMX_IOB_INB_CONTROL_MATCH_ENB CVMX_IOB_INB_CONTROL_MATCH_ENB_FUNC()
+static inline uint64_t CVMX_IOB_INB_CONTROL_MATCH_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000088ull);
+}
+
+#define CVMX_IOB_INB_DATA_MATCH CVMX_IOB_INB_DATA_MATCH_FUNC()
+static inline uint64_t CVMX_IOB_INB_DATA_MATCH_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000070ull);
+}
+
+#define CVMX_IOB_INB_DATA_MATCH_ENB CVMX_IOB_INB_DATA_MATCH_ENB_FUNC()
+static inline uint64_t CVMX_IOB_INB_DATA_MATCH_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000080ull);
+}
+
+#define CVMX_IOB_INT_ENB CVMX_IOB_INT_ENB_FUNC()
+static inline uint64_t CVMX_IOB_INT_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000060ull);
+}
+
+#define CVMX_IOB_INT_SUM CVMX_IOB_INT_SUM_FUNC()
+static inline uint64_t CVMX_IOB_INT_SUM_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000058ull);
+}
+
+#define CVMX_IOB_N2C_L2C_PRI_CNT CVMX_IOB_N2C_L2C_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_N2C_L2C_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000020ull);
+}
+
+#define CVMX_IOB_N2C_RSP_PRI_CNT CVMX_IOB_N2C_RSP_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_N2C_RSP_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000008ull);
+}
+
+#define CVMX_IOB_OUTB_COM_PRI_CNT CVMX_IOB_OUTB_COM_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_OUTB_COM_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000040ull);
+}
+
+#define CVMX_IOB_OUTB_CONTROL_MATCH CVMX_IOB_OUTB_CONTROL_MATCH_FUNC()
+static inline uint64_t CVMX_IOB_OUTB_CONTROL_MATCH_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000098ull);
+}
+
+#define CVMX_IOB_OUTB_CONTROL_MATCH_ENB CVMX_IOB_OUTB_CONTROL_MATCH_ENB_FUNC()
+static inline uint64_t CVMX_IOB_OUTB_CONTROL_MATCH_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F00000A8ull);
+}
+
+#define CVMX_IOB_OUTB_DATA_MATCH CVMX_IOB_OUTB_DATA_MATCH_FUNC()
+static inline uint64_t CVMX_IOB_OUTB_DATA_MATCH_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000090ull);
+}
+
+#define CVMX_IOB_OUTB_DATA_MATCH_ENB CVMX_IOB_OUTB_DATA_MATCH_ENB_FUNC()
+static inline uint64_t CVMX_IOB_OUTB_DATA_MATCH_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F00000A0ull);
+}
+
+#define CVMX_IOB_OUTB_FPA_PRI_CNT CVMX_IOB_OUTB_FPA_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_OUTB_FPA_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000048ull);
+}
+
+#define CVMX_IOB_OUTB_REQ_PRI_CNT CVMX_IOB_OUTB_REQ_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_OUTB_REQ_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000038ull);
+}
+
+#define CVMX_IOB_P2C_REQ_PRI_CNT CVMX_IOB_P2C_REQ_PRI_CNT_FUNC()
+static inline uint64_t CVMX_IOB_P2C_REQ_PRI_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000018ull);
+}
+
+#define CVMX_IOB_PKT_ERR CVMX_IOB_PKT_ERR_FUNC()
+static inline uint64_t CVMX_IOB_PKT_ERR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800F0000068ull);
+}
+
+#define CVMX_IPD_1ST_MBUFF_SKIP CVMX_IPD_1ST_MBUFF_SKIP_FUNC()
+static inline uint64_t CVMX_IPD_1ST_MBUFF_SKIP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000000ull);
+}
+
+#define CVMX_IPD_1st_NEXT_PTR_BACK CVMX_IPD_1st_NEXT_PTR_BACK_FUNC()
+static inline uint64_t CVMX_IPD_1st_NEXT_PTR_BACK_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000150ull);
+}
+
+#define CVMX_IPD_2nd_NEXT_PTR_BACK CVMX_IPD_2nd_NEXT_PTR_BACK_FUNC()
+static inline uint64_t CVMX_IPD_2nd_NEXT_PTR_BACK_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000158ull);
+}
+
+#define CVMX_IPD_BIST_STATUS CVMX_IPD_BIST_STATUS_FUNC()
+static inline uint64_t CVMX_IPD_BIST_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F00000007F8ull);
+}
+
+#define CVMX_IPD_BP_PRT_RED_END CVMX_IPD_BP_PRT_RED_END_FUNC()
+static inline uint64_t CVMX_IPD_BP_PRT_RED_END_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000328ull);
+}
+
+#define CVMX_IPD_CLK_COUNT CVMX_IPD_CLK_COUNT_FUNC()
+static inline uint64_t CVMX_IPD_CLK_COUNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000338ull);
+}
+
+#define CVMX_IPD_CTL_STATUS CVMX_IPD_CTL_STATUS_FUNC()
+static inline uint64_t CVMX_IPD_CTL_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000018ull);
+}
+
+#define CVMX_IPD_INT_ENB CVMX_IPD_INT_ENB_FUNC()
+static inline uint64_t CVMX_IPD_INT_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000160ull);
+}
+
+#define CVMX_IPD_INT_SUM CVMX_IPD_INT_SUM_FUNC()
+static inline uint64_t CVMX_IPD_INT_SUM_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000168ull);
+}
+
+#define CVMX_IPD_NOT_1ST_MBUFF_SKIP CVMX_IPD_NOT_1ST_MBUFF_SKIP_FUNC()
+static inline uint64_t CVMX_IPD_NOT_1ST_MBUFF_SKIP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000008ull);
+}
+
+#define CVMX_IPD_PACKET_MBUFF_SIZE CVMX_IPD_PACKET_MBUFF_SIZE_FUNC()
+static inline uint64_t CVMX_IPD_PACKET_MBUFF_SIZE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000010ull);
+}
+
+#define CVMX_IPD_PKT_PTR_VALID CVMX_IPD_PKT_PTR_VALID_FUNC()
+static inline uint64_t CVMX_IPD_PKT_PTR_VALID_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000358ull);
+}
+
+static inline uint64_t CVMX_IPD_PORTX_BP_PAGE_CNT(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000028ull) + (offset & 63) * 8;
+}
+
+static inline uint64_t CVMX_IPD_PORTX_BP_PAGE_CNT2(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000368ull) + (offset & 63) * 8 -
+	    8 * 36;
+}
+
+static inline uint64_t CVMX_IPD_PORT_BP_COUNTERS2_PAIRX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000388ull) + (offset & 63) * 8 -
+	    8 * 36;
+}
+
+static inline uint64_t CVMX_IPD_PORT_BP_COUNTERS_PAIRX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F00000001B8ull) + (offset & 63) * 8;
+}
+
+static inline uint64_t CVMX_IPD_PORT_QOS_INTX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000808ull) + (offset & 7) * 8;
+}
+
+static inline uint64_t CVMX_IPD_PORT_QOS_INT_ENBX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000848ull) + (offset & 7) * 8;
+}
+
+static inline uint64_t CVMX_IPD_PORT_QOS_X_CNT(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000888ull) + (offset & 511) * 8;
+}
+
+#define CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL_FUNC()
+static inline uint64_t CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000348ull);
+}
+
+#define CVMX_IPD_PRC_PORT_PTR_FIFO_CTL CVMX_IPD_PRC_PORT_PTR_FIFO_CTL_FUNC()
+static inline uint64_t CVMX_IPD_PRC_PORT_PTR_FIFO_CTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000350ull);
+}
+
+#define CVMX_IPD_PTR_COUNT CVMX_IPD_PTR_COUNT_FUNC()
+static inline uint64_t CVMX_IPD_PTR_COUNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000320ull);
+}
+
+#define CVMX_IPD_PWP_PTR_FIFO_CTL CVMX_IPD_PWP_PTR_FIFO_CTL_FUNC()
+static inline uint64_t CVMX_IPD_PWP_PTR_FIFO_CTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000340ull);
+}
+
+#define CVMX_IPD_QOS0_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(0)
+#define CVMX_IPD_QOS1_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(1)
+#define CVMX_IPD_QOS2_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(2)
+#define CVMX_IPD_QOS3_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(3)
+#define CVMX_IPD_QOS4_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(4)
+#define CVMX_IPD_QOS5_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(5)
+#define CVMX_IPD_QOS6_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(6)
+#define CVMX_IPD_QOS7_RED_MARKS CVMX_IPD_QOSX_RED_MARKS(7)
+static inline uint64_t CVMX_IPD_QOSX_RED_MARKS(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000178ull) + (offset & 7) * 8;
+}
+
+#define CVMX_IPD_QUE0_FREE_PAGE_CNT CVMX_IPD_QUE0_FREE_PAGE_CNT_FUNC()
+static inline uint64_t CVMX_IPD_QUE0_FREE_PAGE_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000330ull);
+}
+
+#define CVMX_IPD_RED_PORT_ENABLE CVMX_IPD_RED_PORT_ENABLE_FUNC()
+static inline uint64_t CVMX_IPD_RED_PORT_ENABLE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F00000002D8ull);
+}
+
+#define CVMX_IPD_RED_PORT_ENABLE2 CVMX_IPD_RED_PORT_ENABLE2_FUNC()
+static inline uint64_t CVMX_IPD_RED_PORT_ENABLE2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F00000003A8ull);
+}
+
+#define CVMX_IPD_RED_QUE0_PARAM CVMX_IPD_RED_QUEX_PARAM(0)
+#define CVMX_IPD_RED_QUE1_PARAM CVMX_IPD_RED_QUEX_PARAM(1)
+#define CVMX_IPD_RED_QUE2_PARAM CVMX_IPD_RED_QUEX_PARAM(2)
+#define CVMX_IPD_RED_QUE3_PARAM CVMX_IPD_RED_QUEX_PARAM(3)
+#define CVMX_IPD_RED_QUE4_PARAM CVMX_IPD_RED_QUEX_PARAM(4)
+#define CVMX_IPD_RED_QUE5_PARAM CVMX_IPD_RED_QUEX_PARAM(5)
+#define CVMX_IPD_RED_QUE6_PARAM CVMX_IPD_RED_QUEX_PARAM(6)
+#define CVMX_IPD_RED_QUE7_PARAM CVMX_IPD_RED_QUEX_PARAM(7)
+static inline uint64_t CVMX_IPD_RED_QUEX_PARAM(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x00014F00000002E0ull) + (offset & 7) * 8;
+}
+
+#define CVMX_IPD_SUB_PORT_BP_PAGE_CNT CVMX_IPD_SUB_PORT_BP_PAGE_CNT_FUNC()
+static inline uint64_t CVMX_IPD_SUB_PORT_BP_PAGE_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000148ull);
+}
+
+#define CVMX_IPD_SUB_PORT_FCS CVMX_IPD_SUB_PORT_FCS_FUNC()
+static inline uint64_t CVMX_IPD_SUB_PORT_FCS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000170ull);
+}
+
+#define CVMX_IPD_SUB_PORT_QOS_CNT CVMX_IPD_SUB_PORT_QOS_CNT_FUNC()
+static inline uint64_t CVMX_IPD_SUB_PORT_QOS_CNT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000800ull);
+}
+
+#define CVMX_IPD_WQE_FPA_QUEUE CVMX_IPD_WQE_FPA_QUEUE_FUNC()
+static inline uint64_t CVMX_IPD_WQE_FPA_QUEUE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000020ull);
+}
+
+#define CVMX_IPD_WQE_PTR_VALID CVMX_IPD_WQE_PTR_VALID_FUNC()
+static inline uint64_t CVMX_IPD_WQE_PTR_VALID_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00014F0000000360ull);
+}
+
+#define CVMX_KEY_BIST_REG CVMX_KEY_BIST_REG_FUNC()
+static inline uint64_t CVMX_KEY_BIST_REG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180020000018ull);
+}
+
+#define CVMX_KEY_CTL_STATUS CVMX_KEY_CTL_STATUS_FUNC()
+static inline uint64_t CVMX_KEY_CTL_STATUS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180020000010ull);
+}
+
+#define CVMX_KEY_INT_ENB CVMX_KEY_INT_ENB_FUNC()
+static inline uint64_t CVMX_KEY_INT_ENB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180020000008ull);
+}
+
+#define CVMX_KEY_INT_SUM CVMX_KEY_INT_SUM_FUNC()
+static inline uint64_t CVMX_KEY_INT_SUM_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180020000000ull);
+}
+
+#define CVMX_L2C_BST0 CVMX_L2C_BST0_FUNC()
+static inline uint64_t CVMX_L2C_BST0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800007F8ull);
+}
+
+#define CVMX_L2C_BST1 CVMX_L2C_BST1_FUNC()
+static inline uint64_t CVMX_L2C_BST1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800007F0ull);
+}
+
+#define CVMX_L2C_BST2 CVMX_L2C_BST2_FUNC()
+static inline uint64_t CVMX_L2C_BST2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800007E8ull);
+}
+
+#define CVMX_L2C_CFG CVMX_L2C_CFG_FUNC()
+static inline uint64_t CVMX_L2C_CFG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000000ull);
+}
+
+#define CVMX_L2C_DBG CVMX_L2C_DBG_FUNC()
+static inline uint64_t CVMX_L2C_DBG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000030ull);
+}
+
+#define CVMX_L2C_DUT CVMX_L2C_DUT_FUNC()
+static inline uint64_t CVMX_L2C_DUT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000050ull);
+}
+
+#define CVMX_L2C_GRPWRR0 CVMX_L2C_GRPWRR0_FUNC()
+static inline uint64_t CVMX_L2C_GRPWRR0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000C8ull);
+}
+
+#define CVMX_L2C_GRPWRR1 CVMX_L2C_GRPWRR1_FUNC()
+static inline uint64_t CVMX_L2C_GRPWRR1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000D0ull);
+}
+
+#define CVMX_L2C_INT_EN CVMX_L2C_INT_EN_FUNC()
+static inline uint64_t CVMX_L2C_INT_EN_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000100ull);
+}
+
+#define CVMX_L2C_INT_STAT CVMX_L2C_INT_STAT_FUNC()
+static inline uint64_t CVMX_L2C_INT_STAT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000F8ull);
+}
+
+#define CVMX_L2C_LCKBASE CVMX_L2C_LCKBASE_FUNC()
+static inline uint64_t CVMX_L2C_LCKBASE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000058ull);
+}
+
+#define CVMX_L2C_LCKOFF CVMX_L2C_LCKOFF_FUNC()
+static inline uint64_t CVMX_L2C_LCKOFF_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000060ull);
+}
+
+#define CVMX_L2C_LFB0 CVMX_L2C_LFB0_FUNC()
+static inline uint64_t CVMX_L2C_LFB0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000038ull);
+}
+
+#define CVMX_L2C_LFB1 CVMX_L2C_LFB1_FUNC()
+static inline uint64_t CVMX_L2C_LFB1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000040ull);
+}
+
+#define CVMX_L2C_LFB2 CVMX_L2C_LFB2_FUNC()
+static inline uint64_t CVMX_L2C_LFB2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000048ull);
+}
+
+#define CVMX_L2C_LFB3 CVMX_L2C_LFB3_FUNC()
+static inline uint64_t CVMX_L2C_LFB3_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000B8ull);
+}
+
+#define CVMX_L2C_OOB CVMX_L2C_OOB_FUNC()
+static inline uint64_t CVMX_L2C_OOB_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000D8ull);
+}
+
+#define CVMX_L2C_OOB1 CVMX_L2C_OOB1_FUNC()
+static inline uint64_t CVMX_L2C_OOB1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000E0ull);
+}
+
+#define CVMX_L2C_OOB2 CVMX_L2C_OOB2_FUNC()
+static inline uint64_t CVMX_L2C_OOB2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000E8ull);
+}
+
+#define CVMX_L2C_OOB3 CVMX_L2C_OOB3_FUNC()
+static inline uint64_t CVMX_L2C_OOB3_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000F0ull);
+}
+
+#define CVMX_L2C_PFC0 CVMX_L2C_PFCX(0)
+#define CVMX_L2C_PFC1 CVMX_L2C_PFCX(1)
+#define CVMX_L2C_PFC2 CVMX_L2C_PFCX(2)
+#define CVMX_L2C_PFC3 CVMX_L2C_PFCX(3)
+#define CVMX_L2C_PFCTL CVMX_L2C_PFCTL_FUNC()
+static inline uint64_t CVMX_L2C_PFCTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000090ull);
+}
+
+static inline uint64_t CVMX_L2C_PFCX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000098ull) + (offset & 3) * 8;
+}
+
+#define CVMX_L2C_PPGRP CVMX_L2C_PPGRP_FUNC()
+static inline uint64_t CVMX_L2C_PPGRP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800000C0ull);
+}
+
+#define CVMX_L2C_SPAR0 CVMX_L2C_SPAR0_FUNC()
+static inline uint64_t CVMX_L2C_SPAR0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000068ull);
+}
+
+#define CVMX_L2C_SPAR1 CVMX_L2C_SPAR1_FUNC()
+static inline uint64_t CVMX_L2C_SPAR1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000070ull);
+}
+
+#define CVMX_L2C_SPAR2 CVMX_L2C_SPAR2_FUNC()
+static inline uint64_t CVMX_L2C_SPAR2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000078ull);
+}
+
+#define CVMX_L2C_SPAR3 CVMX_L2C_SPAR3_FUNC()
+static inline uint64_t CVMX_L2C_SPAR3_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000080ull);
+}
+
+#define CVMX_L2C_SPAR4 CVMX_L2C_SPAR4_FUNC()
+static inline uint64_t CVMX_L2C_SPAR4_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000088ull);
+}
+
+#define CVMX_L2D_BST0 CVMX_L2D_BST0_FUNC()
+static inline uint64_t CVMX_L2D_BST0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000780ull);
+}
+
+#define CVMX_L2D_BST1 CVMX_L2D_BST1_FUNC()
+static inline uint64_t CVMX_L2D_BST1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000788ull);
+}
+
+#define CVMX_L2D_BST2 CVMX_L2D_BST2_FUNC()
+static inline uint64_t CVMX_L2D_BST2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000790ull);
+}
+
+#define CVMX_L2D_BST3 CVMX_L2D_BST3_FUNC()
+static inline uint64_t CVMX_L2D_BST3_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000798ull);
+}
+
+#define CVMX_L2D_ERR CVMX_L2D_ERR_FUNC()
+static inline uint64_t CVMX_L2D_ERR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000010ull);
+}
+
+#define CVMX_L2D_FADR CVMX_L2D_FADR_FUNC()
+static inline uint64_t CVMX_L2D_FADR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000018ull);
+}
+
+#define CVMX_L2D_FSYN0 CVMX_L2D_FSYN0_FUNC()
+static inline uint64_t CVMX_L2D_FSYN0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000020ull);
+}
+
+#define CVMX_L2D_FSYN1 CVMX_L2D_FSYN1_FUNC()
+static inline uint64_t CVMX_L2D_FSYN1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000028ull);
+}
+
+#define CVMX_L2D_FUS0 CVMX_L2D_FUS0_FUNC()
+static inline uint64_t CVMX_L2D_FUS0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800007A0ull);
+}
+
+#define CVMX_L2D_FUS1 CVMX_L2D_FUS1_FUNC()
+static inline uint64_t CVMX_L2D_FUS1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800007A8ull);
+}
+
+#define CVMX_L2D_FUS2 CVMX_L2D_FUS2_FUNC()
+static inline uint64_t CVMX_L2D_FUS2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800007B0ull);
+}
+
+#define CVMX_L2D_FUS3 CVMX_L2D_FUS3_FUNC()
+static inline uint64_t CVMX_L2D_FUS3_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800800007B8ull);
+}
+
+#define CVMX_L2T_ERR CVMX_L2T_ERR_FUNC()
+static inline uint64_t CVMX_L2T_ERR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180080000008ull);
+}
+
+#define CVMX_LED_BLINK CVMX_LED_BLINK_FUNC()
+static inline uint64_t CVMX_LED_BLINK_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A48ull);
+}
+
+#define CVMX_LED_CLK_PHASE CVMX_LED_CLK_PHASE_FUNC()
+static inline uint64_t CVMX_LED_CLK_PHASE_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A08ull);
+}
+
+#define CVMX_LED_CYLON CVMX_LED_CYLON_FUNC()
+static inline uint64_t CVMX_LED_CYLON_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001AF8ull);
+}
+
+#define CVMX_LED_DBG CVMX_LED_DBG_FUNC()
+static inline uint64_t CVMX_LED_DBG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A18ull);
+}
+
+#define CVMX_LED_EN CVMX_LED_EN_FUNC()
+static inline uint64_t CVMX_LED_EN_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A00ull);
+}
+
+#define CVMX_LED_POLARITY CVMX_LED_POLARITY_FUNC()
+static inline uint64_t CVMX_LED_POLARITY_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A50ull);
+}
+
+#define CVMX_LED_PRT CVMX_LED_PRT_FUNC()
+static inline uint64_t CVMX_LED_PRT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A10ull);
+}
+
+#define CVMX_LED_PRT_FMT CVMX_LED_PRT_FMT_FUNC()
+static inline uint64_t CVMX_LED_PRT_FMT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A30ull);
+}
+
+static inline uint64_t CVMX_LED_PRT_STATUSX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A80ull) + (offset & 7) * 8;
+}
+
+static inline uint64_t CVMX_LED_UDD_CNTX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A20ull) + (offset & 1) * 8;
+}
+
+static inline uint64_t CVMX_LED_UDD_DATX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001A38ull) + (offset & 1) * 8;
+}
+
+static inline uint64_t CVMX_LED_UDD_DAT_CLRX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001AC8ull) + (offset & 1) * 16;
+}
+
+static inline uint64_t CVMX_LED_UDD_DAT_SETX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001AC0ull) + (offset & 1) * 16;
+}
+
+static inline uint64_t CVMX_LMCX_BIST_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000F0ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_BIST_RESULT(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000F8ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_COMP_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000028ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000010ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_CTL1(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000090ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_DCLK_CNT_HI(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000070ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_DCLK_CNT_LO(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000068ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_DCLK_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000B8ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_DDR2_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000018ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_DELAY_CFG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000088ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_DLL_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000C0ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_DUAL_MEMCFG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000098ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_ECC_SYND(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000038ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_FADR(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000020ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_IFB_CNT_HI(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000050ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_IFB_CNT_LO(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000048ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_MEM_CFG0(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000000ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_MEM_CFG1(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000008ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_NXM(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000C8ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_OPS_CNT_HI(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000060ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_OPS_CNT_LO(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000058ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_PLL_BWCTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000040ull) +
+	    (block_id & 0) * 0x8000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_PLL_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000A8ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_PLL_STATUS(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000B0ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_READ_LEVEL_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000140ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_READ_LEVEL_DBG(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000148ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_READ_LEVEL_RANKX(unsigned long offset,
+						  unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000100ull) + ((offset & 3) +
+							 (block_id & 1) *
+							 0xC000000ull) * 8;
+}
+
+static inline uint64_t CVMX_LMCX_RODT_COMP_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x00011800880000A0ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_RODT_CTL(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000078ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_WODT_CTL0(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000030ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+static inline uint64_t CVMX_LMCX_WODT_CTL1(unsigned long block_id)
+{
+	return CVMX_ADD_IO_SEG(0x0001180088000080ull) +
+	    (block_id & 1) * 0x60000000ull;
+}
+
+#define CVMX_MIO_BOOT_BIST_STAT CVMX_MIO_BOOT_BIST_STAT_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_BIST_STAT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800000000F8ull);
+}
+
+#define CVMX_MIO_BOOT_COMP CVMX_MIO_BOOT_COMP_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_COMP_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800000000B8ull);
+}
+
+static inline uint64_t CVMX_MIO_BOOT_DMA_CFGX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000100ull) + (offset & 3) * 8;
+}
+
+static inline uint64_t CVMX_MIO_BOOT_DMA_INTX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000138ull) + (offset & 3) * 8;
+}
+
+static inline uint64_t CVMX_MIO_BOOT_DMA_INT_ENX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000150ull) + (offset & 3) * 8;
+}
+
+static inline uint64_t CVMX_MIO_BOOT_DMA_TIMX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000120ull) + (offset & 3) * 8;
+}
+
+#define CVMX_MIO_BOOT_ERR CVMX_MIO_BOOT_ERR_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_ERR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800000000A0ull);
+}
+
+#define CVMX_MIO_BOOT_INT CVMX_MIO_BOOT_INT_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_INT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800000000A8ull);
+}
+
+#define CVMX_MIO_BOOT_LOC_ADR CVMX_MIO_BOOT_LOC_ADR_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_LOC_ADR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000090ull);
+}
+
+static inline uint64_t CVMX_MIO_BOOT_LOC_CFGX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000080ull) + (offset & 1) * 8;
+}
+
+#define CVMX_MIO_BOOT_LOC_DAT CVMX_MIO_BOOT_LOC_DAT_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_LOC_DAT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000098ull);
+}
+
+#define CVMX_MIO_BOOT_PIN_DEFS CVMX_MIO_BOOT_PIN_DEFS_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_PIN_DEFS_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800000000C0ull);
+}
+
+static inline uint64_t CVMX_MIO_BOOT_REG_CFGX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000000ull) + (offset & 7) * 8;
+}
+
+static inline uint64_t CVMX_MIO_BOOT_REG_TIMX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000040ull) + (offset & 7) * 8;
+}
+
+#define CVMX_MIO_BOOT_THR CVMX_MIO_BOOT_THR_FUNC()
+static inline uint64_t CVMX_MIO_BOOT_THR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x00011800000000B0ull);
+}
+
+static inline uint64_t CVMX_MIO_FUS_BNK_DATX(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001520ull) + (offset & 3) * 8;
+}
+
+#define CVMX_MIO_FUS_DAT0 CVMX_MIO_FUS_DAT0_FUNC()
+static inline uint64_t CVMX_MIO_FUS_DAT0_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001400ull);
+}
+
+#define CVMX_MIO_FUS_DAT1 CVMX_MIO_FUS_DAT1_FUNC()
+static inline uint64_t CVMX_MIO_FUS_DAT1_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001408ull);
+}
+
+#define CVMX_MIO_FUS_DAT2 CVMX_MIO_FUS_DAT2_FUNC()
+static inline uint64_t CVMX_MIO_FUS_DAT2_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001410ull);
+}
+
+#define CVMX_MIO_FUS_DAT3 CVMX_MIO_FUS_DAT3_FUNC()
+static inline uint64_t CVMX_MIO_FUS_DAT3_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001418ull);
+}
+
+#define CVMX_MIO_FUS_EMA CVMX_MIO_FUS_EMA_FUNC()
+static inline uint64_t CVMX_MIO_FUS_EMA_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001550ull);
+}
+
+#define CVMX_MIO_FUS_PDF CVMX_MIO_FUS_PDF_FUNC()
+static inline uint64_t CVMX_MIO_FUS_PDF_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001420ull);
+}
+
+#define CVMX_MIO_FUS_PLL CVMX_MIO_FUS_PLL_FUNC()
+static inline uint64_t CVMX_MIO_FUS_PLL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001580ull);
+}
+
+#define CVMX_MIO_FUS_PROG CVMX_MIO_FUS_PROG_FUNC()
+static inline uint64_t CVMX_MIO_FUS_PROG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001510ull);
+}
+
+#define CVMX_MIO_FUS_PROG_TIMES CVMX_MIO_FUS_PROG_TIMES_FUNC()
+static inline uint64_t CVMX_MIO_FUS_PROG_TIMES_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001518ull);
+}
+
+#define CVMX_MIO_FUS_RCMD CVMX_MIO_FUS_RCMD_FUNC()
+static inline uint64_t CVMX_MIO_FUS_RCMD_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001500ull);
+}
+
+#define CVMX_MIO_FUS_SPR_REPAIR_RES CVMX_MIO_FUS_SPR_REPAIR_RES_FUNC()
+static inline uint64_t CVMX_MIO_FUS_SPR_REPAIR_RES_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001548ull);
+}
+
+#define CVMX_MIO_FUS_SPR_REPAIR_SUM CVMX_MIO_FUS_SPR_REPAIR_SUM_FUNC()
+static inline uint64_t CVMX_MIO_FUS_SPR_REPAIR_SUM_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001540ull);
+}
+
+#define CVMX_MIO_FUS_UNLOCK CVMX_MIO_FUS_UNLOCK_FUNC()
+static inline uint64_t CVMX_MIO_FUS_UNLOCK_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001578ull);
+}
+
+#define CVMX_MIO_FUS_WADR CVMX_MIO_FUS_WADR_FUNC()
+static inline uint64_t CVMX_MIO_FUS_WADR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001508ull);
+}
+
+#define CVMX_MIO_NDF_DMA_CFG CVMX_MIO_NDF_DMA_CFG_FUNC()
+static inline uint64_t CVMX_MIO_NDF_DMA_CFG_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000168ull);
+}
+
+#define CVMX_MIO_NDF_DMA_INT CVMX_MIO_NDF_DMA_INT_FUNC()
+static inline uint64_t CVMX_MIO_NDF_DMA_INT_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000170ull);
+}
+
+#define CVMX_MIO_NDF_DMA_INT_EN CVMX_MIO_NDF_DMA_INT_EN_FUNC()
+static inline uint64_t CVMX_MIO_NDF_DMA_INT_EN_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000178ull);
+}
+
+#define CVMX_MIO_PLL_CTL CVMX_MIO_PLL_CTL_FUNC()
+static inline uint64_t CVMX_MIO_PLL_CTL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001448ull);
+}
+
+#define CVMX_MIO_PLL_SETTING CVMX_MIO_PLL_SETTING_FUNC()
+static inline uint64_t CVMX_MIO_PLL_SETTING_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001440ull);
+}
+
+static inline uint64_t CVMX_MIO_TWSX_INT(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001010ull) + (offset & 1) * 512;
+}
+
+static inline uint64_t CVMX_MIO_TWSX_SW_TWSI(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001000ull) + (offset & 1) * 512;
+}
+
+static inline uint64_t CVMX_MIO_TWSX_SW_TWSI_EXT(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001018ull) + (offset & 1) * 512;
+}
+
+static inline uint64_t CVMX_MIO_TWSX_TWSI_SW(unsigned long offset)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000001008ull) + (offset & 1) * 512;
+}
+
+#define CVMX_MIO_UART2_DLH CVMX_MIO_UART2_DLH_FUNC()
+static inline uint64_t CVMX_MIO_UART2_DLH_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000488ull);
+}
+
+#define CVMX_MIO_UART2_DLL CVMX_MIO_UART2_DLL_FUNC()
+static inline uint64_t CVMX_MIO_UART2_DLL_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000480ull);
+}
+
+#define CVMX_MIO_UART2_FAR CVMX_MIO_UART2_FAR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_FAR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000520ull);
+}
+
+#define CVMX_MIO_UART2_FCR CVMX_MIO_UART2_FCR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_FCR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000450ull);
+}
+
+#define CVMX_MIO_UART2_HTX CVMX_MIO_UART2_HTX_FUNC()
+static inline uint64_t CVMX_MIO_UART2_HTX_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000708ull);
+}
+
+#define CVMX_MIO_UART2_IER CVMX_MIO_UART2_IER_FUNC()
+static inline uint64_t CVMX_MIO_UART2_IER_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000408ull);
+}
+
+#define CVMX_MIO_UART2_IIR CVMX_MIO_UART2_IIR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_IIR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000410ull);
+}
+
+#define CVMX_MIO_UART2_LCR CVMX_MIO_UART2_LCR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_LCR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000418ull);
+}
+
+#define CVMX_MIO_UART2_LSR CVMX_MIO_UART2_LSR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_LSR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000428ull);
+}
+
+#define CVMX_MIO_UART2_MCR CVMX_MIO_UART2_MCR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_MCR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000420ull);
+}
+
+#define CVMX_MIO_UART2_MSR CVMX_MIO_UART2_MSR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_MSR_FUNC(void)
+{
+	return CVMX_ADD_IO_SEG(0x0001180000000430ull);
+}
+
+#define CVMX_MIO_UART2_RBR CVMX_MIO_UART2_RBR_FUNC()
+static inline uint64_t CVMX_MIO_UART2_RBR_FUNC(void)
+{
[… more lines in the raw message]

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-csr-enums.h new file +86 -0

86 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-csr-typedefs.h new file +27517 -0

27,517 lines not on this page · raw message

arch/mips/cavium-octeon/executive/cvmx-csr.h new file +199 -0

199 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.5.6.5

Part of the diff is not shown here. View the raw message.

#7 lore raw

PATCH 7/36 Don't assume boot CPU is CPU0 if MIPS_DISABLE_BOOT_CPU_ZERO set.

MIPS SMP code currently assumes that the boot CPU will be CPU0 of the system. For some systems, this may not be the case.

---
 arch/mips/Kconfig      |    4 ++++
 arch/mips/kernel/smp.c |    2 ++
 2 files changed, 6 insertions(+), 0 deletions(-)
arch/mips/Kconfig +4 -0
index 653574b..7ff95fb 100644
@@ -747,6 +747,10 @@ config HOTPLUG_CPU
 	bool
 	default n
 
+config MIPS_DISABLE_BOOT_CPU_ZERO
+       bool
+       default n
+
 config I8259
 	bool
 
arch/mips/kernel/smp.c +2 -0
index b79ea70..e2597ef 100644
@@ -195,12 +195,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 /* preload SMP state for boot cpu */
 void __devinit smp_prepare_boot_cpu(void)
 {
+#ifndef MIPS_DISABLE_BOOT_CPU_ZERO
 	/*
 	 * This assumes that bootup is always handled by the processor
 	 * with the logic and physical number 0.
 	 */
 	__cpu_number_map[0] = 0;
 	__cpu_logical_map[0] = 0;
+#endif
 	cpu_set(0, phys_cpu_present_map);
 	cpu_set(0, cpu_online_map);
 	cpu_set(0, cpu_callin_map);
Signature · 1 line
1.5.6.5
#8 lore raw

PATCH 8/36 For Cavium OCTEON handle hazards as per the R10000 handling.

For Cavium CPU, we treat the same as R10000, in that all hazards are dealt with in hardware.

---
 arch/mips/include/asm/hazards.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
arch/mips/include/asm/hazards.h +2 -2
index 2de638f..43baed1 100644
@@ -42,7 +42,7 @@ ASMMACRO(_ehb,
 /*
  * TLB hazards
  */
-#if defined(CONFIG_CPU_MIPSR2)
+#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
 
 /*
  * MIPSR2 defines ehb for hazard avoidance
@@ -138,7 +138,7 @@ do {									\
 		__instruction_hazard();					\
 } while (0)
 
-#elif defined(CONFIG_CPU_R10000)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_CAVIUM_OCTEON)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
Signature · 1 line
1.5.6.5
#9 lore raw

PATCH 9/36 Enable mips32 style bitops for Cavium OCTEON.

Enable the basic bitops like __ffs and so forth that would normally be on if we were MIPS32 or MIPS64, but aren't since Cavium sets neither.

---
 arch/mips/include/asm/bitops.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
arch/mips/include/asm/bitops.h +2 -1
index 49df8c4..6f5f225 100644
@@ -558,7 +558,8 @@ static inline void __clear_bit_unlock(unsigned long nr, volatile unsigned long *
 	__clear_bit(nr, addr);
 }
 
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) \
+ || defined(CONFIG_CPU_CAVIUM_OCTEON)
 
 /*
  * Return the bit position (0..63) of the most significant 1 bit in a word
Signature · 1 line
1.5.6.5
#10 lore raw

PATCH 10/36 Cavium OCTEON: Set hwrena and lazily restore CP2 state.

If on Cavium, then be aware of cop2 and hwrena during do_cpu().

---
 arch/mips/kernel/traps.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)
arch/mips/kernel/traps.c +21 -0
index 80b9e07..8e40795 100644
@@ -46,6 +46,7 @@
 #include <asm/mmu_context.h>
 #include <asm/types.h>
 #include <asm/stacktrace.h>
+#include <asm/irq.h>
 
 extern void check_wait(void);
 extern asmlinkage void r4k_wait(void);
@@ -77,6 +78,10 @@ extern asmlinkage void handle_reserved(void);
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
 	struct mips_fpu_struct *ctx, int has_fpu);
 
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
+#endif
+
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 void (*board_nmi_handler_setup)(void);
@@ -844,6 +849,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 	unsigned int opcode;
 	unsigned int cpid;
 	int status;
+	unsigned long __maybe_unused flags;
 
 	die_if_kernel("do_cpu invoked from kernel context!", regs);
 
@@ -899,6 +905,17 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 		return;
 
 	case 2:
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		prefetch(&current->thread.cp2);
+		local_irq_save(flags);
+		KSTK_STATUS(current) |= ST0_CU2;
+		status = read_c0_status();
+		write_c0_status(status | ST0_CU2);
+		octeon_cop2_restore(&(current->thread.cp2));
+		write_c0_status(status & ~ST0_CU2);
+		local_irq_restore(flags);
+		return;
+#endif
 	case 3:
 		break;
 	}
@@ -1472,6 +1489,10 @@ void __cpuinit per_cpu_trap_init(void)
 		write_c0_hwrena(enable);
 	}
 
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+	write_c0_hwrena(0xc000000f); /* Octeon has register 30 and 31 */
+#endif
+
 #ifdef CONFIG_MIPS_MT_SMTC
 	if (!secondaryTC) {
 #endif /* CONFIG_MIPS_MT_SMTC */
Signature · 1 line
1.5.6.5
#11 lore raw

PATCH 11/36 MIPSR2 ebase isn't just CAC_BASE

On mips{32,64}r2, the ebase isn't just CAC_BASE, but also the part of read_c0_ebase() too.

---
 arch/mips/include/asm/cpu-features.h |    4 ++++
 arch/mips/kernel/traps.c             |   11 +++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)
arch/mips/include/asm/cpu-features.h +4 -0
index 5ea701f..1d0cf0a 100644
@@ -101,6 +101,10 @@
 #ifndef cpu_has_pindexed_dcache
 #define cpu_has_pindexed_dcache	(cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
 #endif
+#ifndef cpu_has_ebase
+#define cpu_has_ebase		(cpu_data[0].isa_level == MIPS_CPU_ISA_M32R2 \
+				 || cpu_data[0].isa_level == MIPS_CPU_ISA_M64R2)
+#endif
 
 /*
  * I-Cache snoops remote store.  This only matters on SMP.  Some multiprocessors
arch/mips/kernel/traps.c +7 -4
index 8e40795..cfec89c 100644
@@ -1609,8 +1609,11 @@ void __init trap_init(void)
 
 	if (cpu_has_veic || cpu_has_vint)
 		ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
-	else
+	else {
 		ebase = CAC_BASE;
+		if (cpu_has_ebase)
+			ebase += read_c0_ebase() & 0x3ffff000;
+	}
 
 	per_cpu_trap_init();
 
@@ -1718,11 +1721,11 @@ void __init trap_init(void)
 
 	if (cpu_has_vce)
 		/* Special exception: R4[04]00 uses also the divec space. */
-		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
+		memcpy((void *)(ebase + 0x180), &except_vec3_r4000, 0x100);
 	else if (cpu_has_4kex)
-		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
+		memcpy((void *)(ebase + 0x180), &except_vec3_generic, 0x80);
 	else
-		memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
+		memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80);
 
 	signal_init();
 #ifdef CONFIG_MIPS32_COMPAT
Signature · 1 line
1.5.6.5
#12 lore raw

PATCH 12/36 Add Cavium OCTEON to arch/mips/Kconfig

---
 arch/mips/Kconfig |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 68 insertions(+), 2 deletions(-)
arch/mips/Kconfig +68 -2
index 7ff95fb..4628398 100644
@@ -597,6 +597,50 @@ config WR_PPMC
 	  This enables support for the Wind River MIPS32 4KC PPMC evaluation
 	  board, which is based on GT64120 bridge chip.
 
+config CAVIUM_OCTEON_SIMULATOR
+	bool "Support for the Cavium Networks Octeon Simulator"
+	select CEVT_R4K
+	select CSRC_R4K
+	select 64BIT_PHYS_ADDR
+	select DMA_COHERENT
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select CPU_CAVIUM_OCTEON
+	help
+	  The Octeon simulator is software performance model of the Cavium
+	  Octeon Processor. It supports simulating Octeon processors on x86
+	  hardware.
+
+config CAVIUM_OCTEON_REFERENCE_BOARD
+	bool "Support for the Cavium Networks Octeon reference board"
+	select CEVT_R4K
+	select CSRC_R4K
+	select 64BIT_PHYS_ADDR
+	select DMA_COHERENT
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_HAS_EARLY_PRINTK
+	select CPU_CAVIUM_OCTEON
+	select SWAP_IO_SPACE
+	select ISA
+	select GENERIC_ISA_DMA
+	select ARCH_MAY_HAVE_PC_FDC
+	help
+	  This option supports all of the Octeon reference boards from Cavium
+	  Networks. It builds a kernel that dynamically determines the Octeon
+	  CPU type and supports all known board reference implementations.
+	  Some of the supported boards are:
+		EBT3000
+		EBH3000
+		EBH3100
+		Asus NA-038
+		Thunder
+		Kodama
+		Hikari
+	  Say Y here for most Octeon reference boards.
+
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
@@ -609,6 +653,7 @@ source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
 source "arch/mips/txx9/Kconfig"
 source "arch/mips/vr41xx/Kconfig"
+source "arch/mips/cavium-octeon/Kconfig"
 
 endmenu
 
@@ -841,6 +886,9 @@ config IRQ_GT641XX
 config IRQ_GIC
 	bool
 
+config IRQ_CPU_OCTEON
+	bool
+
 config MIPS_BOARDS_GEN
 	bool
 
@@ -933,7 +981,7 @@ config BOOT_ELF32
 config MIPS_L1_CACHE_SHIFT
 	int
 	default "4" if MACH_DECSTATION || MIKROTIK_RB532
-	default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM
+	default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
 	default "4" if PMC_MSP4200_EVAL
 	default "5"
 
@@ -1194,6 +1242,24 @@ config CPU_SB1
 	select CPU_SUPPORTS_HIGHMEM
 	select WEAK_ORDERING
 
+config CPU_CAVIUM_OCTEON
+	bool "Cavium Octeon processor"
+	select IRQ_CPU
+	select IRQ_CPU_OCTEON
+	select CPU_HAS_PREFETCH
+	select CPU_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_SMP
+	select NR_CPUS_DEFAULT_16
+	select WEAK_ORDERING
+	select WEAK_REORDERING_BEYOND_LLSC
+	select CPU_SUPPORTS_HIGHMEM
+	select MIPS_DISABLE_BOOT_CPU_ZERO
+	help
+	  The Cavium Octeon processor is a highly integrated chip containing
+	  many ethernet hardware widgets for networking tasks. The processor
+	  can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets.
+	  Full details can be found at http://www.caviumnetworks.com.
+
 endchoice
 
 config SYS_HAS_CPU_LOONGSON2
@@ -1294,7 +1360,7 @@ config CPU_MIPSR1
 
 config CPU_MIPSR2
 	bool
-	default y if CPU_MIPS32_R2 || CPU_MIPS64_R2
+	default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
 
 config SYS_SUPPORTS_32BIT_KERNEL
 	bool
Signature · 1 line
1.5.6.5
#13 lore raw

PATCH 13/36 Add Cavium OCTEON processor constants.

---
 arch/mips/include/asm/cpu.h    |   14 ++++++++++++++
 arch/mips/include/asm/module.h |    2 ++
 2 files changed, 16 insertions(+), 0 deletions(-)
arch/mips/include/asm/cpu.h +14 -0
index 229a786..c018727 100644
@@ -33,6 +33,7 @@
 #define PRID_COMP_TOSHIBA	0x070000
 #define PRID_COMP_LSI		0x080000
 #define PRID_COMP_LEXRA		0x0b0000
+#define PRID_COMP_CAVIUM	0x0d0000
 
 
 /*
@@ -114,6 +115,18 @@
 #define PRID_IMP_BCM3302	0x9000
 
 /*
+ * These are the PRID's for when 23:16 == PRID_COMP_CAVIUM
+ */
+
+#define PRID_IMP_CAVIUM_CN38XX 0x0000
+#define PRID_IMP_CAVIUM_CN31XX 0x0100
+#define PRID_IMP_CAVIUM_CN30XX 0x0200
+#define PRID_IMP_CAVIUM_CN58XX 0x0300
+#define PRID_IMP_CAVIUM_CN56XX 0x0400
+#define PRID_IMP_CAVIUM_CN50XX 0x0600
+#define PRID_IMP_CAVIUM_CN52XX 0x0700
+
+/*
  * Definitions for 7:0 on legacy processors
  */
 
@@ -203,6 +216,7 @@ enum cpu_type_enum {
 	 * MIPS64 class processors
 	 */
 	CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
+	CPU_CAVIUM_OCTEON,
 
 	CPU_LAST
 };
arch/mips/include/asm/module.h +2 -0
index e2e09b2..d94085a 100644
@@ -116,6 +116,8 @@ search_module_dbetables(unsigned long addr)
 #define MODULE_PROC_FAMILY "SB1 "
 #elif defined CONFIG_CPU_LOONGSON2
 #define MODULE_PROC_FAMILY "LOONGSON2 "
+#elif defined CONFIG_CPU_CAVIUM_OCTEON
+#define MODULE_PROC_FAMILY "OCTEON "
 #else
 #error MODULE_PROC_FAMILY undefined for your processor configuration
 #endif
Signature · 1 line
1.5.6.5
#14 lore raw

PATCH 14/36 Rewrite cpu_to_name so it has one statement per line.

Future changes can now pass checkpatch.pl

---
 arch/mips/kernel/cpu-probe.c |  156 +++++++++++++++++++++--------------------
 1 files changed, 80 insertions(+), 76 deletions(-)
arch/mips/kernel/cpu-probe.c +80 -76
index 0cf1545..30f7e8c 100644
@@ -820,86 +820,90 @@ const char *__cpu_name[NR_CPUS];
 /*
  * Name a CPU
  */
+static const char *mips_cpu_names[] = {
+	[CPU_UNKNOWN]		= "unknown",
+	[CPU_R2000]		= "R2000",
+	[CPU_R3000]		= "R3000",
+	[CPU_R3000A]		= "R3000A",
+	[CPU_R3041]		= "R3041",
+	[CPU_R3051]		= "R3051",
+	[CPU_R3052]		= "R3052",
+	[CPU_R3081]		= "R3081",
+	[CPU_R3081E]		= "R3081E",
+	[CPU_R4000PC]		= "R4000PC",
+	[CPU_R4000SC]		= "R4000SC",
+	[CPU_R4000MC]		= "R4000MC",
+	[CPU_R4200]		= "R4200",
+	[CPU_R4400PC]		= "R4400PC",
+	[CPU_R4400SC]		= "R4400SC",
+	[CPU_R4400MC]		= "R4400MC",
+	[CPU_R4600]		= "R4600",
+	[CPU_R6000]		= "R6000",
+	[CPU_R6000A]		= "R6000A",
+	[CPU_R8000]		= "R8000",
+	[CPU_R10000]		= "R10000",
+	[CPU_R12000]		= "R12000",
+	[CPU_R14000]		= "R14000",
+	[CPU_R4300]		= "R4300",
+	[CPU_R4650]		= "R4650",
+	[CPU_R4700]		= "R4700",
+	[CPU_R5000]		= "R5000",
+	[CPU_R5000A]		= "R5000A",
+	[CPU_R4640]		= "R4640",
+	[CPU_NEVADA]		= "Nevada",
+	[CPU_RM7000]		= "RM7000",
+	[CPU_RM9000]		= "RM9000",
+	[CPU_R5432]		= "R5432",
+	[CPU_4KC]		= "MIPS 4Kc",
+	[CPU_5KC]		= "MIPS 5Kc",
+	[CPU_R4310]		= "R4310",
+	[CPU_SB1]		= "SiByte SB1",
+	[CPU_SB1A]		= "SiByte SB1A",
+	[CPU_TX3912]		= "TX3912",
+	[CPU_TX3922]		= "TX3922",
+	[CPU_TX3927]		= "TX3927",
+	[CPU_AU1000]		= "Au1000",
+	[CPU_AU1500]		= "Au1500",
+	[CPU_AU1100]		= "Au1100",
+	[CPU_AU1550]		= "Au1550",
+	[CPU_AU1200]		= "Au1200",
+	[CPU_AU1210]		= "Au1210",
+	[CPU_AU1250]		= "Au1250",
+	[CPU_4KEC]		= "MIPS 4KEc",
+	[CPU_4KSC]		= "MIPS 4KSc",
+	[CPU_VR41XX]		= "NEC Vr41xx",
+	[CPU_R5500]		= "R5500",
+	[CPU_TX49XX]		= "TX49xx",
+	[CPU_20KC]		= "MIPS 20Kc",
+	[CPU_24K]		= "MIPS 24K",
+	[CPU_25KF]		= "MIPS 25Kf",
+	[CPU_34K]		= "MIPS 34K",
+	[CPU_1004K]		= "MIPS 1004K",
+	[CPU_74K]		= "MIPS 74K",
+	[CPU_VR4111]		= "NEC VR4111",
+	[CPU_VR4121]		= "NEC VR4121",
+	[CPU_VR4122]		= "NEC VR4122",
+	[CPU_VR4131]		= "NEC VR4131",
+	[CPU_VR4133]		= "NEC VR4133",
+	[CPU_VR4181]		= "NEC VR4181",
+	[CPU_VR4181A]		= "NEC VR4181A",
+	[CPU_SR71000]		= "Sandcraft SR71000",
+	[CPU_BCM3302]		= "Broadcom BCM3302",
+	[CPU_BCM4710]		= "Broadcom BCM4710",
+	[CPU_PR4450]		= "Philips PR4450",
+	[CPU_LOONGSON2]		= "ICT Loongson-2",
+	[CPU_LAST]		= NULL
+};
+
 static __cpuinit const char *cpu_to_name(struct cpuinfo_mips *c)
 {
-	const char *name = NULL;
+	const char *name;
 
-	switch (c->cputype) {
-	case CPU_UNKNOWN:	name = "unknown"; break;
-	case CPU_R2000:		name = "R2000"; break;
-	case CPU_R3000:		name = "R3000"; break;
-	case CPU_R3000A:	name = "R3000A"; break;
-	case CPU_R3041:		name = "R3041"; break;
-	case CPU_R3051:		name = "R3051"; break;
-	case CPU_R3052:		name = "R3052"; break;
-	case CPU_R3081:		name = "R3081"; break;
-	case CPU_R3081E:	name = "R3081E"; break;
-	case CPU_R4000PC:	name = "R4000PC"; break;
-	case CPU_R4000SC:	name = "R4000SC"; break;
-	case CPU_R4000MC:	name = "R4000MC"; break;
-	case CPU_R4200:		name = "R4200"; break;
-	case CPU_R4400PC:	name = "R4400PC"; break;
-	case CPU_R4400SC:	name = "R4400SC"; break;
-	case CPU_R4400MC:	name = "R4400MC"; break;
-	case CPU_R4600:		name = "R4600"; break;
-	case CPU_R6000:		name = "R6000"; break;
-	case CPU_R6000A:	name = "R6000A"; break;
-	case CPU_R8000:		name = "R8000"; break;
-	case CPU_R10000:	name = "R10000"; break;
-	case CPU_R12000:	name = "R12000"; break;
-	case CPU_R14000:	name = "R14000"; break;
-	case CPU_R4300:		name = "R4300"; break;
-	case CPU_R4650:		name = "R4650"; break;
-	case CPU_R4700:		name = "R4700"; break;
-	case CPU_R5000:		name = "R5000"; break;
-	case CPU_R5000A:	name = "R5000A"; break;
-	case CPU_R4640:		name = "R4640"; break;
-	case CPU_NEVADA:	name = "Nevada"; break;
-	case CPU_RM7000:	name = "RM7000"; break;
-	case CPU_RM9000:	name = "RM9000"; break;
-	case CPU_R5432:		name = "R5432"; break;
-	case CPU_4KC:		name = "MIPS 4Kc"; break;
-	case CPU_5KC:		name = "MIPS 5Kc"; break;
-	case CPU_R4310:		name = "R4310"; break;
-	case CPU_SB1:		name = "SiByte SB1"; break;
-	case CPU_SB1A:		name = "SiByte SB1A"; break;
-	case CPU_TX3912:	name = "TX3912"; break;
-	case CPU_TX3922:	name = "TX3922"; break;
-	case CPU_TX3927:	name = "TX3927"; break;
-	case CPU_AU1000:	name = "Au1000"; break;
-	case CPU_AU1500:	name = "Au1500"; break;
-	case CPU_AU1100:	name = "Au1100"; break;
-	case CPU_AU1550:	name = "Au1550"; break;
-	case CPU_AU1200:	name = "Au1200"; break;
-	case CPU_AU1210:	name = "Au1210"; break;
-	case CPU_AU1250:	name = "Au1250"; break;
-	case CPU_4KEC:		name = "MIPS 4KEc"; break;
-	case CPU_4KSC:		name = "MIPS 4KSc"; break;
-	case CPU_VR41XX:	name = "NEC Vr41xx"; break;
-	case CPU_R5500:		name = "R5500"; break;
-	case CPU_TX49XX:	name = "TX49xx"; break;
-	case CPU_20KC:		name = "MIPS 20Kc"; break;
-	case CPU_24K:		name = "MIPS 24K"; break;
-	case CPU_25KF:		name = "MIPS 25Kf"; break;
-	case CPU_34K:		name = "MIPS 34K"; break;
-	case CPU_1004K:		name = "MIPS 1004K"; break;
-	case CPU_74K:		name = "MIPS 74K"; break;
-	case CPU_VR4111:	name = "NEC VR4111"; break;
-	case CPU_VR4121:	name = "NEC VR4121"; break;
-	case CPU_VR4122:	name = "NEC VR4122"; break;
-	case CPU_VR4131:	name = "NEC VR4131"; break;
-	case CPU_VR4133:	name = "NEC VR4133"; break;
-	case CPU_VR4181:	name = "NEC VR4181"; break;
-	case CPU_VR4181A:	name = "NEC VR4181A"; break;
-	case CPU_SR71000:	name = "Sandcraft SR71000"; break;
-	case CPU_BCM3302:	name = "Broadcom BCM3302"; break;
-	case CPU_BCM4710:	name = "Broadcom BCM4710"; break;
-	case CPU_PR4450:	name = "Philips PR4450"; break;
-	case CPU_LOONGSON2:	name = "ICT Loongson-2"; break;
-	default:
+	if (c->cputype > CPU_LAST)
+		BUG();
+	name = mips_cpu_names[c->cputype];
+	if (!name)
 		BUG();
-	}
-
 	return name;
 }
 
Signature · 1 line
1.5.6.5
#15 lore raw

PATCH 15/36 Probe for Cavium OCTEON CPUs.

Add probe function for Cavium OCTEON CPUs and hook it up.

---
 arch/mips/kernel/cpu-probe.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
arch/mips/kernel/cpu-probe.c +26 -0
index 30f7e8c..fc2403c 100644
@@ -154,6 +154,7 @@ void __init check_wait(void)
 	case CPU_25KF:
 	case CPU_PR4450:
 	case CPU_BCM3302:
+	case CPU_CAVIUM_OCTEON:
 		cpu_wait = r4k_wait;
 		break;
 
@@ -815,6 +816,27 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c)
 	}
 }
 
+static inline void cpu_probe_cavium(struct cpuinfo_mips *c)
+{
+	decode_configs(c);
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_CAVIUM_CN38XX:
+	case PRID_IMP_CAVIUM_CN31XX:
+	case PRID_IMP_CAVIUM_CN30XX:
+	case PRID_IMP_CAVIUM_CN58XX:
+	case PRID_IMP_CAVIUM_CN56XX:
+	case PRID_IMP_CAVIUM_CN50XX:
+	case PRID_IMP_CAVIUM_CN52XX:
+		c->cputype = CPU_CAVIUM_OCTEON;
+		break;
+	default:
+		printk(KERN_INFO "Unknown Octeon chip!\n");
+		c->cputype = CPU_UNKNOWN;
+		break;
+	}
+	mips_probe_watch_registers(c);
+}
+
 const char *__cpu_name[NR_CPUS];
 
 /*
@@ -892,6 +914,7 @@ static const char *mips_cpu_names[] = {
 	[CPU_BCM4710]		= "Broadcom BCM4710",
 	[CPU_PR4450]		= "Philips PR4450",
 	[CPU_LOONGSON2]		= "ICT Loongson-2",
+	[CPU_CAVIUM_OCTEON]	= "Cavium Octeon",
 	[CPU_LAST]		= NULL
 };
 
@@ -939,6 +962,9 @@ __cpuinit void cpu_probe(void)
 	case PRID_COMP_NXP:
 		cpu_probe_nxp(c);
 		break;
+	case PRID_COMP_CAVIUM:
+		cpu_probe_cavium(c);
+		break;
 	default:
 		c->cputype = CPU_UNKNOWN;
 	}
Signature · 1 line
1.5.6.5
#16 lore raw

PATCH 16/36 MIPS: Hook Cavium OCTEON cache init into cache.c

Follow precedent of other boards, and hook-up the CPU specific cache init.

---
 arch/mips/include/asm/cpu-features.h |    3 +++
 arch/mips/mm/cache.c                 |    6 ++++++
 2 files changed, 9 insertions(+), 0 deletions(-)
arch/mips/include/asm/cpu-features.h +3 -0
index 1d0cf0a..331c81e 100644
@@ -38,6 +38,9 @@
 #ifndef cpu_has_tx39_cache
 #define cpu_has_tx39_cache	(cpu_data[0].options & MIPS_CPU_TX39_CACHE)
 #endif
+#ifndef cpu_has_octeon_cache
+#define cpu_has_octeon_cache	0
+#endif
 #ifndef cpu_has_fpu
 #define cpu_has_fpu		(current_cpu_data.options & MIPS_CPU_FPU)
 #define raw_cpu_has_fpu		(raw_current_cpu_data.options & MIPS_CPU_FPU)
arch/mips/mm/cache.c +6 -0
index 1eb7c71..98ad0a8 100644
@@ -182,6 +182,12 @@ void __devinit cpu_cache_init(void)
 		tx39_cache_init();
 	}
 
+	if (cpu_has_octeon_cache) {
+		extern void __weak octeon_cache_init(void);
+
+		octeon_cache_init();
+	}
+
 	setup_protection_map();
 }
 
Signature · 1 line
1.5.6.5
#17 lore raw

PATCH 17/36 cavium: Hook Cavium specifics into main arch/mips dir

Take all the cavium specific files that were added and hook them into the build system for the arch/mips.

---
 arch/mips/Makefile        |   13 +++++++++++++
 arch/mips/kernel/Makefile |    9 +++++++++
 arch/mips/lib/Makefile    |    1 +
 arch/mips/mm/Makefile     |    5 +++++
 4 files changed, 28 insertions(+), 0 deletions(-)
arch/mips/Makefile +13 -0
index 28c55f6..0addc84 100644
@@ -144,6 +144,7 @@ cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-march=sb1,-march=r5000) \
 cflags-$(CONFIG_CPU_R8000)	+= -march=r8000 -Wa,--trap
 cflags-$(CONFIG_CPU_R10000)	+= $(call cc-option,-march=r10000,-march=r8000) \
 			-Wa,--trap
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -march=octeon -Wa,--trap
 
 cflags-$(CONFIG_CPU_R4000_WORKAROUNDS)	+= $(call cc-option,-mfix-r4000,)
 cflags-$(CONFIG_CPU_R4400_WORKAROUNDS)	+= $(call cc-option,-mfix-r4400,)
@@ -586,6 +587,18 @@ core-$(CONFIG_TOSHIBA_RBTX4927)	+= arch/mips/txx9/rbtx4927/
 core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/
 core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/
 
+#
+# Cavium Octeon
+#
+core-$(CONFIG_CPU_CAVIUM_OCTEON)	+= arch/mips/cavium-octeon/
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON)	+= -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon
+core-$(CONFIG_CPU_CAVIUM_OCTEON)	+= arch/mips/cavium-octeon/executive/
+ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+load-$(CONFIG_CPU_CAVIUM_OCTEON)	+= 0xffffffff84100000
+else
+load-$(CONFIG_CPU_CAVIUM_OCTEON) 	+= 0xffffffff81100000
+endif
+
 cflags-y			+= -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)		+= arch/mips/pci/
 
arch/mips/kernel/Makefile +9 -0
index b1372c2..93ff9c4 100644
@@ -43,6 +43,7 @@ obj-$(CONFIG_CPU_SB1)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_VR41XX)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= octeon_switch.o
 
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_SMP_UP)		+= smp-up.o
@@ -66,6 +67,7 @@ obj-$(CONFIG_MIPS_MSC)		+= irq-msc01.o
 obj-$(CONFIG_IRQ_TXX9)		+= irq_txx9.o
 obj-$(CONFIG_IRQ_GT641XX)	+= irq-gt641xx.o
 obj-$(CONFIG_IRQ_GIC)		+= irq-gic.o
+obj-$(CONFIG_IRQ_CPU_OCTEON)	+= irq-octeon.o
 
 obj-$(CONFIG_32BIT)		+= scall32-o32.o
 obj-$(CONFIG_64BIT)		+= scall64-64.o
@@ -90,3 +92,10 @@ CFLAGS_cpu-bugs64.o	= $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/n
 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)	+= 8250-platform.o
 
 EXTRA_CFLAGS += -Werror
+
+ifdef CONFIG_CPU_CAVIUM_OCTEON
+OCTEON_ROOT = $(srctree)/arch/mips/cavium-octeon
+
+CFLAGS_irq-octeon.o	= -I$(OCTEON_ROOT)/executive
+CFLAGS_ptrace.o	= -I$(OCTEON_ROOT)/executive
+endif
arch/mips/lib/Makefile +1 -0
index dbcf651..c13c7ad 100644
@@ -27,6 +27,7 @@ obj-$(CONFIG_CPU_SB1)		+= dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)	+= r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX49XX)	+= dump_tlb.o
 obj-$(CONFIG_CPU_VR41XX)	+= dump_tlb.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
 obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o
arch/mips/mm/Makefile +5 -0
index 95ba32b..3dad926 100644
@@ -27,6 +27,7 @@ obj-$(CONFIG_CPU_SB1)		+= c-r4k.o cerr-sb1.o cex-sb1.o tlb-r4k.o
 obj-$(CONFIG_CPU_TX39XX)	+= c-tx39.o tlb-r3k.o
 obj-$(CONFIG_CPU_TX49XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
 obj-$(CONFIG_CPU_VR41XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= c-octeon.o cex-oct.o tlb-r4k.o
 
 obj-$(CONFIG_IP22_CPU_SCACHE)	+= sc-ip22.o
 obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
@@ -34,3 +35,7 @@ obj-$(CONFIG_RM7000_CPU_SCACHE)	+= sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
 
 EXTRA_CFLAGS += -Werror
+
+OCTEON_ROOT = $(srctree)/arch/mips/cavium-octeon
+CFLAGS_c-octeon.o	= -I$(OCTEON_ROOT)/executive
+
Signature · 1 line
1.5.6.5
#18 lore raw

PATCH 18/36 Cavium OCTEON modify core io.h macros to account for the Octeon Errata Core-301.

---
 arch/mips/include/asm/io.h |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
arch/mips/include/asm/io.h +14 -0
index 501a40b..436878e 100644
@@ -295,6 +295,12 @@ static inline void iounmap(const volatile void __iomem *addr)
 #undef __IS_KSEG1
 }
 
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define war_octeon_io_reorder_wmb()  		wmb()
+#else
+#define war_octeon_io_reorder_wmb()		do { } while (0)
+#endif
+
 #define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq)			\
 									\
 static inline void pfx##write##bwlq(type val,				\
@@ -303,6 +309,8 @@ static inline void pfx##write##bwlq(type val,				\
 	volatile type *__mem;						\
 	type __val;							\
 									\
+	war_octeon_io_reorder_wmb();					\
+									\
 	__mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem));	\
 									\
 	__val = pfx##ioswab##bwlq(__mem, val);				\
@@ -370,6 +378,8 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port)	\
 	volatile type *__addr;						\
 	type __val;							\
 									\
+	war_octeon_io_reorder_wmb();					\
+									\
 	__addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
 									\
 	__val = pfx##ioswab##bwlq(__addr, val);				\
@@ -504,8 +514,12 @@ BUILDSTRING(q, u64)
 #endif
 
 
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define mmiowb() wmb()
+#else
 /* Depends on MIPS II instruction set */
 #define mmiowb() asm volatile ("sync" ::: "memory")
+#endif
 
 static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
 {
Signature · 1 line
1.5.6.5
#19 lore raw

PATCH 19/36 Cavium OCTEON: increase MAX_DMA address.

There is not a fundamental limit like an old ISA board where DMA can be only to an address < 16M, so set the MAX_DMA_ADDRESS accordingly.

---
 arch/mips/include/asm/dma.h |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
arch/mips/include/asm/dma.h +7 -0
index 1353c81..1706089 100644
@@ -87,6 +87,13 @@
 #if defined(CONFIG_SGI_IP22) || defined(CONFIG_SGI_IP28)
 /* don't care; ISA bus master won't work, ISA slave DMA supports 32bit addr */
 #define MAX_DMA_ADDRESS		PAGE_OFFSET
+#elif defined(CONFIG_CPU_CAVIUM_OCTEON)
+/* Octeon can support DMA to any memory installed */
+#ifdef CONFIG_64BIT
+#define MAX_DMA_ADDRESS		(PAGE_OFFSET + (1ull<<32))
+#else
+#define MAX_DMA_ADDRESS		(PAGE_OFFSET + (1ul<<30))
+#endif
 #else
 #define MAX_DMA_ADDRESS		(PAGE_OFFSET + 0x01000000)
 #endif
Signature · 1 line
1.5.6.5
#20 lore raw

PATCH 20/36 Cavium OCTEON: add in icache and dcache error functions.

If there is an icache or dcache error, there is additional data to be had from the 64bit read of c0 @ $27.

---
 arch/mips/include/asm/mipsregs.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
arch/mips/include/asm/mipsregs.h +5 -0
index 9316324..ed266ce 100644
@@ -967,7 +967,12 @@ do {									\
 #define read_c0_derraddr0()	__read_ulong_c0_register($26, 1)
 #define write_c0_derraddr0(val)	__write_ulong_c0_register($26, 1, val)
 
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define read_c0_cacheerr()	__read_64bit_c0_register($27, 0)
+#define write_c0_cacheerr(val)	__write_64bit_c0_register($27, 0, val)
+#else
 #define read_c0_cacheerr()	__read_32bit_c0_register($27, 0)
+#endif
 
 #define read_c0_derraddr1()	__read_ulong_c0_register($27, 1)
 #define write_c0_derraddr1(val)	__write_ulong_c0_register($27, 1, val)
Signature · 1 line
1.5.6.5
#21 lore raw

PATCH 21/36 Cavium OCTEON: Add cop2/cvmseg state entries to processor.h.

Add in the cop2 and cvmseg state info to the known proc reg data for Cavium so that it can be tracked, saved, restored...

---
 arch/mips/include/asm/processor.h |   69 +++++++++++++++++++++++++++++++++++++
 1 files changed, 69 insertions(+), 0 deletions(-)
arch/mips/include/asm/processor.h +69 -0
index 18ee58e..0f926aa 100644
@@ -118,6 +118,60 @@ union mips_watch_reg_state {
 	struct mips3264_watch_reg_state mips3264;
 };
 
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+
+struct octeon_cop2_state {
+	/* DMFC2 rt, 0x0201 */
+	unsigned long   cop2_crc_iv;
+	/* DMFC2 rt, 0x0202 (Set with DMTC2 rt, 0x1202) */
+	unsigned long   cop2_crc_length;
+	/* DMFC2 rt, 0x0200 (set with DMTC2 rt, 0x4200) */
+	unsigned long   cop2_crc_poly;
+	/* DMFC2 rt, 0x0402; DMFC2 rt, 0x040A */
+	unsigned long   cop2_llm_dat[2];
+       /* DMFC2 rt, 0x0084 */
+	unsigned long   cop2_3des_iv;
+	/* DMFC2 rt, 0x0080; DMFC2 rt, 0x0081; DMFC2 rt, 0x0082 */
+	unsigned long   cop2_3des_key[3];
+	/* DMFC2 rt, 0x0088 (Set with DMTC2 rt, 0x0098) */
+	unsigned long   cop2_3des_result;
+	/* DMFC2 rt, 0x0111 (FIXME: Read Pass1 Errata) */
+	unsigned long   cop2_aes_inp0;
+	/* DMFC2 rt, 0x0102; DMFC2 rt, 0x0103 */
+	unsigned long   cop2_aes_iv[2];
+	/* DMFC2 rt, 0x0104; DMFC2 rt, 0x0105; DMFC2 rt, 0x0106; DMFC2
+	 * rt, 0x0107 */
+	unsigned long   cop2_aes_key[4];
+	/* DMFC2 rt, 0x0110 */
+	unsigned long   cop2_aes_keylen;
+	/* DMFC2 rt, 0x0100; DMFC2 rt, 0x0101 */
+	unsigned long   cop2_aes_result[2];
+	/* DMFC2 rt, 0x0240; DMFC2 rt, 0x0241; DMFC2 rt, 0x0242; DMFC2
+	 * rt, 0x0243; DMFC2 rt, 0x0244; DMFC2 rt, 0x0245; DMFC2 rt,
+	 * 0x0246; DMFC2 rt, 0x0247; DMFC2 rt, 0x0248; DMFC2 rt,
+	 * 0x0249; DMFC2 rt, 0x024A; DMFC2 rt, 0x024B; DMFC2 rt,
+	 * 0x024C; DMFC2 rt, 0x024D; DMFC2 rt, 0x024E - Pass2 */
+	unsigned long   cop2_hsh_datw[15];
+	/* DMFC2 rt, 0x0250; DMFC2 rt, 0x0251; DMFC2 rt, 0x0252; DMFC2
+	 * rt, 0x0253; DMFC2 rt, 0x0254; DMFC2 rt, 0x0255; DMFC2 rt,
+	 * 0x0256; DMFC2 rt, 0x0257 - Pass2 */
+	unsigned long   cop2_hsh_ivw[8];
+	/* DMFC2 rt, 0x0258; DMFC2 rt, 0x0259 - Pass2 */
+	unsigned long   cop2_gfm_mult[2];
+	/* DMFC2 rt, 0x025E - Pass2 */
+	unsigned long   cop2_gfm_poly;
+	/* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */
+	unsigned long   cop2_gfm_result[2];
+};
+#define INIT_OCTEON_COP2 {0,}
+
+struct octeon_cvmseg_state {
+	unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE]
+			    [cpu_dcache_line_size() / sizeof(unsigned long)];
+};
+
+#endif
+
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
@@ -160,6 +214,10 @@ struct thread_struct {
 	unsigned long trap_no;
 	unsigned long irix_trampoline;  /* Wheee... */
 	unsigned long irix_oldctx;
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+    struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
+    struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
+#endif
 	struct mips_abi *abi;
 };
 
@@ -171,6 +229,13 @@ struct thread_struct {
 #define FPAFF_INIT
 #endif /* CONFIG_MIPS_MT_FPAFF */
 
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define OCTEON_INIT						\
+	.cp2			= INIT_OCTEON_COP2,
+#else
+#define OCTEON_INIT
+#endif /* CONFIG_CPU_CAVIUM_OCTEON */
+
 #define INIT_THREAD  {						\
         /*							\
          * Saved main processor registers			\
@@ -221,6 +286,10 @@ struct thread_struct {
 	.trap_no		= 0,				\
 	.irix_trampoline	= 0,				\
 	.irix_oldctx		= 0,				\
+	/*							\
+	 * Cavium Octeon specifics (null if not Octeon)		\
+	 */							\
+	OCTEON_INIT						\
 }
 
 struct task_struct;
Signature · 1 line
1.5.6.5
#22 lore raw

PATCH 22/36 Add Cavium OCTEON specific registers to ptrace.h and asm-offsets.c

---
 arch/mips/include/asm/ptrace.h |    4 ++++
 arch/mips/kernel/asm-offsets.c |   31 +++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 0 deletions(-)
arch/mips/include/asm/ptrace.h +4 -0
index 813abd1..db01535 100644
@@ -52,6 +52,10 @@ struct pt_regs {
 #ifdef CONFIG_MIPS_MT_SMTC
 	unsigned long cp0_tcstatus;
 #endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+	unsigned long long mpl[3];        /* MTM{0,1,2} */
+	unsigned long long mtp[3];        /* MTP{0,1,2} */
+#endif
 } __attribute__ ((aligned (8)));
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
arch/mips/kernel/asm-offsets.c +31 -0
index 7294222..c901c22 100644
@@ -64,6 +64,10 @@ void output_ptreg_defines(void)
 #ifdef CONFIG_MIPS_MT_SMTC
 	OFFSET(PT_TCSTATUS, pt_regs, cp0_tcstatus);
 #endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+	OFFSET(PT_MPL, pt_regs, mpl);
+	OFFSET(PT_MTP, pt_regs, mtp);
+#endif /* CONFIG_CPU_CAVIUM_OCTEON */
 	DEFINE(PT_SIZE, sizeof(struct pt_regs));
 	BLANK();
 }
@@ -295,3 +299,30 @@ void output_irq_cpustat_t_defines(void)
 	DEFINE(IC_IRQ_CPUSTAT_T, sizeof(irq_cpustat_t));
 	BLANK();
 }
+
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+void output_octeon_cop2_state_defines(void)
+{
+	COMMENT("Octeon specific octeon_cop2_state offsets.");
+	OFFSET(OCTEON_CP2_CRC_IV,	octeon_cop2_state, cop2_crc_iv);
+	OFFSET(OCTEON_CP2_CRC_LENGTH,	octeon_cop2_state, cop2_crc_length);
+	OFFSET(OCTEON_CP2_CRC_POLY,	octeon_cop2_state, cop2_crc_poly);
+	OFFSET(OCTEON_CP2_LLM_DAT,	octeon_cop2_state, cop2_llm_dat);
+	OFFSET(OCTEON_CP2_3DES_IV,	octeon_cop2_state, cop2_3des_iv);
+	OFFSET(OCTEON_CP2_3DES_KEY,	octeon_cop2_state, cop2_3des_key);
+	OFFSET(OCTEON_CP2_3DES_RESULT,	octeon_cop2_state, cop2_3des_result);
+	OFFSET(OCTEON_CP2_AES_INP0,	octeon_cop2_state, cop2_aes_inp0);
+	OFFSET(OCTEON_CP2_AES_IV,	octeon_cop2_state, cop2_aes_iv);
+	OFFSET(OCTEON_CP2_AES_KEY,	octeon_cop2_state, cop2_aes_key);
+	OFFSET(OCTEON_CP2_AES_KEYLEN,	octeon_cop2_state, cop2_aes_keylen);
+	OFFSET(OCTEON_CP2_AES_RESULT,	octeon_cop2_state, cop2_aes_result);
+	OFFSET(OCTEON_CP2_GFM_MULT,	octeon_cop2_state, cop2_gfm_mult);
+	OFFSET(OCTEON_CP2_GFM_POLY,	octeon_cop2_state, cop2_gfm_poly);
+	OFFSET(OCTEON_CP2_GFM_RESULT,	octeon_cop2_state, cop2_gfm_result);
+	OFFSET(OCTEON_CP2_HSH_DATW,	octeon_cop2_state, cop2_hsh_datw);
+	OFFSET(OCTEON_CP2_HSH_IVW,	octeon_cop2_state, cop2_hsh_ivw);
+	OFFSET(THREAD_CP2,	task_struct, thread.cp2);
+	OFFSET(THREAD_CVMSEG,	task_struct, thread.cvmseg.cvmseg);
+	BLANK();
+}
+#endif
Signature · 1 line
1.5.6.5
#23 lore raw

PATCH 23/36 Add SMP_ICACHE_FLUSH for the Cavium CPU family.

---
 arch/mips/include/asm/smp.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
arch/mips/include/asm/smp.h +3 -0
index 0ff5b52..e6f419f 100644
@@ -37,6 +37,9 @@ extern int __cpu_logical_map[NR_CPUS];
 
 #define SMP_RESCHEDULE_YOURSELF	0x1	/* XXX braindead */
 #define SMP_CALL_FUNCTION	0x2
+/* Octeon - Tell another core to flush its icache */
+#define SMP_ICACHE_FLUSH	0x4
+
 
 extern cpumask_t phys_cpu_present_map;
 #define cpu_possible_map	phys_cpu_present_map
Signature · 1 line
1.5.6.5
#24 lore raw

PATCH 24/36 Cavium OCTEON: PT vs MFC0 reorder, multiplier state preservation.

For cavium, reorder PT ops to be after mfc0 and not before. Also implement a save and restore of the multiplier state so that if it gets corrupted, it will not impact things.

---
 arch/mips/include/asm/stackframe.h |   46 ++++++++++++++++++++++++++++++++++++
 1 files changed, 46 insertions(+), 0 deletions(-)
arch/mips/include/asm/stackframe.h +46 -0
index 4c37c4e..bcaac81 100644
@@ -51,10 +51,12 @@
 		LONG_S	v1, PT_ACX(sp)
 #else
 		mfhi	v1
+#ifndef CONFIG_CPU_CAVIUM_OCTEON
 		LONG_S	v1, PT_HI(sp)
 		mflo	v1
 		LONG_S	v1, PT_LO(sp)
 #endif
+#endif
 #ifdef CONFIG_32BIT
 		LONG_S	$8, PT_R8(sp)
 		LONG_S	$9, PT_R9(sp)
@@ -62,10 +64,17 @@
 		LONG_S	$10, PT_R10(sp)
 		LONG_S	$11, PT_R11(sp)
 		LONG_S	$12, PT_R12(sp)
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		LONG_S	v1, PT_HI(sp)
+		mflo	v1
+#endif
 		LONG_S	$13, PT_R13(sp)
 		LONG_S	$14, PT_R14(sp)
 		LONG_S	$15, PT_R15(sp)
 		LONG_S	$24, PT_R24(sp)
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		LONG_S	v1, PT_LO(sp)
+#endif
 		.endm
 
 		.macro	SAVE_STATIC
@@ -166,7 +175,9 @@
 		LONG_S	$0, PT_R0(sp)
 		mfc0	v1, CP0_STATUS
 		LONG_S	$2, PT_R2(sp)
+#ifndef CONFIG_CPU_CAVIUM_OCTEON
 		LONG_S	v1, PT_STATUS(sp)
+#endif
 #ifdef CONFIG_MIPS_MT_SMTC
 		/*
 		 * Ideally, these instructions would be shuffled in
@@ -178,22 +189,53 @@
 		LONG_S	v1, PT_TCSTATUS(sp)
 #endif /* CONFIG_MIPS_MT_SMTC */
 		LONG_S	$4, PT_R4(sp)
+#ifndef CONFIG_CPU_CAVIUM_OCTEON
 		mfc0	v1, CP0_CAUSE
+#endif
 		LONG_S	$5, PT_R5(sp)
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		LONG_S	v1, PT_STATUS(sp)
+		mfc0	v1, CP0_CAUSE
+#else
 		LONG_S	v1, PT_CAUSE(sp)
+#endif
 		LONG_S	$6, PT_R6(sp)
+#ifndef CONFIG_CPU_CAVIUM_OCTEON
 		MFC0	v1, CP0_EPC
+#endif
 		LONG_S	$7, PT_R7(sp)
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		LONG_S	v1, PT_CAUSE(sp)
+		MFC0	v1, CP0_EPC
+#endif
 #ifdef CONFIG_64BIT
 		LONG_S	$8, PT_R8(sp)
 		LONG_S	$9, PT_R9(sp)
 #endif
+#ifndef CONFIG_CPU_CAVIUM_OCTEON
 		LONG_S	v1, PT_EPC(sp)
+#endif
 		LONG_S	$25, PT_R25(sp)
 		LONG_S	$28, PT_R28(sp)
 		LONG_S	$31, PT_R31(sp)
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		LONG_S	v1, PT_EPC(sp)
+#endif
 		ori	$28, sp, _THREAD_MASK
 		xori	$28, _THREAD_MASK
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		.set    mips64
+		pref    0, 0($28)       /* Prefetch the current pointer */
+		pref    0, PT_R31(sp)   /* Prefetch the $31(ra) */
+		/* The Octeon multiplier state is affected by general multiply
+		    instructions. It must be saved before and kernel code might
+		    corrupt it */
+		jal     octeon_mult_save
+		LONG_L  v1, 0($28)  /* Load the current pointer */
+			 /* Restore $31(ra) that was changed by the jal */
+		LONG_L  ra, PT_R31(sp)
+		pref    0, 0(v1)    /* Prefetch the current thread */
+#endif
 		.set	pop
 		.endm
 
@@ -324,6 +366,10 @@
 		DVPE	5				# dvpe a1
 		jal	mips_ihb
 #endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+		/* Restore the Octeon multiplier state */
+		jal	octeon_mult_restore
+#endif
 		mfc0	a0, CP0_STATUS
 		ori	a0, STATMASK
 		xori	a0, STATMASK
Signature · 1 line
1.5.6.5
#25 lore raw

PATCH 25/36 Add Cavium OCTEON irq hazard in asmmacro.h.

Place irq_enable_hazard and irq_disable_hazard into asmmacro.h

---
 arch/mips/include/asm/asmmacro.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)
arch/mips/include/asm/asmmacro.h +10 -0
index 7a88175..5408149 100644
@@ -35,6 +35,16 @@
 	mtc0	\reg, CP0_TCSTATUS
 	_ehb
 	.endm
+#elif defined(CONFIG_CPU_CAVIUM_OCTEON)
+	.macro	local_irq_enable reg=t0
+	ei
+	irq_enable_hazard
+	.endm
+
+	.macro	local_irq_disable reg=t0
+	di
+	irq_disable_hazard
+	.endm
 #else
 	.macro	local_irq_enable reg=t0
 	mfc0	\reg, CP0_STATUS
Signature · 1 line
1.5.6.5
#26 lore raw

PATCH 26/36 Compute branch returns for Cavium OCTEON specific branch instructions.

For cavium, compute the return epc value in the fashion specific to the OCTEON.

---
 arch/mips/kernel/branch.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)
arch/mips/kernel/branch.c +33 -0
index 6b5df8b..0176ed0 100644
@@ -205,6 +205,39 @@ int __compute_return_epc(struct pt_regs *regs)
 			break;
 		}
 		break;
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+	case lwc2_op: /* This is bbit0 on Octeon */
+		if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
+		     == 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+	case ldc2_op: /* This is bbit032 on Octeon */
+		if ((regs->regs[insn.i_format.rs] &
+		    (1ull<<(insn.i_format.rt+32))) == 0)
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+	case swc2_op: /* This is bbit1 on Octeon */
+		if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+	case sdc2_op: /* This is bbit132 on Octeon */
+		if (regs->regs[insn.i_format.rs] &
+		    (1ull<<(insn.i_format.rt+32)))
+			epc = epc + 4 + (insn.i_format.simmediate << 2);
+		else
+			epc += 8;
+		regs->cp0_epc = epc;
+		break;
+#endif
 	}
 
 	return 0;
Signature · 1 line
1.5.6.5
#27 lore raw

PATCH 27/36 Add Cavium OCTEON slot into proper tlb category.

Expand the case statement for build_tlb_write_entry so that it does the right thing on Cavium CPU variants.

---
 arch/mips/mm/tlbex.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/mips/mm/tlbex.c +1 -0
index 979cf91..4294203 100644
@@ -317,6 +317,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
 	case CPU_BCM3302:
 	case CPU_BCM4710:
 	case CPU_LOONGSON2:
+	case CPU_CAVIUM_OCTEON:
 		if (m4kc_tlbp_war())
 			uasm_i_nop(p);
 		tlbw(p);
Signature · 1 line
1.5.6.5
#28 lore raw

PATCH 28/36 MIPS: move FPU emulator externs to fpu_emulator.h

---
 arch/mips/include/asm/fpu_emulator.h |    5 +++++
 arch/mips/kernel/traps.c             |    4 +---
 arch/mips/kernel/unaligned.c         |    2 +-
 arch/mips/math-emu/dsemul.h          |    1 -
 4 files changed, 7 insertions(+), 5 deletions(-)
arch/mips/include/asm/fpu_emulator.h +5 -0
index 2731c38..c8e1bb2 100644
@@ -34,4 +34,9 @@ struct mips_fpu_emulator_stats {
 
 extern struct mips_fpu_emulator_stats fpuemustats;
 
+extern int do_dsemulret(struct pt_regs *);
+
+extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
+	struct mips_fpu_struct *ctx, int has_fpu);
+
 #endif /* _ASM_FPU_EMULATOR_H */
arch/mips/kernel/traps.c +1 -3
index cfec89c..bf4b847 100644
@@ -47,6 +47,7 @@
 #include <asm/types.h>
 #include <asm/stacktrace.h>
 #include <asm/irq.h>
+#include <asm/fpu_emulator.h>
 
 extern void check_wait(void);
 extern asmlinkage void r4k_wait(void);
@@ -75,9 +76,6 @@ extern asmlinkage void handle_dsp(void);
 extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
-extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-	struct mips_fpu_struct *ctx, int has_fpu);
-
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
 #endif
arch/mips/kernel/unaligned.c +1 -1
index 2070966..e4b0e39 100644
@@ -84,6 +84,7 @@
 #include <asm/inst.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/fpu_emulator.h>
 
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
@@ -499,7 +500,6 @@ sigill:
 
 asmlinkage void do_ade(struct pt_regs *regs)
 {
-	extern int do_dsemulret(struct pt_regs *);
 	unsigned int __user *pc;
 	mm_segment_t seg;
 
arch/mips/math-emu/dsemul.h +0 -1
index 091f0e7..12e2ef1 100644
@@ -1,5 +1,4 @@
 extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc);
-extern int do_dsemulret(struct pt_regs *xcp);
 
 /* Instruction which will always cause an address error */
 #define AdELOAD 0x8c000001	/* lw $0,1($0) */
Signature · 1 line
1.5.6.5
#29 lore raw

PATCH 29/36 Cavium OCTEON FPU EMU exception as TLB exception

The FPU exceptions come in as TLB exceptions -- see if this is one of them, and act accordingly.

---
 arch/mips/mm/fault.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
arch/mips/mm/fault.c +16 -0
index fa636fc..c8a3fb5 100644
@@ -25,6 +25,7 @@
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/highmem.h>		/* For VMALLOC_END */
+#include <asm/fpu_emulator.h>
 
 /*
  * This routine handles page faults.  It determines the address,
@@ -47,6 +48,21 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
 	       field, regs->cp0_epc);
 #endif
 
+#ifdef CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED
+	/*
+	 * Normally the FPU emulator uses a load word from address one
+	 * to retake control of the CPU after executing the
+	 * instruction in the delay slot of an emulated branch. The
+	 * Octeon hardware unaligned access fix changes this from an
+	 * address exception into a TLB exception. This code checks to
+	 * see if this page fault was caused by an FPU emulation.
+	 *
+	 * Terminate if exception was recognized as a delay slot return.
+	 */
+	if (do_dsemulret(regs))
+		return;
+#endif
+
 	info.si_code = SEGV_MAPERR;
 
 	/*
Signature · 1 line
1.5.6.5
#30 lore raw

Re: [PATCH 29/36] Cavium OCTEON FPU EMU exception as TLB exception

Quoted 7 lines · David Daney

The FPU exceptions come in as TLB exceptions -- see if this is one of them, and act accordingly.

(quoted diff) +4 -0
+#ifdef CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED
+	/*
+	 * Normally the FPU emulator uses a load word from address one
+	 * to retake control of the CPU after executing the

Review

Quoted 10 lines
(quoted diff) +10 -0
+	 * instruction in the delay slot of an emulated branch. The
+	 * Octeon hardware unaligned access fix changes this from an
+	 * address exception into a TLB exception. This code checks to
+	 * see if this page fault was caused by an FPU emulation.
+	 *
+	 * Terminate if exception was recognized as a delay slot return.
+	 */
+	if (do_dsemulret(regs))
+		return;
+#endif

There is absolutely no need to use any particular type of exception for this; the choice of the address error exception back in history was totally arbitrary - and arguably ugly. There was even the hook to use the CU exception instead but I think this is more what the break instruction was intended for, so I propose to use a break instruction and allocate a new break code for this. See below patch. Untested. It may compile. It may even work ;-)

Ralf

PS: You may have noticed a pattern - I hunt down most #ifdefs to generic code you submit. Evil stuff :-)

 arch/mips/include/asm/break.h        |    1 +
 arch/mips/include/asm/fpu_emulator.h |   16 ++++++++++++++++
 arch/mips/kernel/traps.c             |   16 ++++++++++++++++
 arch/mips/kernel/unaligned.c         |   12 ------------
 arch/mips/math-emu/cp1emu.c          |    4 ----
 arch/mips/math-emu/dsemul.c          |    7 +++----
 arch/mips/math-emu/dsemul.h          |   17 -----------------
 7 files changed, 36 insertions(+), 37 deletions(-)
arch/mips/include/asm/break.h +1 -0
index 25b980c..44437ed 100644
@@ -29,6 +29,7 @@
 #define _BRK_THREADBP	11	/* For threads, user bp (used by debuggers) */
 #define BRK_BUG		512	/* Used by BUG() */
 #define BRK_KDB		513	/* Used in KDB_ENTER() */
+#define BRK_MEMU	514	/* Used by FPU emulator */
 #define BRK_MULOVF	1023	/* Multiply overflow */
 
 #endif /* __ASM_BREAK_H */
arch/mips/include/asm/fpu_emulator.h +16 -0
index 2731c38..a66f25e 100644
@@ -23,6 +23,8 @@
 #ifndef _ASM_FPU_EMULATOR_H
 #define _ASM_FPU_EMULATOR_H
 
+#include <asm/inst.h>
+
 struct mips_fpu_emulator_stats {
 	unsigned int emulated;
 	unsigned int loads;
@@ -34,4 +36,18 @@ struct mips_fpu_emulator_stats {
 
 extern struct mips_fpu_emulator_stats fpuemustats;
 
+extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
+	unsigned long cpc);
+extern int do_dsemulret(struct pt_regs *xcp);
+
+/*
+ * Instruction inserted following the badinst to further tag the sequence
+ */
+#define BD_COOKIE 0x0000bd36	/* tne $0, $0 with baggage */
+
+/*
+ * Break instruction with special math emu break code set
+ */
+#define BREAK_MATH (0x0000000d | (BRK_MEMU << 16))
+
 #endif /* _ASM_FPU_EMULATOR_H */
arch/mips/kernel/traps.c +16 -0
index 3f6de76..3530561 100644
@@ -32,6 +32,7 @@
 #include <asm/cpu.h>
 #include <asm/dsp.h>
 #include <asm/fpu.h>
+#include <asm/fpu_emulator.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/module.h>
@@ -722,6 +723,21 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 		die_if_kernel("Kernel bug detected", regs);
 		force_sig(SIGTRAP, current);
 		break;
+	case BRK_MEMU:
+		/*
+		 * Address errors may be deliberately induced by the FPU
+		 * emulator to retake control of the CPU after executing the
+		 * instruction in the delay slot of an emulated branch.
+		 *
+		 * Terminate if exception was recognized as a delay slot return
+		 * otherwise handle as normal.
+		 */
+		if (do_dsemulret(regs))
+			return;
+
+		die_if_kernel("Math emu break/trap", regs);
+		force_sig(SIGTRAP, current);
+		break;
 	default:
 		scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
 		die_if_kernel(b, regs);
arch/mips/kernel/unaligned.c +0 -12
index 2070966..bf4c4a9 100644
@@ -499,22 +499,10 @@ sigill:
 
 asmlinkage void do_ade(struct pt_regs *regs)
 {
-	extern int do_dsemulret(struct pt_regs *);
 	unsigned int __user *pc;
 	mm_segment_t seg;
 
 	/*
-	 * Address errors may be deliberately induced by the FPU emulator to
-	 * retake control of the CPU after executing the instruction in the
-	 * delay slot of an emulated branch.
-	 */
-	/* Terminate if exception was recognized as a delay slot return */
-	if (do_dsemulret(regs))
-		return;
-
-	/* Otherwise handle as normal */
-
-	/*
 	 * Did we catch a fault trying to load an instruction?
 	 * Or are we running in MIPS16 mode?
 	 */
arch/mips/math-emu/cp1emu.c +0 -4
index 7ec0b21..890f779 100644
@@ -48,7 +48,6 @@
 #include <asm/branch.h>
 
 #include "ieee754.h"
-#include "dsemul.h"
 
 /* Strap kernel emulator for full MIPS IV emulation */
 
@@ -346,9 +345,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 			/* cop control register rd -> gpr[rt] */
 			u32 value;
 
-			if (ir == CP1UNDEF) {
-				return do_dsemulret(xcp);
-			}
 			if (MIPSInst_RD(ir) == FPCREG_CSR) {
 				value = ctx->fcr31;
 				value = (value & ~0x3) | mips_rm[value & 0x3];
arch/mips/math-emu/dsemul.c +3 -4
index 653e325..df7b9d9 100644
@@ -18,7 +18,6 @@
 #include <asm/fpu_emulator.h>
 
 #include "ieee754.h"
-#include "dsemul.h"
 
 /* Strap kernel emulator for full MIPS IV emulation */
 
@@ -94,7 +93,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 		return SIGBUS;
 
 	err = __put_user(ir, &fr->emul);
-	err |= __put_user((mips_instruction)BADINST, &fr->badinst);
+	err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst);
 	err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie);
 	err |= __put_user(cpc, &fr->epc);
 
@@ -130,13 +129,13 @@ int do_dsemulret(struct pt_regs *xcp)
 	/*
 	 * Do some sanity checking on the stackframe:
 	 *
-	 *  - Is the instruction pointed to by the EPC an BADINST?
+	 *  - Is the instruction pointed to by the EPC an BREAK_MATH?
 	 *  - Is the following memory word the BD_COOKIE?
 	 */
 	err = __get_user(insn, &fr->badinst);
 	err |= __get_user(cookie, &fr->cookie);
 
-	if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) {
+	if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {
 		fpuemustats.errors++;
 		return 0;
 	}
arch/mips/math-emu/dsemul.h deleted +0 -17
deleted file mode 100644
index 091f0e7..0000000
@@ -1,17 +0,0 @@
-extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc);
-extern int do_dsemulret(struct pt_regs *xcp);
-
-/* Instruction which will always cause an address error */
-#define AdELOAD 0x8c000001	/* lw $0,1($0) */
-/* Instruction which will plainly cause a CP1 exception when FPU is disabled */
-#define CP1UNDEF 0x44400001    /* cfc1 $0,$0 undef  */
-
-/* Instruction inserted following the badinst to further tag the sequence */
-#define BD_COOKIE 0x0000bd36 /* tne $0,$0 with baggage */
-
-/* Setup which instruction to use for trampoline */
-#ifdef STANDALONE_EMULATOR
-#define BADINST CP1UNDEF
-#else
-#define BADINST AdELOAD
-#endif
#31 lore raw

Re: [PATCH 17/36] cavium: Hook Cavium specifics into main arch/mips dir

In reply to David Daney

arch/mips/Makefile cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \ · line 147

Quoted 9 lines · David Daney
arch/mips/Makefile +1 -0
index 28c55f6..0addc84 100644
@@ -144,6 +144,7 @@ cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-march=sb1,-march=r5000) \
 cflags-$(CONFIG_CPU_R8000)	+= -march=r8000 -Wa,--trap
 cflags-$(CONFIG_CPU_R10000)	+= $(call cc-option,-march=r10000,-march=r8000) \
 			-Wa,--trap
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -march=octeon -Wa,--trap

One if my standard requirements is that contributions must build and work with a standard FSF toolchain. Browny points for building with even older tools chains - the oldest supported versions are gcc 3.2 for 32-bit and gcc 3.3 for 64-bit.

Latest binutils 2.19 (releast on 2008-10-27) have added Cavium support but gcc 4.3 doesn't have that yet. So you can try something like:

cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += $(call cc-option,-march=octeon,-march=mips64r2) -Wa,--trap

arch/mips/Makefile core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ · line 595

Quoted 1 line
arch/mips/Makefile +1 -0
+core-$(CONFIG_CPU_CAVIUM_OCTEON)	+= arch/mips/cavium-octeon/executive/

-fkeep-ceo-inline ;-)

arch/mips/Makefile core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/ · line 600

Quoted 5 lines
arch/mips/Makefile +5 -0
+ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+load-$(CONFIG_CPU_CAVIUM_OCTEON)	+= 0xffffffff84100000
+else
+load-$(CONFIG_CPU_CAVIUM_OCTEON) 	+= 0xffffffff81100000
+endif

I'm thinking about a more elegant solution for this. PIC code sucks a blue whale through a dialysis filter so I hope we can find something better. Until then this is certainly acceptable.

arch/mips/kernel/Makefile obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o · line 46

Quoted 9 lines
arch/mips/kernel/Makefile +1 -0
index b1372c2..93ff9c4 100644
@@ -43,6 +43,7 @@ obj-$(CONFIG_CPU_SB1)		+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_VR41XX)	+= r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= octeon_switch.o

I guess you could just use the normal r4k_fpu.o r4k_switch.o here and handle the rest of the Cavium bits like other non-standard architecture features in switch_to() and finish_arch_switch:

#define switch_to(prev, next, last)                                     \
do {                                                                    \
        __mips_mt_fpaff_switch_to(prev);                                \
        if (cpu_has_dsp)                                                \
                __save_dsp(prev);                                       \
        if (cpu_has_cavium)                                             \
                __save_cavium_stuff(prev);                              \
        (last) = resume(prev, next, task_thread_info(next));            \

} while (0)

#define finish_arch_switch(prev)                                        \
do {                                                                    \
        if (cpu_has_cavium)                                             \
                __restore_cavium_stuff(prev);                           \
        if (cpu_has_dsp)                                                \
                __restore_dsp(current);                                 \
        if (cpu_has_userlocal)                                          \
                write_c0_userlocal(current_thread_info()->tp_value);    \
        __restore_watch();                                              \

} while (0)

?

arch/mips/kernel/Makefile CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/n · line 100

Quoted 1 line
arch/mips/kernel/Makefile +1 -0
+CFLAGS_ptrace.o	= -I$(OCTEON_ROOT)/executive

Huh?

arch/mips/kernel/Makefile obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o · line 40

Quoted 13 lines
arch/mips/kernel/Makefile +4 -0
 obj-$(CONFIG_CPU_TX49XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
 obj-$(CONFIG_CPU_VR41XX)	+= c-r4k.o cex-gen.o tlb-r4k.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= c-octeon.o cex-oct.o tlb-r4k.o
 
 obj-$(CONFIG_IP22_CPU_SCACHE)	+= sc-ip22.o
 obj-$(CONFIG_R5000_CPU_SCACHE)  += sc-r5k.o
@@ -34,3 +35,7 @@ obj-$(CONFIG_RM7000_CPU_SCACHE)	+= sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)	+= sc-mips.o
 
 EXTRA_CFLAGS += -Werror
+
+OCTEON_ROOT = $(srctree)/arch/mips/cavium-octeon
+CFLAGS_c-octeon.o	= -I$(OCTEON_ROOT)/executive

I've not noticed anything in c-octeon.c which would require this -I flag.

Ralf

#32 lore raw

Re: [PATCH 15/36] Probe for Cavium OCTEON CPUs.

In reply to David Daney
Quoted 32 lines · David Daney
---
 arch/mips/kernel/cpu-probe.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)
arch/mips/kernel/cpu-probe.c +10 -0
index 30f7e8c..fc2403c 100644
@@ -154,6 +154,7 @@ void __init check_wait(void)
 	case CPU_25KF:
 	case CPU_PR4450:
 	case CPU_BCM3302:
+	case CPU_CAVIUM_OCTEON:
 		cpu_wait = r4k_wait;
 		break;
 
@@ -815,6 +816,27 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c)
 	}
 }
 
+static inline void cpu_probe_cavium(struct cpuinfo_mips *c)
+{
+	decode_configs(c);
+	switch (c->processor_id & 0xff00) {
+	case PRID_IMP_CAVIUM_CN38XX:
+	case PRID_IMP_CAVIUM_CN31XX:
+	case PRID_IMP_CAVIUM_CN30XX:
+	case PRID_IMP_CAVIUM_CN58XX:
+	case PRID_IMP_CAVIUM_CN56XX:

arch/mips/kernel/cpu-probe.c static inline void cpu_probe_broadcom(struct cpuinfo_mips *c) · line 837

Quoted 10 lines
arch/mips/kernel/cpu-probe.c +10 -0
+	case PRID_IMP_CAVIUM_CN50XX:
+	case PRID_IMP_CAVIUM_CN52XX:
+		c->cputype = CPU_CAVIUM_OCTEON;
+		break;
+	default:
+		printk(KERN_INFO "Unknown Octeon chip!\n");
+		c->cputype = CPU_UNKNOWN;
+		break;
+	}
+	mips_probe_watch_registers(c);

We probably should move the mips_probe_watch_registers() into mips_probe_watch_registers(). I notice the function is only getting called from cpu_probe_mips(). Iow the watch register support won't work for CPUs made by any other vendor. So I suggest below patch. Plus all of the above patch sans the mips_probe_watch_registers call on top.

Ralf

arch/mips/kernel/cpu-probe.c +12 -10
index 0cf1545..008230f 100644
@@ -652,21 +652,24 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
 
 static void __cpuinit decode_configs(struct cpuinfo_mips *c)
 {
+	int ok;
+
 	/* MIPS32 or MIPS64 compliant CPU.  */
 	c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
 	             MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
 
 	c->scache.flags = MIPS_CACHE_NOT_PRESENT;
 
-	/* Read Config registers.  */
-	if (!decode_config0(c))
-		return;			/* actually worth a panic() */
-	if (!decode_config1(c))
-		return;
-	if (!decode_config2(c))
-		return;
-	if (!decode_config3(c))
-		return;
+	ok = decode_config0(c);			/* Read Config registers.  */
+	BUG_ON(!ok);
+	if (ok)
+		ok = decode_config1(c))
+	if (ok)
+		ok = decode_config2(c);
+	if (ok)
+		ok = decode_config3(c);
+
+	mips_probe_watch_registers(c);
 }
 
 #ifdef CONFIG_CPU_MIPSR2
@@ -678,7 +681,6 @@ static inline void spram_config(void) {}
 static inline void cpu_probe_mips(struct cpuinfo_mips *c)
 {
 	decode_configs(c);
-	mips_probe_watch_registers(c);
 	switch (c->processor_id & 0xff00) {
 	case PRID_IMP_4KC:
 		c->cputype = CPU_4KC;
author Acked-by
#33 lore raw

Re: [PATCH 15/36] Probe for Cavium OCTEON CPUs.

Ralf Baechle wrote:
[...]

arch/mips/kernel/cpu-probe.c

Quoted 15 lines

We probably should move the mips_probe_watch_registers() into mips_probe_watch_registers(). I notice the function is only getting called from cpu_probe_mips(). Iow the watch register support won't work for CPUs made by any other vendor. So I suggest below patch. Plus all of the above patch sans the mips_probe_watch_registers call on top.

Ralf

arch/mips/kernel/cpu-probe.c +0 -0
index 0cf1545..008230f 100644

This seems sane to me assuming that alchemy, sibyte, sandcraft, nxp, and broadcom all have standard mips{32,64} watch registers (i.e., if the watch bit in config1 is set the registers have mips semantics).

David Daney

#34 lore raw

Re: [PATCH 15/36] Probe for Cavium OCTEON CPUs.

Quoted 5 lines · David Daney

This seems sane to me assuming that alchemy, sibyte, sandcraft, nxp, and broadcom all have standard mips{32,64} watch registers (i.e., if the watch bit in config1 is set the registers have mips semantics).

The watch bit is a standard feature of the MIPS R1/R2 architecture. What Sandcraft did was bascially an RM7000 clone with some extensions. I'm still trying to track somebody who could verify the correctness of that code as I don't have Sandcraft docs ...

Ralf

#35 lore raw

Re: [PATCH 15/36] Probe for Cavium OCTEON CPUs.

Quoted 11 lines · Ralf Baechle
Quoted 3 lines · David Daney

This seems sane to me assuming that alchemy, sibyte, sandcraft, nxp, and broadcom all have standard mips{32,64} watch registers (i.e., if the watch bit in config1 is set the registers have mips semantics).

The watch bit is a standard feature of the MIPS R1/R2 architecture. What Sandcraft did was bascially an RM7000 clone with some extensions. I'm still trying to track somebody who could verify the correctness of that code as I don't have Sandcraft docs ...

R4400 and R10K have the watch registers, but they do not have mips semantics, so are not currently usable with the watch register support.
This is why I initially was very conservative about the conditions
under which I probed watch registers. So I think it is good to try to verify these things.

David Daney

#36 lore raw

Re: [PATCH 15/36] Probe for Cavium OCTEON CPUs.

Quoted 11 lines · David Daney
Quoted 5 lines

The watch bit is a standard feature of the MIPS R1/R2 architecture. What Sandcraft did was bascially an RM7000 clone with some extensions. I'm still trying to track somebody who could verify the correctness of that code as I don't have Sandcraft docs ...

R4400 and R10K have the watch registers, but they do not have mips semantics, so are not currently usable with the watch register support. This is why I initially was very conservative about the conditions under which I probed watch registers. So I think it is good to try to verify these things.

All the esotheric stuff really is covered in cpu_probe_legacy. Anything else should comply with MIPS32/MIPS64. Exceptions apply.

Thanks to an old advertisment leaflet I was able to find that the Sandcraft SR71000 is indeed a MIPS64 processor, so the patch was right.

Ralf

#37 lore raw

Re: [PATCH 15/36] Probe for Cavium OCTEON CPUs.

In reply to David Daney
Quoted 4 lines · David Daney

R4400 and R10K have the watch registers, but they do not have mips semantics,
so are not currently usable with the watch register support. This is why I
initially was very conservative about the conditions under which I probed watch registers. So I think it is good to try to verify these things.

Neither is a MIPS architecture processor -- they are legacy MIPS III and
MIPS IV processors, respectively, and as such do not have a MIPS-compliant set of CP0 Config registers nor they support the select specifier for coprocessor transfer operations (although unlike some earlier implementations they do have a CP0.Config register). Watchpoint support would have to be done specifically for them; as I have a moderate interest in it and I have R4000/R4400 hardware, I may look into it eventually (but then, I have meant so for some last six years or so, so...). The same applies to the R4650 which defines watchpoints in yet a different way, but that one does not have an MMU, so we can safely skip it for the time being.

Maciej

#38 lore raw

Re: [PATCH 15/36] Probe for Cavium OCTEON CPUs.

In reply to Ralf Baechle

Hello.

Quoted 2 lines · Ralf Baechle

We probably should move the mips_probe_watch_registers() into mips_probe_watch_registers(). I notice the function is only getting

Move the function into itself? ;-)

WBR, Sergei

#39 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

In reply to David Daney
Quoted 2 lines · David Daney

On mips{32,64}r2, the ebase isn't just CAC_BASE, but also the part of read_c0_ebase() too.

That's a standard R2 feature - yet you were hiding it behind some ifdef Cavium. No good. The patch was also missing another location to fix up, set_uncached_handler().

Another thing I noticed is that we don't use write_c0_ebase(), so the firmware better setup this correctly or we crash and burn. We better should initialize that right ...

So below my version which solves the first mentioned problem. Just like the bitops patch I posted earlier today this patch has become entirely unrelated to the rest of the series so can applied before or after the rest of the series.

Ralf

 arch/mips/kernel/traps.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
arch/mips/kernel/traps.c +9 -4
Index: linux-mips/arch/mips/kernel/traps.c
===================================================================
@@ -1576,6 +1576,8 @@ void __cpuinit set_uncached_handler(unsi
 #ifdef CONFIG_64BIT
 	unsigned long uncached_ebase = TO_UNCAC(ebase);
 #endif
+	if (cpu_has_mips_r2)
+		ebase += (read_c0_ebase() & 0x3ffff000);
 
 	if (!addr)
 		panic(panic_null_cerr);
@@ -1609,8 +1611,11 @@ void __init trap_init(void)
 
 	if (cpu_has_veic || cpu_has_vint)
 		ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
-	else
+	else {
 		ebase = CAC_BASE;
+		if (cpu_has_mips_r2)
+			ebase += (read_c0_ebase() & 0x3ffff000);
+	}
 
 	per_cpu_trap_init();
 
@@ -1718,11 +1723,11 @@ void __init trap_init(void)
 
 	if (cpu_has_vce)
 		/* Special exception: R4[04]00 uses also the divec space. */
-		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x100);
+		memcpy((void *)(ebase + 0x180), &except_vec3_r4000, 0x100);
 	else if (cpu_has_4kex)
-		memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80);
+		memcpy((void *)(ebase + 0x180), &except_vec3_generic, 0x80);
 	else
-		memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80);
+		memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80);
 
 	signal_init();
 #ifdef CONFIG_MIPS32_COMPAT
#40 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

Quoted 3 lines · Ralf Baechle

Another thing I noticed is that we don't use write_c0_ebase(), so the firmware better setup this correctly or we crash and burn. We better should initialize that right ...

Well, your version still does not do it...

Quoted 4 lines

So below my version which solves the first mentioned problem. Just like the bitops patch I posted earlier today this patch has become entirely unrelated to the rest of the series so can applied before or after the rest of the series.

Anyway this is much better than the original proposal indeed, thanks.

Maciej

#41 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

Quoted 9 lines · Maciej W. Rozycki
Quoted 3 lines · Ralf Baechle

Another thing I noticed is that we don't use write_c0_ebase(), so the firmware better setup this correctly or we crash and burn. We better should initialize that right ...

Well, your version still does not do it...

Maciej

#42 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

Quoted 7 lines · Chad Reese

From an Octeon perspective, we'd prefer that the kernel not touch ebase as we set it in the bootloader. The bootloader sets the proper value based on the number of kernels being loaded and which cores the kernel is loaded on. This allows some interesting things, like running 16 kernels each on a different CPU. Although 16 kernels is just a toy project, we have a number of customers that run two kernels. They choose which cores the kernels run on dynamically at boot time.

I see your point. If we dynamically allocate memory for exception handlers at run-time and point ebase to it multi-kernel systems should till work unless maybe the firmware gets disturbed by such a change of ebase.

Ralf

#43 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

Quoted 3 lines · Ralf Baechle

I see your point. If we dynamically allocate memory for exception handlers at run-time and point ebase to it multi-kernel systems should till work unless maybe the firmware gets disturbed by such a change of ebase.

A run-time sanity check would do I suppose. I.e. that ebase points to
somewhere within installed RAM and does not clash with the kernel in some way. We can mark that page as reserved in the memory map then; something we ought to regardless and which I gather we do not at the moment.

Maciej

#44 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

In reply to Chad Reese
Quoted 8 lines · On Tuesday 28 October 2008 17:13:44 Chad Reese wrote:
Quoted 6 lines · Maciej W. Rozycki
Quoted 3 lines · Ralf Baechle

Another thing I noticed is that we don't use write_c0_ebase(), so the firmware better setup this correctly or we crash and burn. We better should initialize that right ...

Well, your version still does not do it...

Quoted 7 lines

From an Octeon perspective, we'd prefer that the kernel not touch ebase as we set it in the bootloader. The bootloader sets the proper value based on the number of kernels being loaded and which cores the kernel is loaded on. This allows some interesting things, like running 16 kernels each on a different CPU. Although 16 kernels is just a toy project, we have a number of customers that run two kernels. They choose which cores the kernels run on dynamically at boot time.

Our system (4KSd-based) also has the bootloader setting EBASE, so like Chad, I'd prefer it if the kernel doesn't (always?) do it, please. (We're not doing anything tricky like what Chad mentions, it's just that on the SoC in question, it's perhaps the easiest way of handling the situation.)

cheers!

	-blf-
Signature · 4 lines
“How many surrealists does it take to   | Brian Foster
 change a lightbulb? Three. One calms   | somewhere in south of France
 the warthog, and two fill the bathtub  |   Stop E$$o (ExxonMobil)!
 with brightly-coloured machine tools.” |      http://www.stopesso.com
#45 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

In reply to Maciej W. Rozycki
Quoted 5 lines · Maciej W. Rozycki
Quoted 3 lines

Another thing I noticed is that we don't use write_c0_ebase(), so the firmware better setup this correctly or we crash and burn. We better should initialize that right ...

Well, your version still does not do it...

Intentional omission. We didn't do that before and Cavium didn't seem to need it so we can put off fixing that for a little longer. It needs a little thought to get NUMA right ...

Ralf

#46 lore raw

Re: [PATCH 11/36] MIPSR2 ebase isn't just CAC_BASE

Quoted 3 lines · Ralf Baechle

Intentional omission. We didn't do that before and Cavium didn't seem to need it so we can put off fixing that for a little longer. It needs a little thought to get NUMA right ...

Fair enough, but it is left a bit ambiguous in your description.

Maciej

#47 lore raw

Re: [PATCH 09/36] Enable mips32 style bitops for Cavium OCTEON.

In reply to David Daney
Quoted 5 lines · David Daney

Enable the basic bitops like __ffs and so forth that would normally be on if we were MIPS32 or MIPS64, but aren't since Cavium sets neither.

Counter proposal. Instead of making the #ifdefery worse get rid of it entirely and give the optimizer a little hand with __builtin_constant_p to get things right for every platform.

(This patch has gone through it-looks-good-so-it-must-be-good QA ...)

Ralf

 arch/mips/include/asm/bitops.h       |  108 +++++++++++++++++++++++------------
 arch/mips/include/asm/cpu-features.h |    2 
 2 files changed, 75 insertions(+), 35 deletions(-)
arch/mips/include/asm/bitops.h +73 -35
Index: linux-mips/arch/mips/include/asm/bitops.h
===================================================================
@@ -558,39 +558,67 @@ static inline void __clear_bit_unlock(un
 	__clear_bit(nr, addr);
 }
 
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
-
 /*
  * Return the bit position (0..63) of the most significant 1 bit in a word
  * Returns -1 if no 1 bit exists
  */
 static inline unsigned long __fls(unsigned long x)
 {
-	int lz;
+	int num;
 
-	if (sizeof(x) == 4) {
+	if (BITS_PER_LONG == 32 &&
+	    __builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r) {
 		__asm__(
 		"	.set	push					\n"
 		"	.set	mips32					\n"
 		"	clz	%0, %1					\n"
 		"	.set	pop					\n"
-		: "=r" (lz)
+		: "=r" (num)
 		: "r" (x));
 
-		return 31 - lz;
+		return 31 - num;
 	}
 
-	BUG_ON(sizeof(x) != 8);
+	if (BITS_PER_LONG == 64 &&
+	    __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) {
+		__asm__(
+		"	.set	push					\n"
+		"	.set	mips64					\n"
+		"	dclz	%0, %1					\n"
+		"	.set	pop					\n"
+		: "=r" (num)
+		: "r" (x));
+
+		return 63 - num;
+	}
 
-	__asm__(
-	"	.set	push						\n"
-	"	.set	mips64						\n"
-	"	dclz	%0, %1						\n"
-	"	.set	pop						\n"
-	: "=r" (lz)
-	: "r" (x));
+	num = BITS_PER_LONG - 1;
 
-	return 63 - lz;
+#if BITS_PER_LONG == 64
+	if (!(word & (~0ul << 32))) {
+		num -= 32;
+		word <<= 32;
+	}
+#endif
+	if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
+		num -= 16;
+		word <<= 16;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
+		num -= 8;
+		word <<= 8;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
+		num -= 4;
+		word <<= 4;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
+		num -= 2;
+		word <<= 2;
+	}
+	if (!(word & (~0ul << (BITS_PER_LONG-1))))
+		num -= 1;
+	return num;
 }
 
 /*
@@ -614,21 +642,41 @@ static inline unsigned long __ffs(unsign
  */
 static inline int fls(int word)
 {
-	__asm__("clz %0, %1" : "=r" (word) : "r" (word));
+	int r;
 
-	return 32 - word;
-}
+	if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r) {
+		__asm__("clz %0, %1" : "=r" (word) : "r" (word));
 
-#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPS64)
-static inline int fls64(__u64 word)
-{
-	__asm__("dclz %0, %1" : "=r" (word) : "r" (word));
+		return 32 - word;
+	}
 
-	return 64 - word;
+	r = 32;
+	if (!x)
+		return 0;
+	if (!(x & 0xffff0000u)) {
+		x <<= 16;
+		r -= 16;
+	}
+	if (!(x & 0xff000000u)) {
+		x <<= 8;
+		r -= 8;
+	}
+	if (!(x & 0xf0000000u)) {
+		x <<= 4;
+		r -= 4;
+	}
+	if (!(x & 0xc0000000u)) {
+		x <<= 2;
+		r -= 2;
+	}
+	if (!(x & 0x80000000u)) {
+		x <<= 1;
+		r -= 1;
+	}
+	return r;
 }
-#else
+
 #include <asm-generic/bitops/fls64.h>
-#endif
 
 /*
  * ffs - find first bit set.
@@ -646,16 +694,6 @@ static inline int ffs(int word)
 	return fls(word & -word);
 }
 
-#else
-
-#include <asm-generic/bitops/__ffs.h>
-#include <asm-generic/bitops/__fls.h>
-#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/fls64.h>
-
-#endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */
-
 #include <asm-generic/bitops/ffz.h>
 #include <asm-generic/bitops/find.h>
 
arch/mips/include/asm/cpu-features.h +2 -0
Index: linux-mips/arch/mips/include/asm/cpu-features.h
===================================================================
@@ -141,6 +141,8 @@
 #define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2)
 #define cpu_has_mips_r1	(cpu_has_mips32r1 | cpu_has_mips64r1)
 #define cpu_has_mips_r2	(cpu_has_mips32r2 | cpu_has_mips64r2)
+#define cpu_has_mips_r	(cpu_has_mips32r1 | cpu_has_mips32r2 | \
+			 cpu_has_mips64r1 | cpu_has_mips64r2)
 
 #ifndef cpu_has_dsp
 #define cpu_has_dsp		(cpu_data[0].ases & MIPS_ASE_DSP)
#48 lore raw

Re: [PATCH 07/36] Don't assume boot CPU is CPU0 if MIPS_DISABLE_BOOT_CPU_ZERO set.

In reply to David Daney
Quoted 2 lines · David Daney

MIPS SMP code currently assumes that the boot CPU will be CPU0 of the system. For some systems, this may not be the case.

It always the logic CPU 0 though the physical number might be different.

Quoted 6 lines
arch/mips/kernel/smp.c +0 -0
index b79ea70..e2597ef 100644
@@ -195,12 +195,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 /* preload SMP state for boot cpu */

arch/mips/kernel/smp.c void __init smp_prepare_cpus(unsigned int max_cpus) · line 205

Quoted 10 lines
arch/mips/kernel/smp.c +2 -0
 void __devinit smp_prepare_boot_cpu(void)
 {
+#ifndef MIPS_DISABLE_BOOT_CPU_ZERO
 	/*
 	 * This assumes that bootup is always handled by the processor
 	 * with the logic and physical number 0.
 	 */
 	__cpu_number_map[0] = 0;
 	__cpu_logical_map[0] = 0;
+#endif

This assignment is redundant anyway - the kernel is starting with the array zeroed. So just remove this entire initialization and do your array initialization in your mp_ops->smp_setup.

And to tell another dirty secret - the arrays currently happen to be unused though we should use them at some point ...

Ralf

#49 lore raw

Re: [PATCH 07/36] Don't assume boot CPU is CPU0 if MIPS_DISABLE_BOOT_CPU_ZERO set.

Quoted 19 lines · Ralf Baechle
Quoted 2 lines · David Daney

MIPS SMP code currently assumes that the boot CPU will be CPU0 of the system. For some systems, this may not be the case.

It always the logic CPU 0 though the physical number might be different.

Quoted 12 lines
arch/mips/kernel/smp.c +1 -0
index b79ea70..e2597ef 100644
@@ -195,12 +195,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 /* preload SMP state for boot cpu */
 void __devinit smp_prepare_boot_cpu(void)
 {
+#ifndef MIPS_DISABLE_BOOT_CPU_ZERO
 	/*
 	 * This assumes that bootup is always handled by the processor
 	 * with the logic and physical number 0.
Quoted 9 lines

arch/mips/kernel/smp.c void __init smp_prepare_cpus(unsigned int max_cpus) · line 205

Quoted 4 lines
arch/mips/kernel/smp.c +1 -0
 	 */
 	__cpu_number_map[0] = 0;
 	__cpu_logical_map[0] = 0;
+#endif

This assignment is redundant anyway - the kernel is starting with the array zeroed. So just remove this entire initialization and do your array initialization in your mp_ops->smp_setup.

We already do that. I will just delete this section unconditionally.

David Daney

#50 lore raw

Re: [PATCH 07/36] Don't assume boot CPU is CPU0 if MIPS_DISABLE_BOOT_CPU_ZERO set.

Quoted 6 lines · David Daney
Quoted 4 lines

This assignment is redundant anyway - the kernel is starting with the array zeroed. So just remove this entire initialization and do your array initialization in your mp_ops->smp_setup.

We already do that. I will just delete this section unconditionally.

I've already committed that locally.

Ralf

#51 lore raw

Re: [PATCH 06/36] Add Cavium OCTEON processor CSR definitions

In reply to David Daney
Quoted 6 lines · David Daney
---
 .../cavium-octeon/executive/cvmx-csr-addresses.h   | 8391 ++++++
 arch/mips/cavium-octeon/executive/cvmx-csr-enums.h |   86 +
 .../cavium-octeon/executive/cvmx-csr-typedefs.h    |27517 ++++++++++++++++++++

27517 lines in a header and it's all junk?

#52 lore raw

Re: [PATCH 06/36] Add Cavium OCTEON processor CSR definitions

Quoted 10 lines · Christoph Hellwig
Quoted 6 lines · David Daney
---
 .../cavium-octeon/executive/cvmx-csr-addresses.h   | 8391 ++++++
 arch/mips/cavium-octeon/executive/cvmx-csr-enums.h |   86 +
 .../cavium-octeon/executive/cvmx-csr-typedefs.h    |27517 ++++++++++++++++++++

27517 lines in a header and it's all junk?

I'm glad you asked. No it is not all junk.

That file contains the bit definitions for all on-chip registers.

We are interested in transforming this information into a form suitable for inclusion in the kernel. Any specific suggestions as to improve the patch will be considered.

Several possibilities are:

1) Don't typedef all the unions in cvmx-csr-typedefs.h. An rename the file so it doesn't contain the reprehensible word 'typedef'

2) Break cvmx-csr-addresses.h and cvmx-csr-typedefs.h into several parts, one for each functional block in the processor.

There are obviously other options as well...

Thanks,
David Daney

#53 lore raw

Re: [PATCH 06/36] Add Cavium OCTEON processor CSR definitions

Quoted 21 lines · David Daney
Quoted 11 lines · Christoph Hellwig
Quoted 7 lines · David Daney

---

.../cavium-octeon/executive/cvmx-csr-addresses.h   | 8391 ++++++
arch/mips/cavium-octeon/executive/cvmx-csr-enums.h |   86 +
.../cavium-octeon/executive/cvmx-csr-typedefs.h    |27517 

++++++++++++++++++++

27517 lines in a header and it's all junk?

I'm glad you asked. No it is not all junk.

That file contains the bit definitions for all on-chip registers.

We are interested in transforming this information into a form suitable for inclusion in the kernel. Any specific suggestions as to improve the patch will be considered.

Quoted 7 lines

Several possibilities are:

1) Don't typedef all the unions in cvmx-csr-typedefs.h. An rename the file so it doesn't contain the reprehensible word 'typedef'

2) Break cvmx-csr-addresses.h and cvmx-csr-typedefs.h into several parts, one for each functional block in the processor.

The two are very good ideas, but not really the important part.

Adding a massive inline for every single bit somewhere in a register just doesn't make sense. Take a look at normal hardware defintion headers in the tree.

Have a simple define for each _register_ (applied relative to a bank/chip or whatever is appropriate) and if the individual bits in it are important add bit defintions, too - leaving the arithmetics for it to the caller.

Also please don't add defintions for those blocks of the chip that aren't actually used in your submission. That's best done with one header per block that can be added with the driver supporting that block.

And yes, we had this a few times. Eventually I'll make a fortune by selling a perl script generating proper headers out of common HDLs..

#54 lore raw

Re: [PATCH 06/36] Add Cavium OCTEON processor CSR definitions

Quoted 39 lines · Christoph Hellwig
Quoted 19 lines · David Daney
Quoted 10 lines · Christoph Hellwig
Quoted 7 lines · David Daney

---

.../cavium-octeon/executive/cvmx-csr-addresses.h   | 8391 ++++++
arch/mips/cavium-octeon/executive/cvmx-csr-enums.h |   86 +
.../cavium-octeon/executive/cvmx-csr-typedefs.h    |27517 

++++++++++++++++++++

27517 lines in a header and it's all junk?

I'm glad you asked. No it is not all junk.

That file contains the bit definitions for all on-chip registers.

We are interested in transforming this information into a form suitable for inclusion in the kernel. Any specific suggestions as to improve the patch will be considered.

Quoted 7 lines

Several possibilities are:

1) Don't typedef all the unions in cvmx-csr-typedefs.h. An rename the file so it doesn't contain the reprehensible word 'typedef'

2) Break cvmx-csr-addresses.h and cvmx-csr-typedefs.h into several parts, one for each functional block in the processor.

The two are very good ideas, but not really the important part.

Adding a massive inline for every single bit somewhere in a register just doesn't make sense. Take a look at normal hardware defintion headers in the tree.

Have a simple define for each _register_ (applied relative to a bank/chip or whatever is appropriate) and if the individual bits in it are important add bit defintions, too - leaving the arithmetics for it to the caller.

Quoted 8 lines

Also please don't add defintions for those blocks of the chip that aren't actually used in your submission. That's best done with one header per block that can be added with the driver supporting that block.

And yes, we had this a few times. Eventually I'll make a fortune by selling a perl script generating proper headers out of common HDLs..

The kernel's normal method of defining a whole bunch of #defines for every bit doesn't really work well for maintainability. Many times it isn't obvious which define goes with which register. It also doesn't cover changes in hardware over time. Our CSR definitions are generated from the RTL and designed to catch incompatibilities that might show up in the future. The "s" member of the union contains all of the bits that
don't conflict for the known Octeon chips. If a bit changes meaning in
a future Octeon, then the bit will disappear out of the "s" member and only be available through the chip specific unions. This makes the compiler find all usages of the change bit and forces you to fix them.

It also doesn't make sense to leave out registers that aren't currently used. How does anyone write a new driver if the register definitions aren't there? Typing these in after the fact is a waste of time.

Chad

#55 lore raw

Re: [PATCH 06/36] Add Cavium OCTEON processor CSR definitions

In reply to David Daney
Quoted 8 lines · David Daney

That file contains the bit definitions for all on-chip registers.

We are interested in transforming this information into a form suitable for inclusion in the kernel. Any specific suggestions as to improve the patch will be considered.

Several possibilities are:

Quoted 7 lines

1) Don't typedef all the unions in cvmx-csr-typedefs.h. An rename the file so it doesn't contain the reprehensible word 'typedef'

2) Break cvmx-csr-addresses.h and cvmx-csr-typedefs.h into several parts, one for each functional block in the processor.

There are obviously other options as well...

The use of bitfields also fires back:

+ struct cvmx_ciu_intx_en1_w1c_cn58xx {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+#else
+ uint64_t wdog:16;
+ uint64_t reserved_16_63:48;
+#endif

You see, everything was defined twice. And gcc even recent gccs tend to do silly stuff with bitfields when combined with volatile:

struct foo {
	unsigned int	x:1;
	unsigned int	y:4;
};

void bar(volatile struct foo *p)

{
	p->x = 1;
	p->y++;
}

which gcc 4.3 for a MIPS32R2 target will compile into:

	lw	$3, 0($4)
	li	$2, 1
	ins	$3, $2, 31, 1
	sw	$3, 0($4)
	lw	$2, 0($4)
	lw	$3, 0($4)
	ext	$2, $2, 27, 4
	addiu	$2, $2, 1
	ins	$3, $2, 27, 4
	sw	$3, 0($4)
	j	$31
	nop

Imagine struct foo was describing a hardware register so the pointer to it was marked volatile. A human coder wouldn't have done multiple loads / stores. Worse, if you actually want to change multiple fields in a register atomically then with bitfields you have _no_ possibility to enforce that.

The Linux programming programming model relies on accessor functions like readl, ioread32 etc. Those take addresses as arguments - but bitfields don't have addresses in C ...

So exec summary: bitfields bad for such low-level stuff.

Ralf

#56 lore raw

Re: [PATCH 06/36] Add Cavium OCTEON processor CSR definitions

Quoted 26 lines · Ralf Baechle
struct foo {
	unsigned int	x:1;
	unsigned int	y:4;
};

void bar(volatile struct foo *p)

{
	p->x = 1;
	p->y++;
}

which gcc 4.3 for a MIPS32R2 target will compile into:

	lw	$3, 0($4)
	li	$2, 1
	ins	$3, $2, 31, 1
	sw	$3, 0($4)
	lw	$2, 0($4)
	lw	$3, 0($4)
	ext	$2, $2, 27, 4
	addiu	$2, $2, 1
	ins	$3, $2, 27, 4
	sw	$3, 0($4)
	j	$31
	nop
Quoted 6 lines

Imagine struct foo was describing a hardware register so the pointer to it was marked volatile. A human coder wouldn't have done multiple loads / stores. Worse, if you actually want to change multiple fields in a register atomically then with bitfields you have _no_ possibility to enforce that.

This is bogus as you use a false premise. For your test case the compiler is generating exactly the accesses you are requesting by declaring the thing as volatile.

Quoted 4 lines

The Linux programming programming model relies on accessor functions like readl, ioread32 etc. Those take addresses as arguments - but bitfields don't have addresses in C ...

We too use accessor functions, as they are required on certain classes of registers to obtain correct semantics.

The real question is if manipulating the values after they are obtained with the accessor is done correctly. My assertion is that although it may not be the One True Kernel Way, our structure bitfield definitions result in correct semantics and have better compile time error checking than can be obtained when coding a bunch of explicit masks and shifts.

That is not to say that I am adverse to eliminating the structure bitfield definitions, but we should not use incorrect register access semantics as the reason, as it is not a valid argument.

David Daney

#57 lore raw

Re: [PATCH 06/36] Add Cavium OCTEON processor CSR definitions

In reply to Ralf Baechle
Quoted 2 lines · Ralf Baechle

You see, everything was defined twice. And gcc even recent gccs tend to do silly stuff with bitfields when combined with volatile:

Nobody should be using volatile anyway. It doesn't supply anywhere close to the needed control for a register access. C would be a better language if the volatile keyword was removed.

Quoted 3 lines

The Linux programming programming model relies on accessor functions like readl, ioread32 etc. Those take addresses as arguments - but bitfields don't have addresses in C ...

It is not valid on Octeon to access parts of CSR registers. You must do a 64bit access, change whatever fields you want, and store the new value. For this model bitfields work very well. GCC converts the bitfield operations into bit insert and extract for mips64r2. It also automatically combines multiple field sets into a single immediate load.

Quoted 1 line

So exec summary: bitfields bad for such low-level stuff.

Having spent a few years programming Octeon in various ways, bitfields work really well for it.

Chad

#58 lore raw

Re: [PATCH 05/36] Add Cavium OCTEON processor support files to and arch/mips/cavium-octeon/executive

In reply to David Daney

So what is all this crappy code actually supposed to do?

A little explanation would help, or in this case I suspect even an explanation might not help anyore.

Quoted 5,771 lines · David Daney
---
 arch/mips/cavium-octeon/executive/Makefile         |   26 +
 arch/mips/cavium-octeon/executive/cvmx-asm.h       |  427 ++++++++++
 arch/mips/cavium-octeon/executive/cvmx-bootinfo.h  |  238 ++++++
 arch/mips/cavium-octeon/executive/cvmx-bootmem.c   |  897 ++++++++++++++++++++
 arch/mips/cavium-octeon/executive/cvmx-bootmem.h   |  403 +++++++++
 arch/mips/cavium-octeon/executive/cvmx-interrupt.h |  255 ++++++
 arch/mips/cavium-octeon/executive/cvmx-l2c.c       |  711 ++++++++++++++++
 arch/mips/cavium-octeon/executive/cvmx-l2c.h       |  328 +++++++
 .../executive/cvmx-linux-kernel-exports.c          |   30 +
 arch/mips/cavium-octeon/executive/cvmx-packet.h    |   64 ++
 arch/mips/cavium-octeon/executive/cvmx-platform.h  |   56 ++
 arch/mips/cavium-octeon/executive/cvmx-spinlock.h  |  376 ++++++++
 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c   |  113 +++
 arch/mips/cavium-octeon/executive/cvmx-sysinfo.h   |  144 ++++
 arch/mips/cavium-octeon/executive/cvmx-warn.c      |   44 +
 arch/mips/cavium-octeon/executive/cvmx-warn.h      |   46 +
 arch/mips/cavium-octeon/executive/cvmx.h           |  772 +++++++++++++++++
 arch/mips/cavium-octeon/executive/octeon-feature.h |  120 +++
 arch/mips/cavium-octeon/executive/octeon-model.c   |  328 +++++++
 arch/mips/cavium-octeon/executive/octeon-model.h   |  225 +++++
 20 files changed, 5603 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/cavium-octeon/executive/Makefile
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-asm.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootinfo.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-interrupt.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-linux-kernel-exports.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-packet.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-platform.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-spinlock.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.c
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.h
 create mode 100644 arch/mips/cavium-octeon/executive/cvmx.h
 create mode 100644 arch/mips/cavium-octeon/executive/octeon-feature.h
 create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.c
 create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.h
arch/mips/cavium-octeon/executive/Makefile new file +26 -0
new file mode 100644
index 0000000..cb51c58
@@ -0,0 +1,26 @@
+#
+# Makefile for the Cavium Octeon specific kernel interface routines
+# under Linux.
+#
+# 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) 2005-2007 Cavium Networks
+#
+
+
+source:=$(srctree)/$(src)
+EXTRA_CFLAGS	+= -I$(source) -I$(source)/config
+
+executive-files := cvmx-bootmem.o
+executive-files += cvmx-l2c.o
+executive-files += cvmx-sysinfo.o
+executive-files += cvmx-warn.o
+executive-files += octeon-model.o
+executive-files += cvmx-linux-kernel-exports.o
+obj-y := $(executive-files)
+
+executive-obj-files := $(executive-files:%=$(obj)/%)
+executive-src-files := $(executive-obj-files:%.o=%.c)
+
arch/mips/cavium-octeon/executive/cvmx-asm.h new file +427 -0
new file mode 100644
index 0000000..8516456
@@ -0,0 +1,427 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ *
+ * This is file defines ASM primitives for the executive.
+
+ *
+ *
+ */
+#ifndef __CVMX_ASM_H__
+#define __CVMX_ASM_H__
+
+#include "octeon-model.h"
+
+/* other useful stuff */
+#define CVMX_BREAK asm volatile ("break")
+#define CVMX_SYNC asm volatile ("sync" : : :"memory")
+/* String version of SYNCW macro for using in inline asm constructs */
+#define CVMX_SYNCW_STR "syncw\nsyncw\n"
+#ifdef __OCTEON__
+#define CVMX_SYNCIO asm volatile ("nop")	/* Deprecated, will be removed in future release */
+#define CVMX_SYNCIOBDMA asm volatile ("synciobdma" : : :"memory")
+#define CVMX_SYNCIOALL asm volatile ("nop")	/* Deprecated, will be removed in future release */
+	/* We actually use two syncw instructions in a row when we need a write
+	   memory barrier. This is because the CN3XXX series of Octeons have
+	   errata Core-401. This can cause a single syncw to not enforce
+	   ordering under very rare conditions. Even if it is rare, better safe
+	   than sorry */
+#define CVMX_SYNCW asm volatile ("syncw\nsyncw\n" : : :"memory")
+	/* Define new sync instructions to be normal SYNC instructions for
+	   operating systems that use threads */
+#define CVMX_SYNCWS CVMX_SYNCW
+#define CVMX_SYNCS  CVMX_SYNC
+#define CVMX_SYNCWS_STR CVMX_SYNCW_STR
+#else
+	/* Not using a Cavium compiler, always use the slower sync so the assembler stays happy */
+#define CVMX_SYNCIO asm volatile ("nop")	/* Deprecated, will be removed in future release */
+#define CVMX_SYNCIOBDMA asm volatile ("sync" : : :"memory")
+#define CVMX_SYNCIOALL asm volatile ("nop")	/* Deprecated, will be removed in future release */
+#define CVMX_SYNCW asm volatile ("sync" : : :"memory")
+#define CVMX_SYNCWS CVMX_SYNCW
+#define CVMX_SYNCS  CVMX_SYNC
+#define CVMX_SYNCWS_STR CVMX_SYNCW_STR
+#endif
+#define CVMX_SYNCI(address, offset) asm volatile ("synci " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+#define CVMX_PREFETCH0(address) CVMX_PREFETCH(address, 0)
+#define CVMX_PREFETCH128(address) CVMX_PREFETCH(address, 128)
+/* a normal prefetch */
+#define CVMX_PREFETCH(address, offset) CVMX_PREFETCH_PREF0(address, offset)
+/* normal prefetches that use the pref instruction */
+#define CVMX_PREFETCH_PREF0(address, offset) asm volatile ("pref 0, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+#define CVMX_PREFETCH_PREF1(address, offset) asm volatile ("pref 1, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+#define CVMX_PREFETCH_PREF6(address, offset) asm volatile ("pref 6, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+#define CVMX_PREFETCH_PREF7(address, offset) asm volatile ("pref 7, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+/* prefetch into L1, do not put the block in the L2 */
+#define CVMX_PREFETCH_NOTL2(address, offset) asm volatile ("pref 4, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+#define CVMX_PREFETCH_NOTL22(address, offset) asm volatile ("pref 5, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+/* prefetch into L2, do not put the block in the L1 */
+#define CVMX_PREFETCH_L2(address, offset) asm volatile ("pref 28, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+/* CVMX_PREPARE_FOR_STORE makes each byte of the block unpredictable (actually old value or zero) until */
+/* that byte is stored to (by this or another processor. Note that the value of each byte is not only */
+/* unpredictable, but may also change again - up until the point when one of the cores stores to the */
+/* byte. */
+#define CVMX_PREPARE_FOR_STORE(address, offset) asm volatile ("pref 30, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+/* This is a command headed to the L2 controller to tell it to clear its dirty bit for a */
+/* block. Basically, SW is telling HW that the current version of the block will not be */
+/* used. */
+#define CVMX_DONT_WRITE_BACK(address, offset) asm volatile ("pref 29, " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address))
+
+#define CVMX_ICACHE_INVALIDATE  { CVMX_SYNC; asm volatile ("synci 0($0)" : : ); }	/* flush stores, invalidate entire icache */
+#define CVMX_ICACHE_INVALIDATE2 { CVMX_SYNC; asm volatile ("cache 0, 0($0)" : : ); }	/* flush stores, invalidate entire icache */
+#define CVMX_DCACHE_INVALIDATE  { CVMX_SYNC; asm volatile ("cache 9, 0($0)" : : ); }	/* complete prefetches, invalidate entire dcache */
+
+/* new instruction to make RC4 run faster */
+#define CVMX_BADDU(result, input1, input2) asm ("baddu %[rd],%[rs],%[rt]" : [rd] "=d" (result) : [rs] "d" (input1) , [rt] "d" (input2))
+
+/* misc v2 stuff */
+#define CVMX_ROTR(result, input1, shiftconst) asm ("rotr %[rd],%[rs]," CVMX_TMP_STR(shiftconst) : [rd] "=d" (result) : [rs] "d" (input1))
+#define CVMX_ROTRV(result, input1, input2) asm ("rotrv %[rd],%[rt],%[rs]" : [rd] "=d" (result) : [rt] "d" (input1) , [rs] "d" (input2))
+#define CVMX_DROTR(result, input1, shiftconst) asm ("drotr %[rd],%[rs]," CVMX_TMP_STR(shiftconst) : [rd] "=d" (result) : [rs] "d" (input1))
+#define CVMX_DROTRV(result, input1, input2) asm ("drotrv %[rd],%[rt],%[rs]" : [rd] "=d" (result) : [rt] "d" (input1) , [rs] "d" (input2))
+#define CVMX_SEB(result, input1) asm ("seb %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
+#define CVMX_SEH(result, input1) asm ("seh %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
+#define CVMX_DSBH(result, input1) asm ("dsbh %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
+#define CVMX_DSHD(result, input1) asm ("dshd %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
+#define CVMX_WSBH(result, input1) asm ("wsbh %[rd],%[rt]" : [rd] "=d" (result) : [rt] "d" (input1))
+
+/* Endian swap */
+#define CVMX_ES64(result, input) \
+        do {\
+        CVMX_DSBH(result, input); \
+        CVMX_DSHD(result, result); \
+        } while (0)
+#define CVMX_ES32(result, input) \
+        do {\
+        CVMX_WSBH(result, input); \
+        CVMX_ROTR(result, result, 16); \
+        } while (0)
+
+/* extract and insert - NOTE that pos and len variables must be constants! */
+/* the P variants take len rather than lenm1 */
+/* the M1 variants take lenm1 rather than len */
+#define CVMX_EXTS(result,input,pos,lenm1) asm ("exts %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : [rs] "d" (input))
+#define CVMX_EXTSP(result,input,pos,len) CVMX_EXTS(result,input,pos,(len)-1)
+
+#define CVMX_DEXT(result,input,pos,len) asm ("dext %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len) : [rt] "=d" (result) : [rs] "d" (input))
+#define CVMX_DEXTM1(result,input,pos,lenm1) CVMX_DEXT(result,input,pos,(lenm1)+1)
+
+#define CVMX_EXT(result,input,pos,len) asm ("ext %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len) : [rt] "=d" (result) : [rs] "d" (input))
+#define CVMX_EXTM1(result,input,pos,lenm1) CVMX_EXT(result,input,pos,(lenm1)+1)
+
+/* removed */
+/* #define CVMX_EXTU(result,input,pos,lenm1) asm ("extu %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : [rs] "d" (input)) */
+/* #define CVMX_EXTUP(result,input,pos,len) CVMX_EXTU(result,input,pos,(len)-1) */
+
+#define CVMX_CINS(result,input,pos,lenm1) asm ("cins %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : [rs] "d" (input))
+#define CVMX_CINSP(result,input,pos,len) CVMX_CINS(result,input,pos,(len)-1)
+
+#define CVMX_DINS(result,input,pos,len) asm ("dins %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len): [rt] "=d" (result): [rs] "d" (input), "[rt]" (result))
+#define CVMX_DINSM1(result,input,pos,lenm1) CVMX_DINS(result,input,pos,(lenm1)+1)
+#define CVMX_DINSC(result,pos,len) asm ("dins %[rt],$0," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len): [rt] "=d" (result): "[rt]" (result))
+#define CVMX_DINSCM1(result,pos,lenm1) CVMX_DINSC(result,pos,(lenm1)+1)
+
+#define CVMX_INS(result,input,pos,len) asm ("ins %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len): [rt] "=d" (result): [rs] "d" (input), "[rt]" (result))
+#define CVMX_INSM1(result,input,pos,lenm1) CVMX_INS(result,input,pos,(lenm1)+1)
+#define CVMX_INSC(result,pos,len) asm ("ins %[rt],$0," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(len): [rt] "=d" (result): "[rt]" (result))
+#define CVMX_INSCM1(result,pos,lenm1) CVMX_INSC(result,pos,(lenm1)+1)
+
+/* removed */
+/* #define CVMX_INS0(result,input,pos,lenm1) asm("ins0 %[rt],%[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1): [rt] "=d" (result): [rs] "d" (input), "[rt]" (result)) */
+/* #define CVMX_INS0P(result,input,pos,len) CVMX_INS0(result,input,pos,(len)-1) */
+/* #define CVMX_INS0C(result,pos,lenm1) asm ("ins0 %[rt],$0," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(lenm1) : [rt] "=d" (result) : "[rt]" (result)) */
+/* #define CVMX_INS0CP(result,pos,len) CVMX_INS0C(result,pos,(len)-1) */
+
+#define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+#define CVMX_DCLZ(result, input) asm ("dclz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+#define CVMX_CLO(result, input) asm ("clo %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+#define CVMX_DCLO(result, input) asm ("dclo %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+#define CVMX_POP(result, input) asm ("pop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+#define CVMX_DPOP(result, input) asm ("dpop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+
+/* some new cop0-like stuff */
+#define CVMX_RDHWR(result, regstr) asm volatile ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result))
+#define CVMX_RDHWRNV(result, regstr) asm ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result))
+#define CVMX_DI(result) asm volatile ("di %[rt]" : [rt] "=d" (result))
+#define CVMX_DI_NULL asm volatile ("di")
+#define CVMX_EI(result) asm volatile ("ei %[rt]" : [rt] "=d" (result))
+#define CVMX_EI_NULL asm volatile ("ei")
+#define CVMX_EHB asm volatile ("ehb")
+
+/* mul stuff */
+#define CVMX_MTM0(m) asm volatile ("mtm0 %[rs]" : : [rs] "d" (m))
+#define CVMX_MTM1(m) asm volatile ("mtm1 %[rs]" : : [rs] "d" (m))
+#define CVMX_MTM2(m) asm volatile ("mtm2 %[rs]" : : [rs] "d" (m))
+#define CVMX_MTP0(p) asm volatile ("mtp0 %[rs]" : : [rs] "d" (p))
+#define CVMX_MTP1(p) asm volatile ("mtp1 %[rs]" : : [rs] "d" (p))
+#define CVMX_MTP2(p) asm volatile ("mtp2 %[rs]" : : [rs] "d" (p))
+#define CVMX_VMULU(dest,mpcand,accum) asm volatile ("vmulu %[rd],%[rs],%[rt]" : [rd] "=d" (dest) : [rs] "d" (mpcand), [rt] "d" (accum))
+#define CVMX_VMM0(dest,mpcand,accum) asm volatile ("vmm0 %[rd],%[rs],%[rt]" : [rd] "=d" (dest) : [rs] "d" (mpcand), [rt] "d" (accum))
+#define CVMX_V3MULU(dest,mpcand,accum) asm volatile ("v3mulu %[rd],%[rs],%[rt]" : [rd] "=d" (dest) : [rs] "d" (mpcand), [rt] "d" (accum))
+
+/* branch stuff */
+/* these are hard to make work because the compiler does not realize that the */
+/* instruction is a branch so may optimize away the label */
+/* the labels to these next two macros must not include a ":" at the end */
+#define CVMX_BBIT1(var, pos, label) asm volatile ("bbit1 %[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(label) : : [rs] "d" (var))
+#define CVMX_BBIT0(var, pos, label) asm volatile ("bbit0 %[rs]," CVMX_TMP_STR(pos) "," CVMX_TMP_STR(label) : : [rs] "d" (var))
+/* the label to this macro must include a ":" at the end */
+#define CVMX_ASM_LABEL(label) label \
+                             asm volatile (CVMX_TMP_STR(label) : : )
+
+/* */
+/* Low-latency memory stuff */
+/* */
+/* set can be 0-1 */
+#define CVMX_MT_LLM_READ_ADDR(set,val)    asm volatile ("dmtc2 %[rt],0x0400+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
+#define CVMX_MT_LLM_WRITE_ADDR_INTERNAL(set,val)   asm volatile ("dmtc2 %[rt],0x0401+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
+#define CVMX_MT_LLM_READ64_ADDR(set,val)  asm volatile ("dmtc2 %[rt],0x0404+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
+#define CVMX_MT_LLM_WRITE64_ADDR_INTERNAL(set,val) asm volatile ("dmtc2 %[rt],0x0405+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
+#define CVMX_MT_LLM_DATA(set,val)         asm volatile ("dmtc2 %[rt],0x0402+(8*(" CVMX_TMP_STR(set) "))" : : [rt] "d" (val))
+#define CVMX_MF_LLM_DATA(set,val)         asm volatile ("dmfc2 %[rt],0x0402+(8*(" CVMX_TMP_STR(set) "))" : [rt] "=d" (val) : )
+
+/* load linked, store conditional */
+#define CVMX_LL(dest, address, offset) asm volatile ("ll %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (dest) : [rbase] "d" (address))
+#define CVMX_LLD(dest, address, offset) asm volatile ("lld %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (dest) : [rbase] "d" (address))
+#define CVMX_SC(srcdest, address, offset) asm volatile ("sc %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" (address), "[rt]" (srcdest))
+#define CVMX_SCD(srcdest, address, offset) asm volatile ("scd %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" (address), "[rt]" (srcdest))
+
+/* load/store word left/right */
+#define CVMX_LWR(srcdest, address, offset) asm volatile ("lwr %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" (address), "[rt]" (srcdest))
+#define CVMX_LWL(srcdest, address, offset) asm volatile ("lwl %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" (address), "[rt]" (srcdest))
+#define CVMX_LDR(srcdest, address, offset) asm volatile ("ldr %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" (address), "[rt]" (srcdest))
+#define CVMX_LDL(srcdest, address, offset) asm volatile ("ldl %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : [rt] "=d" (srcdest) : [rbase] "d" (address), "[rt]" (srcdest))
+
+#define CVMX_SWR(src, address, offset) asm volatile ("swr %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
+#define CVMX_SWL(src, address, offset) asm volatile ("swl %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
+#define CVMX_SDR(src, address, offset) asm volatile ("sdr %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
+#define CVMX_SDL(src, address, offset) asm volatile ("sdl %[rt], " CVMX_TMP_STR(offset) "(%[rbase])" : : [rbase] "d" (address), [rt] "d" (src))
+
+/* */
+/* Useful crypto ASM's */
+/* */
+
+/* CRC */
+
+#define CVMX_MT_CRC_POLYNOMIAL(val)         asm volatile ("dmtc2 %[rt],0x4200" : : [rt] "d" (val))
+#define CVMX_MT_CRC_IV(val)                 asm volatile ("dmtc2 %[rt],0x0201" : : [rt] "d" (val))
+#define CVMX_MT_CRC_LEN(val)                asm volatile ("dmtc2 %[rt],0x1202" : : [rt] "d" (val))
+#define CVMX_MT_CRC_BYTE(val)               asm volatile ("dmtc2 %[rt],0x0204" : : [rt] "d" (val))
+#define CVMX_MT_CRC_HALF(val)               asm volatile ("dmtc2 %[rt],0x0205" : : [rt] "d" (val))
+#define CVMX_MT_CRC_WORD(val)               asm volatile ("dmtc2 %[rt],0x0206" : : [rt] "d" (val))
+#define CVMX_MT_CRC_DWORD(val)              asm volatile ("dmtc2 %[rt],0x1207" : : [rt] "d" (val))
+#define CVMX_MT_CRC_VAR(val)                asm volatile ("dmtc2 %[rt],0x1208" : : [rt] "d" (val))
+#define CVMX_MT_CRC_POLYNOMIAL_REFLECT(val) asm volatile ("dmtc2 %[rt],0x4210" : : [rt] "d" (val))
+#define CVMX_MT_CRC_IV_REFLECT(val)         asm volatile ("dmtc2 %[rt],0x0211" : : [rt] "d" (val))
+#define CVMX_MT_CRC_BYTE_REFLECT(val)       asm volatile ("dmtc2 %[rt],0x0214" : : [rt] "d" (val))
+#define CVMX_MT_CRC_HALF_REFLECT(val)       asm volatile ("dmtc2 %[rt],0x0215" : : [rt] "d" (val))
+#define CVMX_MT_CRC_WORD_REFLECT(val)       asm volatile ("dmtc2 %[rt],0x0216" : : [rt] "d" (val))
+#define CVMX_MT_CRC_DWORD_REFLECT(val)      asm volatile ("dmtc2 %[rt],0x1217" : : [rt] "d" (val))
+#define CVMX_MT_CRC_VAR_REFLECT(val)        asm volatile ("dmtc2 %[rt],0x1218" : : [rt] "d" (val))
+
+#define CVMX_MF_CRC_POLYNOMIAL(val)         asm volatile ("dmfc2 %[rt],0x0200" : [rt] "=d" (val) : )
+#define CVMX_MF_CRC_IV(val)                 asm volatile ("dmfc2 %[rt],0x0201" : [rt] "=d" (val) : )
+#define CVMX_MF_CRC_IV_REFLECT(val)         asm volatile ("dmfc2 %[rt],0x0203" : [rt] "=d" (val) : )
+#define CVMX_MF_CRC_LEN(val)                asm volatile ("dmfc2 %[rt],0x0202" : [rt] "=d" (val) : )
+
+/* MD5 and SHA-1 */
+
+/* pos can be 0-6 */
+#define CVMX_MT_HSH_DAT(val, pos)    asm volatile ("dmtc2 %[rt],0x0040+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+#define CVMX_MT_HSH_DATZ(pos)       asm volatile ("dmtc2    $0,0x0040+" CVMX_TMP_STR(pos) :                 :               )
+/* pos can be 0-14 */
+#define CVMX_MT_HSH_DATW(val, pos)   asm volatile ("dmtc2 %[rt],0x0240+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+#define CVMX_MT_HSH_DATWZ(pos)      asm volatile ("dmtc2    $0,0x0240+" CVMX_TMP_STR(pos) :                 :               )
+#define CVMX_MT_HSH_STARTMD5(val)   asm volatile ("dmtc2 %[rt],0x4047"                   :                 : [rt] "d" (val))
+#define CVMX_MT_HSH_STARTSHA(val)   asm volatile ("dmtc2 %[rt],0x4057"                   :                 : [rt] "d" (val))
+#define CVMX_MT_HSH_STARTSHA256(val)   asm volatile ("dmtc2 %[rt],0x404f"                   :                 : [rt] "d" (val))
+#define CVMX_MT_HSH_STARTSHA512(val)   asm volatile ("dmtc2 %[rt],0x424f"                   :                 : [rt] "d" (val))
+/* pos can be 0-3 */
+#define CVMX_MT_HSH_IV(val, pos)     asm volatile ("dmtc2 %[rt],0x0048+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+/* pos can be 0-7 */
+#define CVMX_MT_HSH_IVW(val, pos)     asm volatile ("dmtc2 %[rt],0x0250+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+
+/* pos can be 0-6 */
+#define CVMX_MF_HSH_DAT(val, pos)    asm volatile ("dmfc2 %[rt],0x0040+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+/* pos can be 0-14 */
+#define CVMX_MF_HSH_DATW(val, pos)   asm volatile ("dmfc2 %[rt],0x0240+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+/* pos can be 0-3 */
+#define CVMX_MF_HSH_IV(val, pos)     asm volatile ("dmfc2 %[rt],0x0048+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+/* pos can be 0-7 */
+#define CVMX_MF_HSH_IVW(val, pos)     asm volatile ("dmfc2 %[rt],0x0250+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+
+/* 3DES */
+
+/* pos can be 0-2 */
+#define CVMX_MT_3DES_KEY(val, pos)   asm volatile ("dmtc2 %[rt],0x0080+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+#define CVMX_MT_3DES_IV(val)        asm volatile ("dmtc2 %[rt],0x0084"                   :                 : [rt] "d" (val))
+#define CVMX_MT_3DES_ENC_CBC(val)   asm volatile ("dmtc2 %[rt],0x4088"                   :                 : [rt] "d" (val))
+#define CVMX_MT_3DES_ENC(val)       asm volatile ("dmtc2 %[rt],0x408a"                   :                 : [rt] "d" (val))
+#define CVMX_MT_3DES_DEC_CBC(val)   asm volatile ("dmtc2 %[rt],0x408c"                   :                 : [rt] "d" (val))
+#define CVMX_MT_3DES_DEC(val)       asm volatile ("dmtc2 %[rt],0x408e"                   :                 : [rt] "d" (val))
+#define CVMX_MT_3DES_RESULT(val)    asm volatile ("dmtc2 %[rt],0x0098"                   :                 : [rt] "d" (val))
+
+/* pos can be 0-2 */
+#define CVMX_MF_3DES_KEY(val, pos)   asm volatile ("dmfc2 %[rt],0x0080+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+#define CVMX_MF_3DES_IV(val)        asm volatile ("dmfc2 %[rt],0x0084"                   : [rt] "=d" (val) :               )
+#define CVMX_MF_3DES_RESULT(val)    asm volatile ("dmfc2 %[rt],0x0088"                   : [rt] "=d" (val) :               )
+
+/* KASUMI */
+
+/* pos can be 0-1 */
+#define CVMX_MT_KAS_KEY(val, pos)    CVMX_MT_3DES_KEY(val, pos)
+#define CVMX_MT_KAS_ENC_CBC(val)    asm volatile ("dmtc2 %[rt],0x4089"                   :                 : [rt] "d" (val))
+#define CVMX_MT_KAS_ENC(val)        asm volatile ("dmtc2 %[rt],0x408b"                   :                 : [rt] "d" (val))
+#define CVMX_MT_KAS_RESULT(val)     CVMX_MT_3DES_RESULT(val)
+
+/* pos can be 0-1 */
+#define CVMX_MF_KAS_KEY(val, pos)    CVMX_MF_3DES_KEY(val, pos)
+#define CVMX_MF_KAS_RESULT(val)     CVMX_MF_3DES_RESULT(val)
+
+/* AES */
+
+#define CVMX_MT_AES_ENC_CBC0(val)   asm volatile ("dmtc2 %[rt],0x0108"                   :                 : [rt] "d" (val))
+#define CVMX_MT_AES_ENC_CBC1(val)   asm volatile ("dmtc2 %[rt],0x3109"                   :                 : [rt] "d" (val))
+#define CVMX_MT_AES_ENC0(val)       asm volatile ("dmtc2 %[rt],0x010a"                   :                 : [rt] "d" (val))
+#define CVMX_MT_AES_ENC1(val)       asm volatile ("dmtc2 %[rt],0x310b"                   :                 : [rt] "d" (val))
+#define CVMX_MT_AES_DEC_CBC0(val)   asm volatile ("dmtc2 %[rt],0x010c"                   :                 : [rt] "d" (val))
+#define CVMX_MT_AES_DEC_CBC1(val)   asm volatile ("dmtc2 %[rt],0x310d"                   :                 : [rt] "d" (val))
+#define CVMX_MT_AES_DEC0(val)       asm volatile ("dmtc2 %[rt],0x010e"                   :                 : [rt] "d" (val))
+#define CVMX_MT_AES_DEC1(val)       asm volatile ("dmtc2 %[rt],0x310f"                   :                 : [rt] "d" (val))
+/* pos can be 0-3 */
+#define CVMX_MT_AES_KEY(val, pos)    asm volatile ("dmtc2 %[rt],0x0104+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+/* pos can be 0-1 */
+#define CVMX_MT_AES_IV(val, pos)     asm volatile ("dmtc2 %[rt],0x0102+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+#define CVMX_MT_AES_KEYLENGTH(val)  asm volatile ("dmtc2 %[rt],0x0110"                   :                 : [rt] "d" (val))	/* write the keylen */
+/* pos can be 0-1 */
+#define CVMX_MT_AES_RESULT(val, pos) asm volatile ("dmtc2 %[rt],0x0100+" CVMX_TMP_STR(pos) :                 : [rt] "d" (val))
+
+/* pos can be 0-1 */
+#define CVMX_MF_AES_RESULT(val, pos) asm volatile ("dmfc2 %[rt],0x0100+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+/* pos can be 0-1 */
+#define CVMX_MF_AES_IV(val, pos)     asm volatile ("dmfc2 %[rt],0x0102+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+/* pos can be 0-3 */
+#define CVMX_MF_AES_KEY(val, pos)    asm volatile ("dmfc2 %[rt],0x0104+" CVMX_TMP_STR(pos) : [rt] "=d" (val) :               )
+#define CVMX_MF_AES_KEYLENGTH(val)  asm volatile ("dmfc2 %[rt],0x0110"                   : [rt] "=d" (val) :               )	/* read the keylen */
+#define CVMX_MF_AES_DAT0(val)       asm volatile ("dmfc2 %[rt],0x0111"                   : [rt] "=d" (val) :               )	/* first piece of input data */
+/* GFM COP2 macros */
+/* index can be 0 or 1 */
+#define CVMX_MF_GFM_MUL(val, index)     asm volatile ("dmfc2 %[rt],0x0258+" CVMX_TMP_STR(index) : [rt] "=d" (val) :               )
+#define CVMX_MF_GFM_POLY(val)           asm volatile ("dmfc2 %[rt],0x025e"                      : [rt] "=d" (val) :               )
+#define CVMX_MF_GFM_RESINP(val, index)  asm volatile ("dmfc2 %[rt],0x025a+" CVMX_TMP_STR(index) : [rt] "=d" (val) :               )
+
+#define CVMX_MT_GFM_MUL(val, index)     asm volatile ("dmtc2 %[rt],0x0258+" CVMX_TMP_STR(index) :                 : [rt] "d" (val))
+#define CVMX_MT_GFM_POLY(val)           asm volatile ("dmtc2 %[rt],0x025e"                      :                 : [rt] "d" (val))
+#define CVMX_MT_GFM_RESINP(val, index)  asm volatile ("dmtc2 %[rt],0x025a+" CVMX_TMP_STR(index) :                 : [rt] "d" (val))
+#define CVMX_MT_GFM_XOR0(val)           asm volatile ("dmtc2 %[rt],0x025c"                      :                 : [rt] "d" (val))
+#define CVMX_MT_GFM_XORMUL1(val)        asm volatile ("dmtc2 %[rt],0x425d"                      :                 : [rt] "d" (val))
+
+/* check_ordering stuff */
+#if 0
+#define CVMX_MF_CHORD(dest)         asm volatile ("dmfc2 %[rt],0x400" : [rt] "=d" (dest) : )
+#else
+#define CVMX_MF_CHORD(dest)         CVMX_RDHWR(dest, 30)
+#endif
+
+#if 0
+#define CVMX_MF_CYCLE(dest)         asm volatile ("dmfc0 %[rt],$9,6" : [rt] "=d" (dest) : )	/* Use (64-bit) CvmCount register rather than Count */
+#else
+#define CVMX_MF_CYCLE(dest)         CVMX_RDHWR(dest, 31)	/* reads the current (64-bit) CvmCount value */
+#endif
+
+#define CVMX_MT_CYCLE(src)         asm volatile ("dmtc0 %[rt],$9,6" :: [rt] "d" (src))
+
+#define CVMX_MF_CACHE_ERR(val)            asm volatile ("dmfc0 %[rt],$27,0" :  [rt] "=d" (val):)
+#define CVMX_MF_DCACHE_ERR(val)           asm volatile ("dmfc0 %[rt],$27,1" :  [rt] "=d" (val):)
+#define CVMX_MF_CVM_MEM_CTL(val)          asm volatile ("dmfc0 %[rt],$11,7" :  [rt] "=d" (val):)
+#define CVMX_MF_CVM_CTL(val)              asm volatile ("dmfc0 %[rt],$9,7"  :  [rt] "=d" (val):)
+#define CVMX_MT_CACHE_ERR(val)            asm volatile ("dmtc0 %[rt],$27,0" : : [rt] "d" (val))
+#define CVMX_MT_DCACHE_ERR(val)           asm volatile ("dmtc0 %[rt],$27,1" : : [rt] "d" (val))
+#define CVMX_MT_CVM_MEM_CTL(val)          asm volatile ("dmtc0 %[rt],$11,7" : : [rt] "d" (val))
+#define CVMX_MT_CVM_CTL(val)              asm volatile ("dmtc0 %[rt],$9,7"  : : [rt] "d" (val))
+
+/* Macros for TLB */
+#define CVMX_TLBWI                       asm volatile ("tlbwi" : : )
+#define CVMX_TLBWR                       asm volatile ("tlbwr" : : )
+#define CVMX_TLBR                        asm volatile ("tlbr" : : )
+#define CVMX_MT_ENTRY_HIGH(val)          asm volatile ("dmtc0 %[rt],$10,0" : : [rt] "d" (val))
+#define CVMX_MT_ENTRY_LO_0(val)          asm volatile ("dmtc0 %[rt],$2,0" : : [rt] "d" (val))
+#define CVMX_MT_ENTRY_LO_1(val)          asm volatile ("dmtc0 %[rt],$3,0" : : [rt] "d" (val))
+#define CVMX_MT_PAGEMASK(val)            asm volatile ("mtc0 %[rt],$5,0" : : [rt] "d" (val))
+#define CVMX_MT_PAGEGRAIN(val)           asm volatile ("mtc0 %[rt],$5,1" : : [rt] "d" (val))
+#define CVMX_MT_TLB_INDEX(val)           asm volatile ("mtc0 %[rt],$0,0" : : [rt] "d" (val))
+#define CVMX_MT_TLB_CONTEXT(val)         asm volatile ("dmtc0 %[rt],$4,0" : : [rt] "d" (val))
+#define CVMX_MT_TLB_WIRED(val)           asm volatile ("mtc0 %[rt],$6,0" : : [rt] "d" (val))
+#define CVMX_MT_TLB_RANDOM(val)          asm volatile ("mtc0 %[rt],$1,0" : : [rt] "d" (val))
+#define CVMX_MF_ENTRY_LO_0(val)          asm volatile ("dmfc0 %[rt],$2,0" :  [rt] "=d" (val):)
+#define CVMX_MF_ENTRY_LO_1(val)          asm volatile ("dmfc0 %[rt],$3,0" :  [rt] "=d" (val):)
+#define CVMX_MF_ENTRY_HIGH(val)          asm volatile ("dmfc0 %[rt],$10,0" :  [rt] "=d" (val):)
+#define CVMX_MF_PAGEMASK(val)            asm volatile ("mfc0 %[rt],$5,0" :  [rt] "=d" (val):)
+#define CVMX_MF_PAGEGRAIN(val)           asm volatile ("mfc0 %[rt],$5,1" :  [rt] "=d" (val):)
+#define CVMX_MF_TLB_WIRED(val)           asm volatile ("mfc0 %[rt],$6,0" :  [rt] "=d" (val):)
+#define CVMX_MF_TLB_RANDOM(val)          asm volatile ("mfc0 %[rt],$1,0" :  [rt] "=d" (val):)
+#define TLB_DIRTY   (0x1ULL<<2)
+#define TLB_VALID   (0x1ULL<<1)
+#define TLB_GLOBAL  (0x1ULL<<0)
+
+/* assembler macros to guarantee byte loads/stores are used */
+/* for an unaligned 16-bit access (these use AT register) */
+/* we need the hidden argument (__a) so that GCC gets the dependencies right */
+#define CVMX_LOADUNA_INT16(result, address, offset) \
+	{ char *__a = (char *)(address); \
+	  asm ("ulh %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] "=d" (result) : [rbase] "d" (__a), "m"(__a[offset]), "m"(__a[offset + 1])); }
+#define CVMX_LOADUNA_UINT16(result, address, offset) \
+	{ char *__a = (char *)(address); \
+	  asm ("ulhu %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] "=d" (result) : [rbase] "d" (__a), "m"(__a[offset + 0]), "m"(__a[offset + 1])); }
+#define CVMX_STOREUNA_INT16(data, address, offset) \
+	{ char *__a = (char *)(address); \
+	  asm ("ush %[rsrc], " CVMX_TMP_STR(offset) "(%[rbase])" : "=m"(__a[offset + 0]), "=m"(__a[offset + 1]): [rsrc] "d" (data), [rbase] "d" (__a)); }
+
+#define CVMX_LOADUNA_INT32(result, address, offset) \
+	{ char *__a = (char *)(address); \
+	  asm ("ulw %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] "=d" (result) : \
+	       [rbase] "d" (__a), "m"(__a[offset + 0]), "m"(__a[offset + 1]), "m"(__a[offset + 2]), "m"(__a[offset + 3])); }
+#define CVMX_STOREUNA_INT32(data, address, offset) \
+	{ char *__a = (char *)(address); \
+	  asm ("usw %[rsrc], " CVMX_TMP_STR(offset) "(%[rbase])" : \
+	       "=m"(__a[offset + 0]), "=m"(__a[offset + 1]), "=m"(__a[offset + 2]), "=m"(__a[offset + 3]) : \
+	       [rsrc] "d" (data), [rbase] "d" (__a)); }
+
+#define CVMX_LOADUNA_INT64(result, address, offset) \
+	{ char *__a = (char *)(address); \
+	  asm ("uld %[rdest], " CVMX_TMP_STR(offset) "(%[rbase])" : [rdest] "=d" (result) : \
+	       [rbase] "d" (__a), "m"(__a[offset + 0]), "m"(__a[offset + 1]), "m"(__a[offset + 2]), "m"(__a[offset + 3]), \
+	       "m"(__a[offset + 4]), "m"(__a[offset + 5]), "m"(__a[offset + 6]), "m"(__a[offset + 7])); }
+#define CVMX_STOREUNA_INT64(data, address, offset) \
+	{ char *__a = (char *)(address); \
+	  asm ("usd %[rsrc], " CVMX_TMP_STR(offset) "(%[rbase])" : \
+	       "=m"(__a[offset + 0]), "=m"(__a[offset + 1]), "=m"(__a[offset + 2]), "=m"(__a[offset + 3]), \
+	       "=m"(__a[offset + 4]), "=m"(__a[offset + 5]), "=m"(__a[offset + 6]), "=m"(__a[offset + 7]) : \
+	       [rsrc] "d" (data), [rbase] "d" (__a)); }
+
+#endif /* __CVMX_ASM_H__ */
arch/mips/cavium-octeon/executive/cvmx-bootinfo.h new file +238 -0
new file mode 100644
index 0000000..acd1c57
@@ -0,0 +1,238 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ * Header file containing the ABI with the bootloader.
+ *
+ */
+
+#ifndef __CVMX_BOOTINFO_H__
+#define __CVMX_BOOTINFO_H__
+
+/* Current major and minor versions of the CVMX bootinfo block that is
+** passed from the bootloader to the application.  This is versioned
+** so that applications can properly handle multiple bootloader
+** versions. */
+#define CVMX_BOOTINFO_MAJ_VER 1
+#define CVMX_BOOTINFO_MIN_VER 2
+
+#if (CVMX_BOOTINFO_MAJ_VER == 1)
+#define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20
+/* This structure is populated by the bootloader.  For binary
+** compatibility the only changes that should be made are
+** adding members to the end of the structure, and the minor
+** version should be incremented at that time.
+** If an incompatible change is made, the major version
+** must be incremented, and the minor version should be reset
+** to 0.
+*/
+typedef struct {
+	uint32_t major_version;
+	uint32_t minor_version;
+
+	uint64_t stack_top;
+	uint64_t heap_base;
+	uint64_t heap_end;
+	uint64_t desc_vaddr;
+
+	uint32_t exception_base_addr;
+	uint32_t stack_size;
+	uint32_t flags;
+	uint32_t core_mask;
+	uint32_t dram_size;
+			 /**< DRAM size in megabytes */
+	uint32_t phy_mem_desc_addr;
+				 /**< physical address of free memory descriptor block*/
+	uint32_t debugger_flags_base_addr;
+					/**< used to pass flags from app to debugger */
+	uint32_t eclock_hz;
+			 /**< CPU clock speed, in hz */
+	uint32_t dclock_hz;
+			 /**< DRAM clock speed, in hz */
+	uint32_t reserved0;
+	uint16_t board_type;
+	uint8_t board_rev_major;
+	uint8_t board_rev_minor;
+	uint16_t reserved1;
+	uint8_t reserved2;
+	uint8_t reserved3;
+	char board_serial_number[CVMX_BOOTINFO_OCTEON_SERIAL_LEN];
+	uint8_t mac_addr_base[6];
+	uint8_t mac_addr_count;
+#if (CVMX_BOOTINFO_MIN_VER >= 1)
+	/* Several boards support compact flash on the Octeon boot bus.  The CF
+	 ** memory spaces may be mapped to different addresses on different boards.
+	 ** These are the physical addresses, so care must be taken to use the correct
+	 ** XKPHYS/KSEG0 addressing depending on the application's ABI.
+	 ** These values will be 0 if CF is not present */
+	uint64_t compact_flash_common_base_addr;
+	uint64_t compact_flash_attribute_base_addr;
+	/* Base address of the LED display (as on EBT3000 board)
+	 ** This will be 0 if LED display not present. */
+	uint64_t led_display_base_addr;
+#endif
+#if (CVMX_BOOTINFO_MIN_VER >= 2)
+	uint32_t dfa_ref_clock_hz;
+	/**< DFA reference clock in hz (if applicable)*/
+	uint32_t config_flags;
+	/**< flags indicating various configuration options.  These
+	 ** flags supercede the 'flags' variable and should be used
+	 ** instead if available */
+#endif
+
+} cvmx_bootinfo_t;
+
+#define CVMX_BOOTINFO_CFG_FLAG_PCI_HOST			(1ull << 0)
+#define CVMX_BOOTINFO_CFG_FLAG_PCI_TARGET		(1ull << 1)
+#define CVMX_BOOTINFO_CFG_FLAG_DEBUG			(1ull << 2)
+#define CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC			(1ull << 3)
+/* This flag is set if the TLB mappings are not contained in the
+** 0x10000000 - 0x20000000 boot bus region. */
+#define CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING     (1ull << 4)
+#define CVMX_BOOTINFO_CFG_FLAG_BREAK			(1ull << 5)
+
+#endif /*   (CVMX_BOOTINFO_MAJ_VER == 1) */
+
+/* Type defines for board and chip types */
+enum cvmx_board_types_enum {
+	CVMX_BOARD_TYPE_NULL = 0,
+	CVMX_BOARD_TYPE_SIM = 1,
+	CVMX_BOARD_TYPE_EBT3000 = 2,
+	CVMX_BOARD_TYPE_KODAMA = 3,
+	CVMX_BOARD_TYPE_NIAGARA = 4,
+	CVMX_BOARD_TYPE_NAC38 = 5,	/* formerly NAO38 */
+	CVMX_BOARD_TYPE_THUNDER = 6,
+	CVMX_BOARD_TYPE_TRANTOR = 7,
+	CVMX_BOARD_TYPE_EBH3000 = 8,
+	CVMX_BOARD_TYPE_EBH3100 = 9,
+	CVMX_BOARD_TYPE_HIKARI = 10,
+	CVMX_BOARD_TYPE_CN3010_EVB_HS5 = 11,
+	CVMX_BOARD_TYPE_CN3005_EVB_HS5 = 12,
+	CVMX_BOARD_TYPE_KBP = 13,
+	CVMX_BOARD_TYPE_CN3020_EVB_HS5 = 14,	/* Deprecated, CVMX_BOARD_TYPE_CN3010_EVB_HS5 supports the CN3020 */
+	CVMX_BOARD_TYPE_EBT5800 = 15,
+	CVMX_BOARD_TYPE_NICPRO2 = 16,
+	CVMX_BOARD_TYPE_EBH5600 = 17,
+	CVMX_BOARD_TYPE_EBH5601 = 18,
+	CVMX_BOARD_TYPE_EBH5200 = 19,
+	CVMX_BOARD_TYPE_BBGW_REF = 20,
+	CVMX_BOARD_TYPE_NIC_XLE_4G = 21,
+	CVMX_BOARD_TYPE_EBT5600 = 22,
+	CVMX_BOARD_TYPE_EBH5201 = 23,
+	CVMX_BOARD_TYPE_MAX,
+
+	/* The range from CVMX_BOARD_TYPE_MAX to CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved
+	 ** for future SDK use. */
+
+	/* Set aside a range for customer boards.  These numbers are managed
+	 ** by Cavium.
+	 */
+	CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000,
+	CVMX_BOARD_TYPE_CUST_WSX16 = 10001,
+	CVMX_BOARD_TYPE_CUST_NS0216 = 10002,
+	CVMX_BOARD_TYPE_CUST_NB5 = 10003,
+	CVMX_BOARD_TYPE_CUST_WMR500 = 10004,
+	CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000,
+
+	/* Set aside a range for customer private use.  The SDK won't
+	 ** use any numbers in this range. */
+	CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
+	CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
+
+	/* The remaining range is reserved for future use. */
+};
+enum cvmx_chip_types_enum {
+	CVMX_CHIP_TYPE_NULL = 0,
+	CVMX_CHIP_SIM_TYPE_DEPRECATED = 1,
+	CVMX_CHIP_TYPE_OCTEON_SAMPLE = 2,
+	CVMX_CHIP_TYPE_MAX,
+};
+
+/* Compatability alias for NAC38 name change, planned to be removed from SDK 1.7 */
+#define CVMX_BOARD_TYPE_NAO38	CVMX_BOARD_TYPE_NAC38
+
+/* Functions to return string based on type */
+#define ENUM_BRD_TYPE_CASE(x)   case x: return(#x + 16);	/* Skip CVMX_BOARD_TYPE_ */
+static inline const char *cvmx_board_type_to_string(enum
+						    cvmx_board_types_enum type)
+{
+	switch (type) {
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT3000)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KODAMA)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIAGARA)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NAC38)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_THUNDER)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_TRANTOR)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3000)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3100)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_HIKARI)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3010_EVB_HS5)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3005_EVB_HS5)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KBP)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3020_EVB_HS5)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5800)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NICPRO2)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5600)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5601)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5200)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_BBGW_REF)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX)
+
+		    /* Customer boards listed here */
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WSX16)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NS0216)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NB5)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WMR500)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX)
+
+		    /* Customer private range */
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
+		    ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
+	}
+	return "Unsupported Board";
+}
+
+#define ENUM_CHIP_TYPE_CASE(x)   case x: return(#x + 15);	/* Skip CVMX_CHIP_TYPE */
+static inline const char *cvmx_chip_type_to_string(enum
+						   cvmx_chip_types_enum type)
+{
+	switch (type) {
+		ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_NULL)
+		    ENUM_CHIP_TYPE_CASE(CVMX_CHIP_SIM_TYPE_DEPRECATED)
+		    ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_OCTEON_SAMPLE)
+		    ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_MAX)
+	}
+	return "Unsupported Chip";
+}
+
+#endif /* __CVMX_BOOTINFO_H__ */
arch/mips/cavium-octeon/executive/cvmx-bootmem.c new file +897 -0
new file mode 100644
index 0000000..bb8b087
@@ -0,0 +1,897 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ * Simple allocate only memory allocator.  Used to allocate memory at application
+ * start time.
+ *
+ */
+
+#include "cvmx.h"
+#include "cvmx-spinlock.h"
+#include "cvmx-bootmem.h"
+
+/*#define DEBUG */
+
+#undef	MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+
+#undef	MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+
+#define ALIGN_ADDR_UP(addr, align)     (((addr) + (~(align))) & (align))
+
+static cvmx_bootmem_desc_t *cvmx_bootmem_desc;
+
+/* See header file for descriptions of functions */
+
+/* Wrapper functions are provided for reading/writing the size and
+ * next block values as these may not be directly addressible (in 32
+ * bit applications, for instance.)  Offsets of data elements in
+ * bootmem list, must match cvmx_bootmem_block_header_t */
+#define NEXT_OFFSET 0
+#define SIZE_OFFSET 8
+static void cvmx_bootmem_phy_set_size(uint64_t addr, uint64_t size)
+{
+	cvmx_write64_uint64((addr + SIZE_OFFSET) | (1ull << 63), size);
+}
+
+static void cvmx_bootmem_phy_set_next(uint64_t addr, uint64_t next)
+{
+	cvmx_write64_uint64((addr + NEXT_OFFSET) | (1ull << 63), next);
+}
+
+static uint64_t cvmx_bootmem_phy_get_size(uint64_t addr)
+{
+	return cvmx_read64_uint64((addr + SIZE_OFFSET) | (1ull << 63));
+}
+
+static uint64_t cvmx_bootmem_phy_get_next(uint64_t addr)
+{
+	return cvmx_read64_uint64((addr + NEXT_OFFSET) | (1ull << 63));
+}
+
+void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
+			       uint64_t min_addr, uint64_t max_addr)
+{
+	int64_t address;
+	address =
+	    cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment, 0);
+
+	if (address > 0)
+		return cvmx_phys_to_ptr(address);
+	else
+		return NULL;
+}
+
+void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address,
+				 uint64_t alignment)
+{
+	return cvmx_bootmem_alloc_range(size, alignment, address,
+					address + size);
+}
+
+void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment)
+{
+	return cvmx_bootmem_alloc_range(size, alignment, 0, 0);
+}
+
+void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
+				     uint64_t max_addr, uint64_t align,
+				     char *name)
+{
+	int64_t addr;
+
+	addr =
+	    cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, align,
+					       name, 0);
+	if (addr >= 0)
+		return cvmx_phys_to_ptr(addr);
+	else
+		return NULL;
+
+}
+
+void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address,
+				       char *name)
+{
+	return cvmx_bootmem_alloc_named_range (size, address,
+					       address + size, 0, name);
+}
+
+void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name)
+{
+	return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name);
+}
+
+int cvmx_bootmem_free_named(char *name)
+{
+	return cvmx_bootmem_phy_named_block_free(name, 0);
+}
+
+cvmx_bootmem_named_block_desc_t *cvmx_bootmem_find_named_block(char *name)
+{
+	return cvmx_bootmem_phy_named_block_find(name, 0);
+}
+
+void cvmx_bootmem_print_named(void)
+{
+	cvmx_bootmem_phy_named_block_print();
+}
+
+
+int cvmx_bootmem_init(void *mem_desc_ptr)
+{
+	/* Verify that the size of cvmx_spinlock_t meets our assumptions */
+	if (sizeof(cvmx_spinlock_t) != 4) {
+		cvmx_dprintf("ERROR: Unexpected size of cvmx_spinlock_t\n");
+		return -1;
+	}
+
+	/* Here we set the global pointer to the bootmem descriptor block.  This pointer will
+	 ** be used directly, so we will set it up to be directly usable by the application.
+	 ** It is set up as follows for the various runtime/ABI combinations:
+	 ** Linux 64 bit: Set XKPHYS bit
+	 ** Linux 32 bit: use mmap to create mapping, use virtual address
+	 ** CVMX 64 bit:  use physical address directly
+	 ** CVMX 32 bit:  use physical address directly
+	 ** Note that the CVMX environment assumes the use of 1-1 TLB mappings so that the physical addresses
+	 ** can be used directly
+	 */
+	if (!cvmx_bootmem_desc) {
+#if   defined(CVMX_ABI_64)
+		/* Set XKPHYS bit */
+		cvmx_bootmem_desc = cvmx_phys_to_ptr(CAST64(mem_desc_ptr));
+#else
+		cvmx_bootmem_desc = (cvmx_bootmem_desc_t *) mem_desc_ptr;
+#endif
+	}
+
+	return 0;
+}
+
+uint64_t cvmx_bootmem_available_mem(uint64_t min_block_size)
+{
+	return cvmx_bootmem_phy_available_mem(min_block_size);
+}
+
+/*********************************************************************
+** The cvmx_bootmem_phy* functions below return 64 bit physical addresses,
+** and expose more features that the cvmx_bootmem_functions above.  These are
+** required for full memory space access in 32 bit applications, as well as for
+** using some advance features.
+** Most applications should not need to use these.
+**
+**/
+
+int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
+			       uint64_t address_max, uint64_t alignment,
+			       uint32_t flags)
+{
+
+	uint64_t head_addr;
+	uint64_t ent_addr;
+	uint64_t prev_addr = 0;	/* points to previous list entry, NULL current entry is head of list */
+	uint64_t new_ent_addr = 0;
+	uint64_t desired_min_addr;
+	uint64_t alignment_mask = ~(alignment - 1);
+
+#ifdef DEBUG
+	cvmx_dprintf
+	    ("cvmx_bootmem_phy_alloc: req_size: 0x%llx, min_addr: 0x%llx, max_addr: 0x%llx, align: 0x%llx\n",
+	     (unsigned long long)req_size, (unsigned long long)address_min,
+	     (unsigned long long)address_max, (unsigned long long)alignment);
+#endif
+
+	if (cvmx_bootmem_desc->major_version > 3) {
+		cvmx_dprintf
+		    ("ERROR: Incompatible bootmem descriptor version: %d.%d at addr: %p\n",
+		     (int)cvmx_bootmem_desc->major_version,
+		     (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
+		goto error_out;
+	}
+
+	/* Do a variety of checks to validate the arguments.  The
+	 * allocator code will later assume that these checks have
+	 * been made.  We validate that the requested constraints are
+	 * not self-contradictory before we look through the list of
+	 * available memory
+	 */
+
+	/* 0 is not a valid req_size for this allocator */
+	if (!req_size)
+		goto error_out;
+
+	/* Round req_size up to mult of minimum alignment bytes */
+	req_size =
+	    (req_size +
+	     (CVMX_BOOTMEM_ALIGNMENT_SIZE -
+	      1)) & ~(CVMX_BOOTMEM_ALIGNMENT_SIZE - 1);
+
+	/* Convert !0 address_min and 0 address_max to special case of
+	 * range that specifies an exact memory block to allocate.
+	 * Do this before other checks and adjustments so that this
+	 * tranformation will be validated */
+	if (address_min && !address_max)
+		address_max = address_min + req_size;
+	else if (!address_min && !address_max)
+		address_max = ~0ull;	/* If no limits given, use max limits */
+
+
+	/* Enforce minimum alignment (this also keeps the minimum free block
+	 ** req_size the same as the alignment req_size */
+	if (alignment < CVMX_BOOTMEM_ALIGNMENT_SIZE) {
+		alignment = CVMX_BOOTMEM_ALIGNMENT_SIZE;
+	}
+	alignment_mask = ~(alignment - 1);
+
+	/* Adjust address minimum based on requested alignment (round
+	 * up to meet alignment).  Do this here so we can reject
+	 * impossible requests up front. (NOP for address_min ==
+	 * 0) */
+	if (alignment)
+		address_min =
+		    (address_min + (alignment - 1)) & ~(alignment - 1);
+
+	/* Reject inconsistent args.  We have adjusted these, so this
+	 * may fail due to our internal changes even if this check
+	 * would pass for the values the user supplied. */
+	if (req_size > address_max - address_min)
+		goto error_out;
+
+	/* Walk through the list entries - first fit found is returned */
+
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_lock((cvmx_spinlock_t *) &
+				   (cvmx_bootmem_desc->lock));
+	head_addr = cvmx_bootmem_desc->head_addr;
+	ent_addr = head_addr;
+	while (ent_addr) {
+		uint64_t usable_base, usable_max;
+		uint64_t ent_size = cvmx_bootmem_phy_get_size(ent_addr);
+
+		if (cvmx_bootmem_phy_get_next(ent_addr)
+		    && ent_addr > cvmx_bootmem_phy_get_next(ent_addr)) {
+			cvmx_dprintf
+			    ("Internal bootmem_alloc() error: ent: 0x%llx, next: 0x%llx\n",
+			     (unsigned long long)ent_addr, (unsigned long long)
+			     cvmx_bootmem_phy_get_next(ent_addr));
+			goto error_out;
+		}
+
+		/* Determine if this is an entry that can satisify the request */
+		/* Check to make sure entry is large enough to satisfy request */
+		usable_base =
+		    ALIGN_ADDR_UP(MAX(address_min, ent_addr), alignment_mask);
+		usable_max = MIN(address_max, ent_addr + ent_size);
+		/* We should be able to allocate block at address usable_base */
+
+		desired_min_addr = usable_base;
+
+		/* Determine if request can be satisfied from the current entry */
+		if ((((ent_addr + ent_size) > usable_base
+		      && ent_addr < address_max))
+		    && req_size <= usable_max - usable_base) {
+			/* We have found an entry that has room to satisfy the request, so allocate it from this entry */
+
+			/* If end CVMX_BOOTMEM_FLAG_END_ALLOC set, then allocate from the end of this block
+			 ** rather than the beginning */
+			if (flags & CVMX_BOOTMEM_FLAG_END_ALLOC) {
+				desired_min_addr = usable_max - req_size;
+				/* Align desired address down to required alignment */
+				desired_min_addr &= alignment_mask;
+			}
+
+			/* Match at start of entry */
+			if (desired_min_addr == ent_addr) {
+				if (req_size < ent_size) {
+					/* big enough to create a new block from top portion of block */
+					new_ent_addr = ent_addr + req_size;
+					cvmx_bootmem_phy_set_next(new_ent_addr,
+								  cvmx_bootmem_phy_get_next
+								  (ent_addr));
+					cvmx_bootmem_phy_set_size(new_ent_addr,
+								  ent_size -
+								  req_size);
+
+					/* Adjust next pointer as following code uses this */
+					cvmx_bootmem_phy_set_next(ent_addr,
+								  new_ent_addr);
+				}
+
+				/* adjust prev ptr or head to remove this entry from list */
+				if (prev_addr) {
+					cvmx_bootmem_phy_set_next(prev_addr,
+								  cvmx_bootmem_phy_get_next
+								  (ent_addr));
+				} else {
+					/* head of list being returned, so update head ptr */
+					cvmx_bootmem_desc->head_addr =
+					    cvmx_bootmem_phy_get_next(ent_addr);
+				}
+				if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+					cvmx_spinlock_unlock((cvmx_spinlock_t *)
+							     &
+							     (cvmx_bootmem_desc->lock));
+				return desired_min_addr;
+			}
+
+			/* block returned doesn't start at beginning
+			 * of entry, so we know that we will be
+			 * splitting a block off the front of this
+			 * one.  Create a new block from the
+			 * beginning, add to list, and go to top of
+			 * loop again.
+			 *
+			 * create new block from high portion of
+			 * block, so that top block starts at desired
+			 * addr
+			 **/
+			new_ent_addr = desired_min_addr;
+			cvmx_bootmem_phy_set_next(new_ent_addr,
+						  cvmx_bootmem_phy_get_next
+						  (ent_addr));
+			cvmx_bootmem_phy_set_size(new_ent_addr,
+						  cvmx_bootmem_phy_get_size
+						  (ent_addr) -
+						  (desired_min_addr -
+						   ent_addr));
+			cvmx_bootmem_phy_set_size(ent_addr,
+						  desired_min_addr - ent_addr);
+			cvmx_bootmem_phy_set_next(ent_addr, new_ent_addr);
+			/* Loop again to handle actual alloc from new block */
+		}
+
+		prev_addr = ent_addr;
+		ent_addr = cvmx_bootmem_phy_get_next(ent_addr);
+	}
+error_out:
+	/* We didn't find anything, so return error */
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_unlock((cvmx_spinlock_t *) &
+				     (cvmx_bootmem_desc->lock));
+	return -1;
+}
+
+int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags)
+{
+	uint64_t cur_addr;
+	uint64_t prev_addr = 0;	/* zero is invalid */
+	int retval = 0;
+
+#ifdef DEBUG
+	cvmx_dprintf("__cvmx_bootmem_phy_free addr: 0x%llx, size: 0x%llx\n",
+		     (unsigned long long)phy_addr, (unsigned long long)size);
+#endif
+	if (cvmx_bootmem_desc->major_version > 3) {
+		cvmx_dprintf
+		    ("ERROR: Incompatible bootmem descriptor version: %d.%d at addr: %p\n",
+		     (int)cvmx_bootmem_desc->major_version,
+		     (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
+		return 0;
+	}
+
+	/* 0 is not a valid size for this allocator */
+	if (!size)
+		return 0;
+
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_lock((cvmx_spinlock_t *) &
+				   (cvmx_bootmem_desc->lock));
+	cur_addr = cvmx_bootmem_desc->head_addr;
+	if (cur_addr == 0 || phy_addr < cur_addr) {
+		/* add at front of list - special case with changing head ptr */
+		if (cur_addr && phy_addr + size > cur_addr)
+			goto bootmem_free_done;	/* error, overlapping section */
+		else if (phy_addr + size == cur_addr) {
+			/* Add to front of existing first block */
+			cvmx_bootmem_phy_set_next(phy_addr,
+						  cvmx_bootmem_phy_get_next
+						  (cur_addr));
+			cvmx_bootmem_phy_set_size(phy_addr,
+						  cvmx_bootmem_phy_get_size
+						  (cur_addr) + size);
+			cvmx_bootmem_desc->head_addr = phy_addr;
+
+		} else {
+			/* New block before first block */
+			cvmx_bootmem_phy_set_next(phy_addr, cur_addr);	/* OK if cur_addr is 0 */
+			cvmx_bootmem_phy_set_size(phy_addr, size);
+			cvmx_bootmem_desc->head_addr = phy_addr;
+		}
+		retval = 1;
+		goto bootmem_free_done;
+	}
+
+	/* Find place in list to add block */
+	while (cur_addr && phy_addr > cur_addr) {
+		prev_addr = cur_addr;
+		cur_addr = cvmx_bootmem_phy_get_next(cur_addr);
+	}
+
+	if (!cur_addr) {
+		/* We have reached the end of the list, add on to end, checking
+		 ** to see if we need to combine with last block
+		 **/
+		if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) ==
+		    phy_addr) {
+			cvmx_bootmem_phy_set_size(prev_addr,
+						  cvmx_bootmem_phy_get_size
+						  (prev_addr) + size);
+		} else {
+			cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
+			cvmx_bootmem_phy_set_size(phy_addr, size);
+			cvmx_bootmem_phy_set_next(phy_addr, 0);
+		}
+		retval = 1;
+		goto bootmem_free_done;
+	} else {
+		/* insert between prev and cur nodes, checking for merge with either/both */
+
+		if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) ==
+		    phy_addr) {
+			/* Merge with previous */
+			cvmx_bootmem_phy_set_size(prev_addr,
+						  cvmx_bootmem_phy_get_size
+						  (prev_addr) + size);
+			if (phy_addr + size == cur_addr) {
+				/* Also merge with current */
+				cvmx_bootmem_phy_set_size(prev_addr,
+							  cvmx_bootmem_phy_get_size
+							  (cur_addr) +
+							  cvmx_bootmem_phy_get_size
+							  (prev_addr));
+				cvmx_bootmem_phy_set_next(prev_addr,
+							  cvmx_bootmem_phy_get_next
+							  (cur_addr));
+			}
+			retval = 1;
+			goto bootmem_free_done;
+		} else if (phy_addr + size == cur_addr) {
+			/* Merge with current */
+			cvmx_bootmem_phy_set_size(phy_addr,
+						  cvmx_bootmem_phy_get_size
+						  (cur_addr) + size);
+			cvmx_bootmem_phy_set_next(phy_addr,
+						  cvmx_bootmem_phy_get_next
+						  (cur_addr));
+			cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
+			retval = 1;
+			goto bootmem_free_done;
+		}
+
+		/* It is a standalone block, add in between prev and cur */
+		cvmx_bootmem_phy_set_size(phy_addr, size);
+		cvmx_bootmem_phy_set_next(phy_addr, cur_addr);
+		cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
+
+	}
+	retval = 1;
+
+bootmem_free_done:
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_unlock((cvmx_spinlock_t *) &
+				     (cvmx_bootmem_desc->lock));
+	return retval;
+
+}
+
+void cvmx_bootmem_phy_list_print(void)
+{
+	uint64_t addr;
+
+	addr = cvmx_bootmem_desc->head_addr;
+	cvmx_dprintf
+	    ("\n\n\nPrinting bootmem block list, descriptor: %p,  head is 0x%llx\n",
+	     cvmx_bootmem_desc, (unsigned long long)addr);
+	cvmx_dprintf("Descriptor version: %d.%d\n",
+		     (int)cvmx_bootmem_desc->major_version,
+		     (int)cvmx_bootmem_desc->minor_version);
+	if (cvmx_bootmem_desc->major_version > 3) {
+		cvmx_dprintf
+		    ("Warning: Bootmem descriptor version is newer than expected\n");
+	}
+	if (!addr) {
+		cvmx_dprintf("mem list is empty!\n");
+	}
+	while (addr) {
+		cvmx_dprintf
+		    ("Block address: 0x%08qx, size: 0x%08qx, next: 0x%08qx\n",
+		     (unsigned long long)addr,
+		     (unsigned long long)cvmx_bootmem_phy_get_size(addr),
+		     (unsigned long long)cvmx_bootmem_phy_get_next(addr));
+		addr = cvmx_bootmem_phy_get_next(addr);
+	}
+	cvmx_dprintf("\n\n");
+
+}
+
+uint64_t cvmx_bootmem_phy_available_mem(uint64_t min_block_size)
+{
+	uint64_t addr;
+
+	uint64_t available_mem = 0;
+
+	cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+	addr = cvmx_bootmem_desc->head_addr;
+	while (addr) {
+		if (cvmx_bootmem_phy_get_size(addr) >= min_block_size)
+			available_mem += cvmx_bootmem_phy_get_size(addr);
+		addr = cvmx_bootmem_phy_get_next(addr);
+	}
+	cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+	return available_mem;
+
+}
+
+cvmx_bootmem_named_block_desc_t *cvmx_bootmem_phy_named_block_find(char *name,
+								   uint32_t
+								   flags)
+{
+	unsigned int i;
+	cvmx_bootmem_named_block_desc_t *named_block_array_ptr;
+
+#ifdef DEBUG
+	cvmx_dprintf("cvmx_bootmem_phy_named_block_find: %s\n", name);
+#endif
+	/* Lock the structure to make sure that it is not being
+	 * changed while we are examining it.
+	 */
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_lock((cvmx_spinlock_t *) &
+				   (cvmx_bootmem_desc->lock));
+
+#if !defined(CONFIG_OCTEON_U_BOOT)
+	/* Use XKPHYS for 64 bit linux */
+	named_block_array_ptr = (cvmx_bootmem_named_block_desc_t *)
+	    cvmx_phys_to_ptr(cvmx_bootmem_desc->named_block_array_addr);
+#else
+	/* Simple executive case. (and u-boot) This could be in the
+	 * low 1 meg of memory that is not 1-1 mapped, so we need use
+	 * XKPHYS/KSEG0 addressing for it */
+	named_block_array_ptr =
+	    CASTPTR(cvmx_bootmem_named_block_desc_t,
+		    CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0,
+				   cvmx_bootmem_desc->named_block_array_addr));
+#endif
+
+#ifdef DEBUG
+	cvmx_dprintf
+	    ("cvmx_bootmem_phy_named_block_find: named_block_array_ptr: %p\n",
+	     named_block_array_ptr);
+#endif
+	if (cvmx_bootmem_desc->major_version == 3) {
+		for (i = 0; i < cvmx_bootmem_desc->named_block_num_blocks; i++) {
+			if ((name && named_block_array_ptr[i].size
+			     && !strncmp(name, named_block_array_ptr[i].name,
+					 cvmx_bootmem_desc->named_block_name_len
+					 - 1))
+			    || (!name && !named_block_array_ptr[i].size)) {
+				if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+					cvmx_spinlock_unlock((cvmx_spinlock_t *)
+							     &
+							     (cvmx_bootmem_desc->lock));
+
+				return &(named_block_array_ptr[i]);
+			}
+		}
+	} else {
+		cvmx_dprintf
+		    ("ERROR: Incompatible bootmem descriptor version: %d.%d at addr: %p\n",
+		     (int)cvmx_bootmem_desc->major_version,
+		     (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
+	}
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_unlock((cvmx_spinlock_t *) &
+				     (cvmx_bootmem_desc->lock));
+
+	return NULL;
+}
+
+int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags)
+{
+	cvmx_bootmem_named_block_desc_t *named_block_ptr;
+
+	if (cvmx_bootmem_desc->major_version != 3) {
+		cvmx_dprintf
+		    ("ERROR: Incompatible bootmem descriptor version: %d.%d at addr: %p\n",
+		     (int)cvmx_bootmem_desc->major_version,
+		     (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
+		return 0;
+	}
+#ifdef DEBUG
+	cvmx_dprintf("cvmx_bootmem_phy_named_block_free: %s\n", name);
+#endif
+
+	/* Take lock here, as name lookup/block free/name free need to be atomic */
+	cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+
+	named_block_ptr =
+	    cvmx_bootmem_phy_named_block_find(name,
+					      CVMX_BOOTMEM_FLAG_NO_LOCKING);
+	if (named_block_ptr) {
+#ifdef DEBUG
+		cvmx_dprintf
+		    ("cvmx_bootmem_phy_named_block_free: %s, base: 0x%llx, size: 0x%llx\n",
+		     name, (unsigned long long)named_block_ptr->base_addr,
+		     (unsigned long long)named_block_ptr->size);
+#endif
+		__cvmx_bootmem_phy_free(named_block_ptr->base_addr,
+					named_block_ptr->size,
+					CVMX_BOOTMEM_FLAG_NO_LOCKING);
+		named_block_ptr->size = 0;
+		/* Set size to zero to indicate block not used. */
+	}
+
+	cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+
+	return named_block_ptr != NULL;	/* 0 on failure, 1 on success */
+}
+
+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
+					   uint64_t max_addr,
+					   uint64_t alignment, char *name,
+					   uint32_t flags)
+{
+	int64_t addr_allocated;
+	cvmx_bootmem_named_block_desc_t *named_block_desc_ptr;
+
+#ifdef DEBUG
+	cvmx_dprintf
+	    ("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: 0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n",
+	     (unsigned long long)size, (unsigned long long)min_addr,
+	     (unsigned long long)max_addr, (unsigned long long)alignment, name);
+#endif
+	if (cvmx_bootmem_desc->major_version != 3) {
+		cvmx_dprintf
+		    ("ERROR: Incompatible bootmem descriptor version: %d.%d at addr: %p\n",
+		     (int)cvmx_bootmem_desc->major_version,
+		     (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
+		return -1;
+	}
+
+	/* Take lock here, as name lookup/block alloc/name add need to be atomic */
+
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_lock((cvmx_spinlock_t *) &
+				   (cvmx_bootmem_desc->lock));
+
+	/* Get pointer to first available named block descriptor */
+	named_block_desc_ptr =
+	    cvmx_bootmem_phy_named_block_find(NULL,
+					      flags |
+					      CVMX_BOOTMEM_FLAG_NO_LOCKING);
+
+	/* Check to see if name already in use, return error if name
+	 ** not available or no more room for blocks.
+	 */
+	if (cvmx_bootmem_phy_named_block_find
+	    (name, flags | CVMX_BOOTMEM_FLAG_NO_LOCKING)
+	    || !named_block_desc_ptr) {
+		if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+			cvmx_spinlock_unlock((cvmx_spinlock_t *) &
+					     (cvmx_bootmem_desc->lock));
+		return -1;
+	}
+
+	/* Round size up to mult of minimum alignment bytes
+	 ** We need the actual size allocated to allow for blocks to be coallesced
+	 ** when they are freed.  The alloc routine does the same rounding up
+	 ** on all allocations. */
+	size =
+	    (size +
+	     (CVMX_BOOTMEM_ALIGNMENT_SIZE -
+	      1)) & ~(CVMX_BOOTMEM_ALIGNMENT_SIZE - 1);
+
+	addr_allocated =
+	    cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment,
+				   flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
+	if (addr_allocated >= 0) {
+		named_block_desc_ptr->base_addr = addr_allocated;
+		named_block_desc_ptr->size = size;
+		strncpy(named_block_desc_ptr->name, name,
+			cvmx_bootmem_desc->named_block_name_len);
+		named_block_desc_ptr->
+		    name[cvmx_bootmem_desc->named_block_name_len - 1] = 0;
+	}
+
+	if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+		cvmx_spinlock_unlock((cvmx_spinlock_t *) &
+				     (cvmx_bootmem_desc->lock));
+
+	return addr_allocated;
+}
+
+void cvmx_bootmem_phy_named_block_print(void)
+{
+	unsigned int i;
+	int printed = 0;
+
+#if !defined(CONFIG_OCTEON_U_BOOT)
+	/* Use XKPHYS for 64 bit linux */
+	cvmx_bootmem_named_block_desc_t *named_block_array_ptr =
+	    (cvmx_bootmem_named_block_desc_t *)
+	    cvmx_phys_to_ptr(cvmx_bootmem_desc->named_block_array_addr);
+#else
+	/* Simple executive case. (and u-boot)
+	 ** This could be in the low 1 meg of memory that is not 1-1 mapped, so we need use XKPHYS/KSEG0 addressing for it */
+	cvmx_bootmem_named_block_desc_t *named_block_array_ptr =
+	    CASTPTR(cvmx_bootmem_named_block_desc_t,
+		    CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0,
+				   cvmx_bootmem_desc->named_block_array_addr));
+#endif
+#ifdef DEBUG
+	cvmx_dprintf("cvmx_bootmem_phy_named_block_print, desc addr: %p\n",
+		     cvmx_bootmem_desc);
+#endif
+	if (cvmx_bootmem_desc->major_version != 3) {
+		cvmx_dprintf
+		    ("ERROR: Incompatible bootmem descriptor version: %d.%d at addr: %p\n",
+		     (int)cvmx_bootmem_desc->major_version,
+		     (int)cvmx_bootmem_desc->minor_version, cvmx_bootmem_desc);
+		return;
+	}
+	cvmx_dprintf("List of currently allocated named bootmem blocks:\n");
+	for (i = 0; i < cvmx_bootmem_desc->named_block_num_blocks; i++) {
+		if (named_block_array_ptr[i].size) {
+			printed++;
+			cvmx_dprintf
+			    ("Name: %s, address: 0x%08qx, size: 0x%08qx, index: %d\n",
+			     named_block_array_ptr[i].name,
+			     (unsigned long long)
+			     named_block_array_ptr[i].base_addr,
+			     (unsigned long long)named_block_array_ptr[i].size,
+			     i);
+
+		}
+	}
+	if (!printed) {
+		cvmx_dprintf("No named bootmem blocks exist.\n");
+	}
+
+}
+
+/* Real physical addresses of memory regions */
+#define OCTEON_DDR0_BASE    (0x0ULL)
+#define OCTEON_DDR0_SIZE    (0x010000000ULL)
+#define OCTEON_DDR1_BASE    (0x410000000ULL)
+#define OCTEON_DDR1_SIZE    (0x010000000ULL)
+#define OCTEON_DDR2_BASE    (0x020000000ULL)
+#define OCTEON_DDR2_SIZE    (0x3e0000000ULL)
+#define OCTEON_MAX_PHY_MEM_SIZE (16*1024*1024*1024ULL)
+int64_t cvmx_bootmem_phy_mem_list_init(uint64_t mem_size,
+				       uint32_t low_reserved_bytes,
+				       cvmx_bootmem_desc_t *desc_buffer)
+{
+	uint64_t cur_block_addr;
+	int64_t addr;
+
+#ifdef DEBUG
+	cvmx_dprintf
+	    ("cvmx_bootmem_phy_mem_list_init (arg desc ptr: %p, cvmx_bootmem_desc: %p)\n",
+	     desc_buffer, cvmx_bootmem_desc);
+#endif
+
+	/* Descriptor buffer needs to be in 32 bit addressable space to be compatible with
+	 ** 32 bit applications */
+	if (!desc_buffer) {
+		cvmx_dprintf
+		    ("ERROR: no memory for cvmx_bootmem descriptor provided\n");
+		return 0;
+	}
+
+	if (mem_size > OCTEON_MAX_PHY_MEM_SIZE) {
+		mem_size = OCTEON_MAX_PHY_MEM_SIZE;
+		cvmx_dprintf
+		    ("ERROR: requested memory size too large, truncating to maximum size\n");
+	}
+
+	if (cvmx_bootmem_desc)
+		return 1;
+
+	/* Initialize cvmx pointer to descriptor */
+	cvmx_bootmem_init(desc_buffer);
+
+	/* Set up global pointer to start of list, exclude low 64k for exception vectors, space for global descriptor */
+	memset(cvmx_bootmem_desc, 0x0, sizeof(cvmx_bootmem_desc_t));
+	/* Set version of bootmem descriptor */
+	cvmx_bootmem_desc->major_version = CVMX_BOOTMEM_DESC_MAJ_VER;
+	cvmx_bootmem_desc->minor_version = CVMX_BOOTMEM_DESC_MIN_VER;
+
+	cur_block_addr = cvmx_bootmem_desc->head_addr =
+	    (OCTEON_DDR0_BASE + low_reserved_bytes);
+
+	cvmx_bootmem_desc->head_addr = 0;
+
+	if (mem_size <= OCTEON_DDR0_SIZE) {
+		__cvmx_bootmem_phy_free(cur_block_addr,
+					mem_size - low_reserved_bytes, 0);
+		goto frees_done;
+	}
+
+	__cvmx_bootmem_phy_free(cur_block_addr,
+				OCTEON_DDR0_SIZE - low_reserved_bytes, 0);
+
+	mem_size -= OCTEON_DDR0_SIZE;
+
+	/* Add DDR2 block next if present */
+	if (mem_size > OCTEON_DDR1_SIZE) {
+		__cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, OCTEON_DDR1_SIZE, 0);
+		__cvmx_bootmem_phy_free(OCTEON_DDR2_BASE,
+					mem_size - OCTEON_DDR1_SIZE, 0);
+	} else {
+		__cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, mem_size, 0);
+
+	}
+frees_done:
+
+	/* Initialize the named block structure */
+	cvmx_bootmem_desc->named_block_name_len = CVMX_BOOTMEM_NAME_LEN;
+	cvmx_bootmem_desc->named_block_num_blocks =
+	    CVMX_BOOTMEM_NUM_NAMED_BLOCKS;
+	cvmx_bootmem_desc->named_block_array_addr = 0;
+
+	/* Allocate this near the top of the low 256 MBytes of memory */
+	addr =
+	    cvmx_bootmem_phy_alloc(CVMX_BOOTMEM_NUM_NAMED_BLOCKS *
+				   sizeof(cvmx_bootmem_named_block_desc_t), 0,
+				   0x10000000, 0, CVMX_BOOTMEM_FLAG_END_ALLOC);
+	if (addr >= 0)
+		cvmx_bootmem_desc->named_block_array_addr = addr;
+
+#ifdef DEBUG
+	cvmx_dprintf
+	    ("cvmx_bootmem_phy_mem_list_init: named_block_array_addr: 0x%llx)\n",
+	     (unsigned long long)cvmx_bootmem_desc->named_block_array_addr);
+#endif
+	if (!cvmx_bootmem_desc->named_block_array_addr) {
+		cvmx_dprintf
+		    ("FATAL ERROR: unable to allocate memory for bootmem descriptor!\n");
+		return 0;
+	}
+	memset((void *)(unsigned long)cvmx_bootmem_desc->named_block_array_addr,
+	       0x0,
+	       CVMX_BOOTMEM_NUM_NAMED_BLOCKS *
+	       sizeof(cvmx_bootmem_named_block_desc_t));
+
+	return 1;
+}
+
+void cvmx_bootmem_lock(void)
+{
+	cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+}
+
+void cvmx_bootmem_unlock(void)
+{
+	cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+}
+
+void *__cvmx_bootmem_internal_get_desc_ptr(void)
+{
+	return cvmx_bootmem_desc;
+}
arch/mips/cavium-octeon/executive/cvmx-bootmem.h new file +403 -0
new file mode 100644
index 0000000..71cf611
@@ -0,0 +1,403 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ * Simple allocate only memory allocator.  Used to allocate memory at application
+ * start time.
+ *
+ *
+ */
+
+#ifndef __CVMX_BOOTMEM_H__
+#define __CVMX_BOOTMEM_H__
+
+#define CVMX_BOOTMEM_NAME_LEN 128	/* Must be multiple of 8, changing breaks ABI */
+#define CVMX_BOOTMEM_NUM_NAMED_BLOCKS 64	/* Can change without breaking ABI */
+#define CVMX_BOOTMEM_ALIGNMENT_SIZE     (16ull)	/* minimum alignment of bootmem alloced blocks */
+
+/* Flags for cvmx_bootmem_phy_mem* functions */
+#define CVMX_BOOTMEM_FLAG_END_ALLOC    (1 << 0)	/* Allocate from end of block instead of beginning */
+#define CVMX_BOOTMEM_FLAG_NO_LOCKING   (1 << 1)	/* Don't do any locking. */
+
+/* First bytes of each free physical block of memory contain this structure,
+ * which is used to maintain the free memory list.  Since the bootloader is
+ * only 32 bits, there is a union providing 64 and 32 bit versions.  The
+ * application init code converts addresses to 64 bit addresses before the
+ * application starts.
+ */
+typedef struct {
+	/* Note: these are referenced from assembly routines in the bootloader, so this structure
+	 ** should not be changed without changing those routines as well. */
+	uint64_t next_block_addr;
+	uint64_t size;
+
+} cvmx_bootmem_block_header_t;
+
+/* Structure for named memory blocks
+** Number of descriptors
+** available can be changed without affecting compatiblity,
+** but name length changes require a bump in the bootmem
+** descriptor version
+** Note: This structure must be naturally 64 bit aligned, as a single
+** memory image will be used by both 32 and 64 bit programs.
+*/
+typedef struct {
+	uint64_t base_addr;
+			    /**< Base address of named block */
+	uint64_t size;
+			    /**< Size actually allocated for named block (may differ from requested) */
+	char name[CVMX_BOOTMEM_NAME_LEN];
+					/**< name of named block */
+} cvmx_bootmem_named_block_desc_t;
+
+/* Current descriptor versions */
+#define CVMX_BOOTMEM_DESC_MAJ_VER   3	/* CVMX bootmem descriptor major version */
+#define CVMX_BOOTMEM_DESC_MIN_VER   0	/* CVMX bootmem descriptor minor version */
+
+/* First three members of cvmx_bootmem_desc_t are left in original
+** positions for backwards compatibility.
+*/
+typedef struct {
+	uint32_t lock;
+			    /**< spinlock to control access to list */
+	uint32_t flags;
+			    /**< flags for indicating various conditions */
+	uint64_t head_addr;
+
+	uint32_t major_version;
+				/**< incremented changed when incompatible changes made */
+	uint32_t minor_version;
+				/**< incremented changed when compatible changes made, reset to zero when major incremented */
+	uint64_t app_data_addr;
+	uint64_t app_data_size;
+
+	uint32_t named_block_num_blocks;
+					 /**< number of elements in named blocks array */
+	uint32_t named_block_name_len;
+					 /**< length of name array in bootmem blocks */
+	uint64_t named_block_array_addr;
+					 /**< address of named memory block descriptors */
+
+} cvmx_bootmem_desc_t;
+
+/**
+ * Initialize the boot alloc memory structures. This is
+ * normally called inside of cvmx_user_app_init()
+ *
+ * @param mem_desc_ptr	Address of the free memory list
+ * @return
+ */
+extern int cvmx_bootmem_init(void *mem_desc_ptr);
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader.
+ * This is an allocate-only algorithm, so freeing memory is not possible.
+ *
+ * @param size      Size in bytes of block to allocate
+ * @param alignment Alignment required - must be power of 2
+ *
+ * @return pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment);
+
+/**
+ * Allocate a block of memory from the free list that was
+ * passed to the application by the bootloader at a specific
+ * address. This is an allocate-only algorithm, so
+ * freeing memory is not possible. Allocation will fail if
+ * memory cannot be allocated at the specified address.
+ *
+ * @param size      Size in bytes of block to allocate
+ * @param address   Physical address to allocate memory at.  If this memory is not
+ *                  available, the allocation fails.
+ * @param alignment Alignment required - must be power of 2
+ * @return pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address,
+					uint64_t alignment);
+
+/**
+ * Allocate a block of memory from the free list that was
+ * passed to the application by the bootloader within a specified
+ * address range. This is an allocate-only algorithm, so
+ * freeing memory is not possible. Allocation will fail if
+ * memory cannot be allocated in the requested range.
+ *
+ * @param size      Size in bytes of block to allocate
+ * @param min_addr  defines the minimum address of the range
+ * @param max_addr  defines the maximum address of the range
+ * @param alignment Alignment required - must be power of 2
+ * @return pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
+				      uint64_t min_addr, uint64_t max_addr);
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader, and assign it a name in the
+ * global named block table.  (part of the cvmx_bootmem_descriptor_t structure)
+ * Named blocks can later be freed.
+ *
+ * @param size      Size in bytes of block to allocate
+ * @param alignment Alignment required - must be power of 2
+ * @param name      name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ *
+ * @return pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment,
+				      char *name);
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader, and assign it a name in the
+ * global named block table.  (part of the cvmx_bootmem_descriptor_t structure)
+ * Named blocks can later be freed.
+ *
+ * @param size      Size in bytes of block to allocate
+ * @param address   Physical address to allocate memory at.  If this memory is not
+ *                  available, the allocation fails.
+ * @param name      name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ *
+ * @return pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named_address(uint64_t size,
+					      uint64_t address, char *name);
+
+/**
+ * Allocate a block of memory from a specific range of the free list that was passed
+ * to the application by the bootloader, and assign it a name in the
+ * global named block table.  (part of the cvmx_bootmem_descriptor_t structure)
+ * Named blocks can later be freed.
+ * If request cannot be satisfied within the address range specified, NULL is returned
+ *
+ * @param size      Size in bytes of block to allocate
+ * @param min_addr  minimum address of range
+ * @param max_addr  maximum address of range
+ * @param align  Alignment of memory to be allocated. (must be a power of 2)
+ * @param name      name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ *
+ * @return pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named_range(uint64_t size,
+					    uint64_t min_addr,
+					    uint64_t max_addr,
+					    uint64_t align, char *name);
+
+/**
+ * Frees a previously allocated named bootmem block.
+ *
+ * @param name   name of block to free
+ *
+ * @return 0 on failure,
+ *         !0 on success
+ */
+extern int cvmx_bootmem_free_named(char *name);
+
+/**
+ * Finds a named bootmem block by name.
+ *
+ * @param name   name of block to free
+ *
+ * @return pointer to named block descriptor on success
+ *         0 on failure
+ */
+cvmx_bootmem_named_block_desc_t *cvmx_bootmem_find_named_block(char
+							       *name);
+
+/**
+ * Returns the size of available memory in bytes, only
+ * counting blocks that are at least as big as the minimum block
+ * size.
+ *
+ * @param min_block_size
+ *               Minimum block size to count in total.
+ *
+ * @return Number of bytes available for allocation that meet the block size requirement
+ */
+uint64_t cvmx_bootmem_available_mem(uint64_t min_block_size);
+
+/**
+ * Prints out the list of named blocks that have been allocated
+ * along with their addresses and sizes.
+ * This is primarily used for debugging purposes
+ */
+void cvmx_bootmem_print_named(void);
+
+/**
+ * Allocates a block of physical memory from the free list, at (optional) requested address and alignment.
+ *
+ * @param req_size  size of region to allocate.  All requests are rounded up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE bytes size
+ * @param address_min
+ *                  Minimum address that block can occupy.
+ * @param address_max
+ *                  Specifies the maximum address_min (inclusive) that the allocation can use.
+ * @param alignment Requested alignment of the block.  If this alignment cannot be met, the allocation fails.
+ *                  This must be a power of 2.
+ *                  (Note: Alignment of CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and internally enforced.  Requested alignments of
+ *                  less than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to CVMX_BOOTMEM_ALIGNMENT_SIZE.)
+ * @param flags     Flags to control options for the allocation.
+ *
+ * @return physical address of block allocated, or -1 on failure
+ */
+int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
+			       uint64_t address_max, uint64_t alignment,
+			       uint32_t flags);
+
+/**
+ * Allocates a named block of physical memory from the free list, at (optional) requested address and alignment.
+ *
+ * @param size      size of region to allocate.  All requests are rounded up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE bytes size
+ * @param min_addr
+ *                  Minimum address that block can occupy.
+ * @param max_addr
+ *                  Specifies the maximum address_min (inclusive) that the allocation can use.
+ * @param alignment Requested alignment of the block.  If this alignment cannot be met, the allocation fails.
+ *                  This must be a power of 2.
+ *                  (Note: Alignment of CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and internally enforced.  Requested alignments of
+ *                  less than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to CVMX_BOOTMEM_ALIGNMENT_SIZE.)
+ * @param name      name to assign to named block
+ * @param flags     Flags to control options for the allocation.
+ *
+ * @return physical address of block allocated, or -1 on failure
+ */
+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size,
+					   uint64_t min_addr,
+					   uint64_t max_addr,
+					   uint64_t alignment,
+					   char *name, uint32_t flags);
+
+/**
+ * Finds a named memory block by name.
+ * Also used for finding an unused entry in the named block table.
+ *
+ * @param name   Name of memory block to find.
+ *               If NULL pointer given, then finds unused descriptor, if available.
+ * @param flags     Flags to control options for the allocation.
+ *
+ * @return Pointer to memory block descriptor, NULL if not found.
+ *         If NULL returned when name parameter is NULL, then no memory
+ *         block descriptors are available.
+ */
+cvmx_bootmem_named_block_desc_t *cvmx_bootmem_phy_named_block_find(char
+								   *name,
+								   uint32_t
+								   flags);
+
+/**
+ * Returns the size of available memory in bytes, only
+ * counting blocks that are at least as big as the minimum block
+ * size.
+ *
+ * @param min_block_size
+ *               Minimum block size to count in total.
+ *
+ * @return Number of bytes available for allocation that meet the block size requirement
+ */
+uint64_t cvmx_bootmem_phy_available_mem(uint64_t min_block_size);
+
+/**
+ * Frees a named block.
+ *
+ * @param name   name of block to free
+ * @param flags  flags for passing options
+ *
+ * @return 0 on failure
+ *         1 on success
+ */
+int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags);
+
+/**
+ * Frees a block to the bootmem allocator list.  This must
+ * be used with care, as the size provided must match the size
+ * of the block that was allocated, or the list will become
+ * corrupted.
+ *
+ * IMPORTANT:  This is only intended to be used as part of named block
+ * frees and initial population of the free memory list.
+ *                                                      *
+ *
+ * @param phy_addr physical address of block
+ * @param size     size of block in bytes.
+ * @param flags    flags for passing options
+ *
+ * @return 1 on success,
+ *         0 on failure
+ */
+int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags);
+
+/**
+ * Prints the list of currently allocated named blocks
+ *
+ */
+void cvmx_bootmem_phy_named_block_print(void);
+
+/**
+ * Prints the list of available memory.
+ *
+ */
+void cvmx_bootmem_phy_list_print(void);
+
+/**
+ * This function initializes the free memory list used by cvmx_bootmem.
+ * This must be called before any allocations can be done.
+ *
+ * @param mem_size Total memory available, in bytes
+ * @param low_reserved_bytes
+ *                 Number of bytes to reserve (leave out of free list) at address 0x0.
+ * @param desc_buffer
+ *                 Buffer for the bootmem descriptor.  This must be a 32 bit addressable
+ *                 address.
+ *
+ * @return 1 on success
+ *         0 on failure
+ */
+int64_t cvmx_bootmem_phy_mem_list_init(uint64_t mem_size,
+				       uint32_t low_reserved_bytes,
+				       cvmx_bootmem_desc_t *desc_buffer);
+
+/**
+ * Locks the bootmem allocator.  This is useful in certain situations
+ * where multiple allocations must be made without being interrupted.
+ * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag.
+ *
+ */
+void cvmx_bootmem_lock(void);
+
+/**
+ * Unlocks the bootmem allocator.  This is useful in certain situations
+ * where multiple allocations must be made without being interrupted.
+ * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag.
+ *
+ */
+void cvmx_bootmem_unlock(void);
+
+/**
+ * Internal use function to get the current descriptor pointer */
+void *__cvmx_bootmem_internal_get_desc_ptr(void);
+
+#endif /*   __CVMX_BOOTMEM_H__ */
arch/mips/cavium-octeon/executive/cvmx-interrupt.h new file +255 -0
new file mode 100644
index 0000000..8bddf25
@@ -0,0 +1,255 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ *
+ * Interface to the Mips interrupts.
+ *
+ */
+#ifndef __CVMX_INTERRUPT_H__
+#define __CVMX_INTERRUPT_H__
+
+/**
+ * Enumeration of Interrupt numbers
+ */
+typedef enum {
+	/* 0 - 7 represent the 8 MIPS standard interrupt sources */
+	CVMX_IRQ_SW0 = 0,
+	CVMX_IRQ_SW1 = 1,
+	CVMX_IRQ_CIU0 = 2,
+	CVMX_IRQ_CIU1 = 3,
+	CVMX_IRQ_4 = 4,
+	CVMX_IRQ_5 = 5,
+	CVMX_IRQ_6 = 6,
+	CVMX_IRQ_7 = 7,
+
+	/* 8 - 71 represent the sources in CIU_INTX_EN0 */
+	CVMX_IRQ_WORKQ0 = 8,
+	CVMX_IRQ_WORKQ1 = 9,
+	CVMX_IRQ_WORKQ2 = 10,
+	CVMX_IRQ_WORKQ3 = 11,
+	CVMX_IRQ_WORKQ4 = 12,
+	CVMX_IRQ_WORKQ5 = 13,
+	CVMX_IRQ_WORKQ6 = 14,
+	CVMX_IRQ_WORKQ7 = 15,
+	CVMX_IRQ_WORKQ8 = 16,
+	CVMX_IRQ_WORKQ9 = 17,
+	CVMX_IRQ_WORKQ10 = 18,
+	CVMX_IRQ_WORKQ11 = 19,
+	CVMX_IRQ_WORKQ12 = 20,
+	CVMX_IRQ_WORKQ13 = 21,
+	CVMX_IRQ_WORKQ14 = 22,
+	CVMX_IRQ_WORKQ15 = 23,
+	CVMX_IRQ_GPIO0 = 24,
+	CVMX_IRQ_GPIO1 = 25,
+	CVMX_IRQ_GPIO2 = 26,
+	CVMX_IRQ_GPIO3 = 27,
+	CVMX_IRQ_GPIO4 = 28,
+	CVMX_IRQ_GPIO5 = 29,
+	CVMX_IRQ_GPIO6 = 30,
+	CVMX_IRQ_GPIO7 = 31,
+	CVMX_IRQ_GPIO8 = 32,
+	CVMX_IRQ_GPIO9 = 33,
+	CVMX_IRQ_GPIO10 = 34,
+	CVMX_IRQ_GPIO11 = 35,
+	CVMX_IRQ_GPIO12 = 36,
+	CVMX_IRQ_GPIO13 = 37,
+	CVMX_IRQ_GPIO14 = 38,
+	CVMX_IRQ_GPIO15 = 39,
+	CVMX_IRQ_MBOX0 = 40,
+	CVMX_IRQ_MBOX1 = 41,
+	CVMX_IRQ_UART0 = 42,
+	CVMX_IRQ_UART1 = 43,
+	CVMX_IRQ_PCI_INT0 = 44,
+	CVMX_IRQ_PCI_INT1 = 45,
+	CVMX_IRQ_PCI_INT2 = 46,
+	CVMX_IRQ_PCI_INT3 = 47,
+	CVMX_IRQ_PCI_MSI0 = 48,
+	CVMX_IRQ_PCI_MSI1 = 49,
+	CVMX_IRQ_PCI_MSI2 = 50,
+	CVMX_IRQ_PCI_MSI3 = 51,
+	CVMX_IRQ_RESERVED44 = 52,
+	CVMX_IRQ_TWSI = 53,
+	CVMX_IRQ_RML = 54,
+	CVMX_IRQ_TRACE = 55,
+	CVMX_IRQ_GMX_DRP0 = 56,
+	CVMX_IRQ_GMX_DRP1 = 57,
+	CVMX_IRQ_IPD_DRP = 58,
+	CVMX_IRQ_KEY_ZERO = 59,
+	CVMX_IRQ_TIMER0 = 60,
+	CVMX_IRQ_TIMER1 = 61,
+	CVMX_IRQ_TIMER2 = 62,
+	CVMX_IRQ_TIMER3 = 63,
+	CVMX_IRQ_USB = 64,	/* Doesn't apply on CN38XX or CN58XX */
+	CVMX_IRQ_PCM = 65,
+	CVMX_IRQ_MPI = 66,
+	CVMX_IRQ_TWSI2 = 67,	/* Added in CN56XX */
+	CVMX_IRQ_POWIQ = 68,	/* Added in CN56XX */
+	CVMX_IRQ_IPDPPTHR = 69,	/* Added in CN56XX */
+	CVMX_IRQ_MII = 70,	/* Added in CN56XX */
+	CVMX_IRQ_BOOTDMA = 71,	/* Added in CN56XX */
+
+	/* 72 - 135 represent the sources in CIU_INTX_EN1 */
+	CVMX_IRQ_WDOG0 = 72,
+	CVMX_IRQ_WDOG1 = 73,
+	CVMX_IRQ_WDOG2 = 74,
+	CVMX_IRQ_WDOG3 = 75,
+	CVMX_IRQ_WDOG4 = 76,
+	CVMX_IRQ_WDOG5 = 77,
+	CVMX_IRQ_WDOG6 = 78,
+	CVMX_IRQ_WDOG7 = 79,
+	CVMX_IRQ_WDOG8 = 80,
+	CVMX_IRQ_WDOG9 = 81,
+	CVMX_IRQ_WDOG10 = 82,
+	CVMX_IRQ_WDOG11 = 83,
+	CVMX_IRQ_WDOG12 = 84,
+	CVMX_IRQ_WDOG13 = 85,
+	CVMX_IRQ_WDOG14 = 86,
+	CVMX_IRQ_WDOG15 = 87
+	    /* numbers 88 - 135 are reserved */
+} cvmx_irq_t;
+
+/**
+ * Function prototype for the exception handler
+ */
+typedef void (*cvmx_interrupt_exception_t) (uint64_t registers[32]);
+
+/**
+ * Function prototype for interrupt handlers
+ */
+typedef void (*cvmx_interrupt_func_t) (int irq_number, uint64_t registers[32],
+				       void *user_arg);
+
+/**
+ * Register an interrupt handler for the specified interrupt number.
+ *
+ * @param irq_number Interrupt number to register for (0-135)
+ * @param func       Function to call on interrupt.
+ * @param user_arg   User data to pass to the interrupt handler
+ */
+void cvmx_interrupt_register(cvmx_irq_t irq_number, cvmx_interrupt_func_t func,
+			     void *user_arg);
+
+/**
+ * Set the exception handler for all non interrupt sources.
+ *
+ * @param handler New exception handler
+ * @return Old exception handler
+ */
+cvmx_interrupt_exception_t
+cvmx_interrupt_set_exception(cvmx_interrupt_exception_t handler);
+
+/**
+ * Masks a given interrupt number.
+ * EN0 sources are masked on IP2
+ * EN1 sources are masked on IP3
+ *
+ * @param irq_number interrupt number to mask (0-135)
+ */
+static inline void cvmx_interrupt_mask_irq(int irq_number)
+{
+	if (irq_number < 8) {
+		uint32_t mask;
+		asm volatile ("mfc0 %0,$12,0":"=r" (mask));
+		mask &= ~(1 << (8 + irq_number));
+		asm volatile ("mtc0 %0,$12,0"::"r" (mask));
+	} else if (irq_number < 8 + 64) {
+		int ciu_bit = (irq_number - 8) & 63;
+		int ciu_offset = cvmx_get_core_num() * 2;
+		uint64_t mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(ciu_offset));
+		mask &= ~(1ull << ciu_bit);
+		cvmx_write_csr(CVMX_CIU_INTX_EN0(ciu_offset), mask);
+	} else {
+		int ciu_bit = (irq_number - 8) & 63;
+		int ciu_offset = cvmx_get_core_num() * 2 + 1;
+		uint64_t mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(ciu_offset));
+		mask &= ~(1ull << ciu_bit);
+		cvmx_write_csr(CVMX_CIU_INTX_EN1(ciu_offset), mask);
+	}
+}
+
+/**
+ * Unmasks a given interrupt number
+ * EN0 sources are unmasked on IP2
+ * EN1 sources are unmasked on IP3
+ *
+ * @param irq_number interrupt number to unmask (0-135)
+ */
+static inline void cvmx_interrupt_unmask_irq(int irq_number)
+{
+	if (irq_number < 8) {
+		uint32_t mask;
+		asm volatile ("mfc0 %0,$12,0":"=r" (mask));
+		mask |= (1 << (8 + irq_number));
+		asm volatile ("mtc0 %0,$12,0"::"r" (mask));
+	} else if (irq_number < 8 + 64) {
+		int ciu_bit = (irq_number - 8) & 63;
+		int ciu_offset = cvmx_get_core_num() * 2;
+		uint64_t mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(ciu_offset));
+		mask |= (1ull << ciu_bit);
+		cvmx_write_csr(CVMX_CIU_INTX_EN0(ciu_offset), mask);
+	} else {
+		int ciu_bit = (irq_number - 8) & 63;
+		int ciu_offset = cvmx_get_core_num() * 2 + 1;
+		uint64_t mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(ciu_offset));
+		mask |= (1ull << ciu_bit);
+		cvmx_write_csr(CVMX_CIU_INTX_EN1(ciu_offset), mask);
+	}
+}
+
+/* Disable interrupts by clearing bit 0 of the COP0 status register,
+** and return the previous contents of the status register.
+** Note: this is only used to track interrupt status. */
+static inline uint32_t cvmx_interrupt_disable_save(void)
+{
+	uint32_t flags;
+	asm volatile ("DI   %[flags]\n":[flags] "=r"(flags));
+	return (flags);
+}
+
+/* Restore the contents of the cop0 status register.  Used with
+** cvmx_interrupt_disable_save to allow recursive interrupt disabling */
+static inline void cvmx_interrupt_restore(uint32_t flags)
+{
+	/* If flags value indicates interrupts should be enabled, then enable them */
+	if (flags & 1) {
+		asm volatile ("EI     \n"::);
+	}
+}
+
+/**
+ * Utility function to decode Octeon's RSL_INT_BLOCKS interrupts
+ * into error messages.
+ */
+extern void cvmx_interrupt_rsl_decode(void);
+
+/**
+ * Utility function to enable all RSL error interupts
+ */
+extern void cvmx_interrupt_rsl_enable(void);
+
+#endif
arch/mips/cavium-octeon/executive/cvmx-l2c.c new file +711 -0
new file mode 100644
index 0000000..b44f232
@@ -0,0 +1,711 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ *
+ * Implementation of the Level 2 Cache (L2C) control,
+ * measurement, and debugging facilities.
+ *
+ *
+ */
+#include "cvmx.h"
+#include "cvmx-l2c.h"
+#include "cvmx-spinlock.h"
+#include "cvmx-interrupt.h"
+
+/* This spinlock is used internally to ensure that only one core is performing
+** certain L2 operations at a time.
+**
+** NOTE: This only protects calls from within a single application -
+** if multiple applications or operating systems are running, then it
+** is up to the user program to coordinate between them.
+*/
+CVMX_SHARED cvmx_spinlock_t cvmx_l2c_spinlock;
+
+static inline int l2_size_half(void)
+{
+	uint64_t val = cvmx_read_csr(CVMX_L2D_FUS3);
+	return !!(val & (1ull << 34));
+}
+
+int cvmx_l2c_get_core_way_partition(uint32_t core)
+{
+	uint32_t field;
+
+	/* Validate the core number */
+	if (core >= cvmx_octeon_num_cores())
+		return -1;
+
+	/* Use the lower two bits of the coreNumber to determine the bit offset
+	 * of the UMSK[] field in the L2C_SPAR register.
+	 */
+	field = (core & 0x3) * 8;
+
+	/* Return the UMSK[] field from the appropriate L2C_SPAR register based
+	 * on the coreNumber.
+	 */
+
+	switch (core & 0xC) {
+	case 0x0:
+		return (cvmx_read_csr(CVMX_L2C_SPAR0) & (0xFF << field)) >>
+			field;
+	case 0x4:
+		return (cvmx_read_csr(CVMX_L2C_SPAR1) & (0xFF << field)) >>
+			field;
+	case 0x8:
+		return (cvmx_read_csr(CVMX_L2C_SPAR2) & (0xFF << field)) >>
+			field;
+	case 0xC:
+		return (cvmx_read_csr(CVMX_L2C_SPAR3) & (0xFF << field)) >>
+			field;
+	}
+	return 0;
+}
+
+int cvmx_l2c_set_core_way_partition(uint32_t core, uint32_t mask)
+{
+	uint32_t field;
+	uint32_t valid_mask;
+
+	valid_mask = (0x1 << cvmx_l2c_get_num_assoc()) - 1;
+
+	mask &= valid_mask;
+
+	/* A UMSK setting which blocks all L2C Ways is an error. */
+	if (mask == valid_mask)
+		return -1;
+
+	/* Validate the core number */
+	if (core >= cvmx_octeon_num_cores())
+		return -1;
+
+	/* Check to make sure current mask & new mask don't block all ways */
+	if (((mask | cvmx_l2c_get_core_way_partition(core)) & valid_mask) ==
+	    valid_mask)
+		return -1;
+
+	/* Use the lower two bits of core to determine the bit offset of the
+	 * UMSK[] field in the L2C_SPAR register.
+	 */
+	field = (core & 0x3) * 8;
+
+	/* Assign the new mask setting to the UMSK[] field in the appropriate
+	 * L2C_SPAR register based on the core_num.
+	 *
+	 */
+	switch (core & 0xC) {
+	case 0x0:
+		cvmx_write_csr(CVMX_L2C_SPAR0,
+			       (cvmx_read_csr(CVMX_L2C_SPAR0) &
+				~(0xFF << field)) | mask << field);
+		break;
+	case 0x4:
+		cvmx_write_csr(CVMX_L2C_SPAR1,
+			       (cvmx_read_csr(CVMX_L2C_SPAR1) &
+				~(0xFF << field)) | mask << field);
+		break;
+	case 0x8:
+		cvmx_write_csr(CVMX_L2C_SPAR2,
+			       (cvmx_read_csr(CVMX_L2C_SPAR2) &
+				~(0xFF << field)) | mask << field);
+		break;
+	case 0xC:
+		cvmx_write_csr(CVMX_L2C_SPAR3,
+			       (cvmx_read_csr(CVMX_L2C_SPAR3) &
+				~(0xFF << field)) | mask << field);
+		break;
+	}
+	return 0;
+}
+
+int cvmx_l2c_set_hw_way_partition(uint32_t mask)
+{
+	uint32_t valid_mask;
+
+	valid_mask = 0xff;
+
+	if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN38XX)) {
+		if (l2_size_half())
+			valid_mask = 0xf;
+	} else if (l2_size_half())
+		valid_mask = 0x3;
+
+	mask &= valid_mask;
+
+	/* A UMSK setting which blocks all L2C Ways is an error. */
+	if (mask == valid_mask)
+		return -1;
+	/* Check to make sure current mask & new mask don't block all ways */
+	if (((mask | cvmx_l2c_get_hw_way_partition()) & valid_mask) ==
+	    valid_mask)
+		return -1;
+
+	cvmx_write_csr(CVMX_L2C_SPAR4,
+		       (cvmx_read_csr(CVMX_L2C_SPAR4) & ~0xFF) | mask);
+	return 0;
+}
+
+int cvmx_l2c_get_hw_way_partition(void)
+{
+	return cvmx_read_csr(CVMX_L2C_SPAR4) & (0xFF);
+}
+
+void cvmx_l2c_config_perf(uint32_t counter, cvmx_l2c_event_t event,
+			  uint32_t clear_on_read)
+{
+	cvmx_l2c_pfctl_t pfctl;
+
+	pfctl.u64 = cvmx_read_csr(CVMX_L2C_PFCTL);
+
+	switch (counter) {
+	case 0:
+		pfctl.s.cnt0sel = event;
+		pfctl.s.cnt0ena = 1;
+		if (!cvmx_octeon_is_pass1())
+			pfctl.s.cnt0rdclr = clear_on_read;
+		break;
+	case 1:
+		pfctl.s.cnt1sel = event;
+		pfctl.s.cnt1ena = 1;
+		if (!cvmx_octeon_is_pass1())
+			pfctl.s.cnt1rdclr = clear_on_read;
+		break;
+	case 2:
+		pfctl.s.cnt2sel = event;
+		pfctl.s.cnt2ena = 1;
+		if (!cvmx_octeon_is_pass1())
+			pfctl.s.cnt2rdclr = clear_on_read;
+		break;
+	case 3:
+	default:
+		pfctl.s.cnt3sel = event;
+		pfctl.s.cnt3ena = 1;
+		if (!cvmx_octeon_is_pass1())
+			pfctl.s.cnt3rdclr = clear_on_read;
+		break;
+	}
+
+	cvmx_write_csr(CVMX_L2C_PFCTL, pfctl.u64);
+}
+
+uint64_t cvmx_l2c_read_perf(uint32_t counter)
+{
+	switch (counter) {
+	case 0:
+		return cvmx_read_csr(CVMX_L2C_PFC0);
+	case 1:
+		return cvmx_read_csr(CVMX_L2C_PFC1);
+	case 2:
+		return cvmx_read_csr(CVMX_L2C_PFC2);
+	case 3:
+	default:
+		return cvmx_read_csr(CVMX_L2C_PFC3);
+	}
+}
+
+/**
+ * @INTERNAL
+ * Helper function use to fault in cache lines for L2 cache locking
+ *
+ * @param addr   Address of base of memory region to read into L2 cache
+ * @param len    Length (in bytes) of region to fault in
+ */
+static void fault_in(uint64_t addr, int len)
+{
+	volatile char *ptr;
+	volatile char dummy;
+	/* Adjust addr and length so we get all cache lines even for
+	 ** small ranges spanning two cache lines */
+	len += addr & CVMX_CACHE_LINE_MASK;
+	addr &= ~CVMX_CACHE_LINE_MASK;
+	ptr = (volatile char *)cvmx_phys_to_ptr(addr);
+	/* Invalidate L1 cache to make sure all loads result in data
+	 * being in L2 */
+	CVMX_DCACHE_INVALIDATE;
+	while (len > 0) {
+		dummy += *ptr;
+		len -= CVMX_CACHE_LINE_SIZE;
+		ptr += CVMX_CACHE_LINE_SIZE;
+	}
+}
+
+int cvmx_l2c_lock_line(uint64_t addr)
+{
+	int retval = 0;
+	cvmx_l2c_dbg_t l2cdbg;
+	cvmx_l2c_lckbase_t lckbase;
+	cvmx_l2c_lckoff_t lckoff;
+	cvmx_l2t_err_t l2t_err;
+	l2cdbg.u64 = 0;
+	lckbase.u64 = 0;
+	lckoff.u64 = 0;
+
+	cvmx_spinlock_lock(&cvmx_l2c_spinlock);
+
+	/* Clear l2t error bits if set */
+	l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+	l2t_err.s.lckerr = 1;
+	l2t_err.s.lckerr2 = 1;
+	cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+
+	addr &= ~CVMX_CACHE_LINE_MASK;
+
+	/* Set this core as debug core */
+	l2cdbg.s.ppnum = cvmx_get_core_num();
+	CVMX_SYNC;
+	cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+	cvmx_read_csr(CVMX_L2C_DBG);
+
+	lckoff.s.lck_offset = 0;	/* Only lock 1 line at a time */
+	cvmx_write_csr(CVMX_L2C_LCKOFF, lckoff.u64);
+	cvmx_read_csr(CVMX_L2C_LCKOFF);
+
+	if (((cvmx_l2c_cfg_t) (cvmx_read_csr(CVMX_L2C_CFG))).s.idxalias) {
+		int alias_shift =
+		    CVMX_L2C_IDX_ADDR_SHIFT + 2 * CVMX_L2_SET_BITS - 1;
+		uint64_t addr_tmp =
+		    addr ^ (addr & ((1 << alias_shift) - 1)) >>
+		    CVMX_L2_SET_BITS;
+		lckbase.s.lck_base = addr_tmp >> 7;
+	} else {
+		lckbase.s.lck_base = addr >> 7;
+	}
+
+	lckbase.s.lck_ena = 1;
+	cvmx_write_csr(CVMX_L2C_LCKBASE, lckbase.u64);
+	cvmx_read_csr(CVMX_L2C_LCKBASE);	/* Make sure it gets there */
+
+	fault_in(addr, CVMX_CACHE_LINE_SIZE);
+
+	lckbase.s.lck_ena = 0;
+	cvmx_write_csr(CVMX_L2C_LCKBASE, lckbase.u64);
+	cvmx_read_csr(CVMX_L2C_LCKBASE);	/* Make sure it gets there */
+
+	/* Stop being debug core */
+	cvmx_write_csr(CVMX_L2C_DBG, 0);
+	cvmx_read_csr(CVMX_L2C_DBG);
+
+	l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+	if (l2t_err.s.lckerr || l2t_err.s.lckerr2)
+		retval = 1;	/* We were unable to lock the line */
+
+	cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+
+	return retval;
+}
+
+int cvmx_l2c_lock_mem_region(uint64_t start, uint64_t len)
+{
+	int retval = 0;
+
+	/* Round start/end to cache line boundaries */
+	len += start & CVMX_CACHE_LINE_MASK;
+	start &= ~CVMX_CACHE_LINE_MASK;
+	len = (len + CVMX_CACHE_LINE_MASK) & ~CVMX_CACHE_LINE_MASK;
+
+	while (len) {
+		retval += cvmx_l2c_lock_line(start);
+		start += CVMX_CACHE_LINE_SIZE;
+		len -= CVMX_CACHE_LINE_SIZE;
+	}
+
+	return retval;
+}
+
+void cvmx_l2c_flush(void)
+{
+	uint64_t assoc, set;
+	uint64_t n_assoc, n_set;
+	cvmx_l2c_dbg_t l2cdbg;
+
+	cvmx_spinlock_lock(&cvmx_l2c_spinlock);
+
+	l2cdbg.u64 = 0;
+	if (!OCTEON_IS_MODEL(OCTEON_CN30XX))
+		l2cdbg.s.ppnum = cvmx_get_core_num();
+	l2cdbg.s.finv = 1;
+	n_set = CVMX_L2_SETS;
+	n_assoc = l2_size_half() ? (CVMX_L2_ASSOC / 2) : CVMX_L2_ASSOC;
+	for (set = 0; set < n_set; set++) {
+		for (assoc = 0; assoc < n_assoc; assoc++) {
+			l2cdbg.s.set = assoc;
+			/* Enter debug mode, and make sure all other
+			 ** writes complete before we enter debug
+			 ** mode */
+			CVMX_SYNCW;
+			cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+			cvmx_read_csr(CVMX_L2C_DBG);
+
+			CVMX_PREPARE_FOR_STORE(CVMX_ADD_SEG
+					       (CVMX_MIPS_SPACE_XKPHYS,
+						set * CVMX_CACHE_LINE_SIZE), 0);
+			CVMX_SYNCW;	/* Push STF out to L2 */
+			/* Exit debug mode */
+			CVMX_SYNC;
+			cvmx_write_csr(CVMX_L2C_DBG, 0);
+			cvmx_read_csr(CVMX_L2C_DBG);
+		}
+	}
+
+	cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+}
+
+int cvmx_l2c_unlock_line(uint64_t address)
+{
+	int assoc;
+	cvmx_l2c_tag_t tag;
+	cvmx_l2c_dbg_t l2cdbg;
+	uint32_t tag_addr;
+
+	uint32_t index = cvmx_l2c_address_to_index(address);
+
+	cvmx_spinlock_lock(&cvmx_l2c_spinlock);
+	/* Compute portion of address that is stored in tag */
+	tag_addr =
+	    ((address >> CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) &
+	     ((1 << CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) - 1));
+	for (assoc = 0; assoc < CVMX_L2_ASSOC; assoc++) {
+		tag = cvmx_get_l2c_tag(assoc, index);
+
+		if (tag.s.V && (tag.s.addr == tag_addr)) {
+			l2cdbg.u64 = 0;
+			l2cdbg.s.ppnum = cvmx_get_core_num();
+			l2cdbg.s.set = assoc;
+			l2cdbg.s.finv = 1;
+
+			CVMX_SYNC;
+			/* Enter debug mode */
+			cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+			cvmx_read_csr(CVMX_L2C_DBG);
+
+			CVMX_PREPARE_FOR_STORE(CVMX_ADD_SEG
+					       (CVMX_MIPS_SPACE_XKPHYS,
+						address), 0);
+			CVMX_SYNC;
+			/* Exit debug mode */
+			cvmx_write_csr(CVMX_L2C_DBG, 0);
+			cvmx_read_csr(CVMX_L2C_DBG);
+			cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+			return tag.s.L;
+		}
+	}
+	cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+	return 0;
+}
+
+int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len)
+{
+	int num_unlocked = 0;
+	/* Round start/end to cache line boundaries */
+	len += start & CVMX_CACHE_LINE_MASK;
+	start &= ~CVMX_CACHE_LINE_MASK;
+	len = (len + CVMX_CACHE_LINE_MASK) & ~CVMX_CACHE_LINE_MASK;
+	while (len > 0) {
+		num_unlocked += cvmx_l2c_unlock_line(start);
+		start += CVMX_CACHE_LINE_SIZE;
+		len -= CVMX_CACHE_LINE_SIZE;
+	}
+
+	return num_unlocked;
+}
+
+/* Internal l2c tag types.  These are converted to a generic structure
+** that can be used on all chips */
+typedef union {
+	uint64_t u64;
+	struct cvmx_l2c_tag_cn50xx {
+		uint64_t reserved:40;
+		uint64_t V:1;	/* Line valid */
+		uint64_t D:1;	/* Line dirty */
+		uint64_t L:1;	/* Line locked */
+		uint64_t U:1;	/* Use, LRU eviction */
+		uint64_t addr:20;	/* Phys mem addr (33..14) */
+	} cn50xx;
+	struct cvmx_l2c_tag_cn30xx {
+		uint64_t reserved:41;
+		uint64_t V:1;	/* Line valid */
+		uint64_t D:1;	/* Line dirty */
+		uint64_t L:1;	/* Line locked */
+		uint64_t U:1;	/* Use, LRU eviction */
+		uint64_t addr:19;	/* Phys mem addr (33..15) */
+	} cn30xx;
+	struct cvmx_l2c_tag_cn31xx {
+		uint64_t reserved:42;
+		uint64_t V:1;	/* Line valid */
+		uint64_t D:1;	/* Line dirty */
+		uint64_t L:1;	/* Line locked */
+		uint64_t U:1;	/* Use, LRU eviction */
+		uint64_t addr:18;	/* Phys mem addr (33..16) */
+	} cn31xx;
+	struct cvmx_l2c_tag_cn38xx {
+		uint64_t reserved:43;
+		uint64_t V:1;	/* Line valid */
+		uint64_t D:1;	/* Line dirty */
+		uint64_t L:1;	/* Line locked */
+		uint64_t U:1;	/* Use, LRU eviction */
+		uint64_t addr:17;	/* Phys mem addr (33..17) */
+	} cn38xx;
+	struct cvmx_l2c_tag_cn58xx {
+		uint64_t reserved:44;
+		uint64_t V:1;	/* Line valid */
+		uint64_t D:1;	/* Line dirty */
+		uint64_t L:1;	/* Line locked */
+		uint64_t U:1;	/* Use, LRU eviction */
+		uint64_t addr:16;	/* Phys mem addr (33..18) */
+	} cn58xx;
+	struct cvmx_l2c_tag_cn58xx cn56xx;	/* 2048 sets */
+	struct cvmx_l2c_tag_cn31xx cn52xx;	/* 512 sets */
+} __cvmx_l2c_tag_t;
+
+/**
+ * @INTERNAL
+ * Function to read a L2C tag.  This code make the current core
+ * the 'debug core' for the L2.  This code must only be executed by
+ * 1 core at a time.
+ *
+ * @param assoc  Association (way) of the tag to dump
+ * @param index  Index of the cacheline
+ *
+ * @return The Octeon model specific tag structure.  This is translated by a wrapper
+ *         function to a generic form that is easier for applications to use.
+ */
+static __cvmx_l2c_tag_t __read_l2_tag(uint64_t assoc, uint64_t index)
+{
+
+	uint64_t debug_tag_addr = (((1ULL << 63) | (index << 7)) + 96);
+	uint64_t core = cvmx_get_core_num();
+	__cvmx_l2c_tag_t tag_val;
+	uint64_t dbg_addr = CVMX_L2C_DBG;
+	uint32_t flags;
+
+	cvmx_l2c_dbg_t debug_val;
+	debug_val.u64 = 0;
+	/* For low core count parts, the core number is always small enough
+	 ** to stay in the correct field and not set any reserved bits */
+	debug_val.s.ppnum = core;
+	debug_val.s.l2t = 1;
+	debug_val.s.set = assoc;
+
+	CVMX_SYNC;		/* Make sure core is quiet (no prefetches, etc.) before entering debug mode */
+	CVMX_DCACHE_INVALIDATE;	/* Flush L1 to make sure debug load misses L1 */
+
+	flags = cvmx_interrupt_disable_save();
+
+	/* The following must be done in assembly as when in debug
+	 * mode all data loads from L2 return special debug data, not
+	 * normal memory contents.  Also, interrupts must be
+	 * disabled, since if an interrupt occurs while in debug mode
+	 * the ISR will get debug data from all its memory reads
+	 * instead of the contents of memory */
+
+	asm volatile ("        .set push              \n"
+		"        .set mips64              \n"
+		"        .set noreorder           \n"
+		"        sd    %[dbg_val], 0(%[dbg_addr])  \n"	/* Enter debug mode, wait for store */
+		"        ld    $0, 0(%[dbg_addr]) \n"
+		"        ld    %[tag_val], 0(%[tag_addr]) \n"	/* Read L2C tag data */
+		"        sd    $0, 0(%[dbg_addr])  \n"	/* Exit debug mode, wait for store */
+		"        ld    $0, 0(%[dbg_addr]) \n"
+		"        cache 9, 0($0) \n"	/* Invalidate dcache to discard debug data */
+		"        .set pop             \n" :
+		[tag_val] "=r"(tag_val) : [dbg_addr] "r"(dbg_addr),
+		[dbg_val] "r"(debug_val),
+		[tag_addr] "r"(debug_tag_addr) : "memory");
+
+	cvmx_interrupt_restore(flags);
+
+	return tag_val;
+
+}
+
+cvmx_l2c_tag_t cvmx_l2c_get_tag(uint32_t association, uint32_t index)
+{
+	__cvmx_l2c_tag_t tmp_tag;
+	cvmx_l2c_tag_t tag;
+	tag.u64 = 0;
+
+	if ((int)association >= cvmx_l2c_get_num_assoc()) {
+		cvmx_dprintf
+		    ("ERROR: cvmx_get_l2c_tag association out of range\n");
+		return tag;
+	}
+	if ((int)index >= cvmx_l2c_get_num_sets()) {
+		cvmx_dprintf ("ERROR: cvmx_get_l2c_tag "
+			      "index out of range (arg: %d, max: %d\n",
+		     index, cvmx_l2c_get_num_sets());
+		return tag;
+	}
+	/* __read_l2_tag is intended for internal use only */
+	tmp_tag = __read_l2_tag(association, index);
+
+	/* Convert all tag structure types to generic version, as it can represent all models */
+	if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) {
+		tag.s.V = tmp_tag.cn58xx.V;
+		tag.s.D = tmp_tag.cn58xx.D;
+		tag.s.L = tmp_tag.cn58xx.L;
+		tag.s.U = tmp_tag.cn58xx.U;
+		tag.s.addr = tmp_tag.cn58xx.addr;
+	} else if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
+		tag.s.V = tmp_tag.cn38xx.V;
+		tag.s.D = tmp_tag.cn38xx.D;
+		tag.s.L = tmp_tag.cn38xx.L;
+		tag.s.U = tmp_tag.cn38xx.U;
+		tag.s.addr = tmp_tag.cn38xx.addr;
+	} else if (OCTEON_IS_MODEL(OCTEON_CN31XX)
+		   || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
+		tag.s.V = tmp_tag.cn31xx.V;
+		tag.s.D = tmp_tag.cn31xx.D;
+		tag.s.L = tmp_tag.cn31xx.L;
+		tag.s.U = tmp_tag.cn31xx.U;
+		tag.s.addr = tmp_tag.cn31xx.addr;
+	} else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) {
+		tag.s.V = tmp_tag.cn30xx.V;
+		tag.s.D = tmp_tag.cn30xx.D;
+		tag.s.L = tmp_tag.cn30xx.L;
+		tag.s.U = tmp_tag.cn30xx.U;
+		tag.s.addr = tmp_tag.cn30xx.addr;
+	} else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) {
+		tag.s.V = tmp_tag.cn50xx.V;
+		tag.s.D = tmp_tag.cn50xx.D;
+		tag.s.L = tmp_tag.cn50xx.L;
+		tag.s.U = tmp_tag.cn50xx.U;
+		tag.s.addr = tmp_tag.cn50xx.addr;
+	} else {
+		cvmx_dprintf("Unsupported OCTEON Model in %s\n", __FUNCTION__);
+	}
+
+	return tag;
+}
+
+uint32_t cvmx_l2c_address_to_index(uint64_t addr)
+{
+	uint64_t idx = addr >> CVMX_L2C_IDX_ADDR_SHIFT;
+	cvmx_l2c_cfg_t l2c_cfg;
+	l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
+
+	if (l2c_cfg.s.idxalias) {
+		idx ^=
+		    ((addr & CVMX_L2C_ALIAS_MASK) >>
+		     CVMX_L2C_TAG_ADDR_ALIAS_SHIFT);
+	}
+	idx &= CVMX_L2C_IDX_MASK;
+	return idx;
+}
+
+int cvmx_l2c_get_cache_size_bytes(void)
+{
+	return cvmx_l2c_get_num_sets() * cvmx_l2c_get_num_assoc() *
+		CVMX_CACHE_LINE_SIZE;
+}
+
+/**
+ * Return log base 2 of the number of sets in the L2 cache
+ * @return
+ */
+int cvmx_l2c_get_set_bits(void)
+{
+	int l2_set_bits;
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
+		l2_set_bits = 11;	/* 2048 sets */
+	else if (OCTEON_IS_MODEL(OCTEON_CN38XX))
+		l2_set_bits = 10;	/* 1024 sets */
+	else if (OCTEON_IS_MODEL(OCTEON_CN31XX)
+		 || OCTEON_IS_MODEL(OCTEON_CN52XX))
+		l2_set_bits = 9;	/* 512 sets */
+	else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
+		l2_set_bits = 8;	/* 256 sets */
+	else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
+		l2_set_bits = 7;	/* 128 sets */
+	else {
+		cvmx_dprintf("Unsupported OCTEON Model in %s\n", __FUNCTION__);
+		l2_set_bits = 11;	/* 2048 sets */
+	}
+	return l2_set_bits;
+
+}
+
+/* Return the number of sets in the L2 Cache */
+int cvmx_l2c_get_num_sets(void)
+{
+	return 1 << cvmx_l2c_get_set_bits();
+}
+
+/* Return the number of associations in the L2 Cache */
+int cvmx_l2c_get_num_assoc(void)
+{
+	int l2_assoc;
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX) ||
+	    OCTEON_IS_MODEL(OCTEON_CN52XX) ||
+	    OCTEON_IS_MODEL(OCTEON_CN58XX) ||
+	    OCTEON_IS_MODEL(OCTEON_CN50XX) || OCTEON_IS_MODEL(OCTEON_CN38XX))
+		l2_assoc = 8;
+	else if (OCTEON_IS_MODEL(OCTEON_CN31XX) ||
+		 OCTEON_IS_MODEL(OCTEON_CN30XX))
+		l2_assoc = 4;
+	else {
+		cvmx_dprintf("Unsupported OCTEON Model in %s\n", __FUNCTION__);
+		l2_assoc = 8;
+	}
+
+	/* Check to see if part of the cache is disabled */
+	if (cvmx_fuse_read(265))
+		l2_assoc = l2_assoc >> 2;
+	else if (cvmx_fuse_read(264))
+		l2_assoc = l2_assoc >> 1;
+
+	return l2_assoc;
+}
+
+/**
+ * Flush a line from the L2 cache
+ * This should only be called from one core at a time, as this routine
+ * sets the core to the 'debug' core in order to flush the line.
+ *
+ * @param assoc  Association (or way) to flush
+ * @param index  Index to flush
+ */
+void cvmx_l2c_flush_line(uint32_t assoc, uint32_t index)
+{
+	cvmx_l2c_dbg_t l2cdbg;
+
+	l2cdbg.u64 = 0;
+	l2cdbg.s.ppnum = cvmx_get_core_num();
+	l2cdbg.s.finv = 1;
+
+	l2cdbg.s.set = assoc;
+	/* Enter debug mode, and make sure all other writes complete before we
+	 ** enter debug mode */
+	asm volatile ("sync \n":::"memory");
+	cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+	cvmx_read_csr(CVMX_L2C_DBG);
+
+	CVMX_PREPARE_FOR_STORE(((1ULL << 63) + (index) * 128), 0);
+	/* Exit debug mode */
+	asm volatile ("sync \n":::"memory");
+	cvmx_write_csr(CVMX_L2C_DBG, 0);
+	cvmx_read_csr(CVMX_L2C_DBG);
+}
arch/mips/cavium-octeon/executive/cvmx-l2c.h new file +328 -0
new file mode 100644
index 0000000..4ee87f0
@@ -0,0 +1,328 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: [email protected]
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as published by
+ * the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * @file
+ *
+ * Interface to the Level 2 Cache (L2C) control, measurement, and debugging
+ * facilities.
+ *
+ */
+
+#ifndef __CVMX_L2C_H__
+#define __CVMX_L2C_H__
+
+#define CVMX_L2_ASSOC     cvmx_l2c_get_num_assoc()	/* Deprecated macro, use function */
+#define CVMX_L2_SET_BITS  cvmx_l2c_get_set_bits()	/* Deprecated macro, use function */
+#define CVMX_L2_SETS      cvmx_l2c_get_num_sets()	/* Deprecated macro, use function */
+
+#define CVMX_L2C_IDX_ADDR_SHIFT 7	/* based on 128 byte cache line size */
+#define CVMX_L2C_IDX_MASK       (cvmx_l2c_get_num_sets() - 1)
[… more lines in the raw message]

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-linux-kernel-exports.c new file +30 -0
new file mode 100644
index 0000000..1384717

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-packet.h new file +64 -0
new file mode 100644
index 0000000..1f5d5a2

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-platform.h new file +56 -0
new file mode 100644
index 0000000..696e88f

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-spinlock.h new file +376 -0
new file mode 100644
index 0000000..7f8a30d

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-sysinfo.c new file +113 -0
new file mode 100644
index 0000000..59fa614

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-sysinfo.h new file +144 -0
new file mode 100644
index 0000000..b557d2c

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-warn.c new file +44 -0
new file mode 100644
index 0000000..db0bd31

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx-warn.h new file +46 -0
new file mode 100644
index 0000000..a00f823

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/cvmx.h new file +772 -0
new file mode 100644
index 0000000..c475224

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/octeon-feature.h new file +120 -0
new file mode 100644
index 0000000..2b7b6d8

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/octeon-model.c new file +328 -0
new file mode 100644
index 0000000..be67f77

Lines of this file are not shown. View the raw message.

arch/mips/cavium-octeon/executive/octeon-model.h new file +225 -0
new file mode 100644
index 0000000..3d4b74e

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.5.6.5

---end quoted text---

Part of the diff is not shown here. View the raw message.

#59 lore raw

Re: [PATCH 05/36] Add Cavium OCTEON processor support files to and arch/mips/cavium-octeon/executive

Hello.

Quoted 5 lines · Christoph Hellwig

So what is all this crappy code actually supposed to do?

A little explanation would help, or in this case I suspect even an explanation might not help anyore.

Hey, leaving behind 220 KB of unreplied quoting was kind of rude...

WBR, Sergei

#60 lore raw

Re: [PATCH 05/36] Add Cavium OCTEON processor support files to and arch/mips/cavium-octeon/executive

Quoted 11 lines · Sergei Shtylyov

Hello.

Quoted 5 lines · Christoph Hellwig

So what is all this crappy code actually supposed to do?

A little explanation would help, or in this case I suspect even an explanation might not help anyore.

Hey, leaving behind 220 KB of unreplied quoting was kind of rude...

Huh? I trimmer all that junk so that it didn't appear. Full quotes are rude, not trimming them.

#61 lore raw

Re: [PATCH 05/36] Add Cavium OCTEON processor support files to and arch/mips/cavium-octeon/executive

Hello.

Quoted 9 lines · Christoph Hellwig
Quoted 6 lines
Quoted 4 lines

So what is all this crappy code actually supposed to do?

A little explanation would help, or in this case I suspect even an explanation might not help anyore.

Hey, leaving behind 220 KB of unreplied quoting was kind of rude...

Huh? I trimmer all that junk so that it didn't appear. Full quotes are rude, not trimming them.

You've trimmed the patch 6 and probably forgot to trim this one. :-)

WBR, Sergei

#62 lore raw

Re: [PATCH 05/36] Add Cavium OCTEON processor support files to and arch/mips/cavium-octeon/executive

Quoted 1 line · Sergei Shtylyov

You've trimmed the patch 6 and probably forgot to trim this one. :-)

Oops, you are right.

Sincer apologies for helping the ham/spam ratio on a homeopathic level, but annoying everyone on the list :)

#63 lore raw

Re: [PATCH 04/36] Add Cavium OCTEON processor support files to arch/mips/mm.

In reply to David Daney
Quoted 28 lines · David Daney
 arch/mips/mm/c-octeon.c |  309 +++++++++++++++++++++++++++++++++++++++++++++++
 arch/mips/mm/cex-oct.S  |   70 +++++++++++
 2 files changed, 379 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/mm/c-octeon.c
 create mode 100644 arch/mips/mm/cex-oct.S
arch/mips/mm/c-octeon.c new file +16 -0
new file mode 100644
index 0000000..6c96c1a
@@ -0,0 +1,309 @@
+/*
+ * 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) 2005-2007 Cavium Networks
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/bitops.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
+
+#include <asm/bcache.h>

arch/mips/mm/c-octeon.c line 26

Quoted 10 lines
arch/mips/mm/c-octeon.c new file +10 -0
+#include <asm/bootinfo.h>
+#include <asm/cacheops.h>
+#include <asm/cpu-features.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/r4kcache.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/war.h>
+#include "../cavium-octeon/hal.h"

You probably want to move that header to arch/mips/include/asm/mach-cavium-octeon so you can get away without the "../" kludge.

Quoted 23 lines
arch/mips/mm/c-octeon.c new file +23 -0
+static void octeon_flush_icache_all_cores(struct vm_area_struct *vma)
+{
+	extern struct plat_smp_ops *mp_ops;	/* private */
+#ifdef CONFIG_SMP
+	int i;
+	int cpu;
+#endif
+
+	preempt_disable();
+#ifdef CONFIG_SMP
+	cpu = smp_processor_id();
+#endif
+	mb();
+
+	/* If we have a vma structure, we only need to worry about cores it
+	   has been used on */
+	if (vma) {
+#ifdef CONFIG_SMP
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_isset(i, vma->vm_mm->cpu_vm_mask) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");

arch/mips/mm/c-octeon.c line 88

Quoted 10 lines
arch/mips/mm/c-octeon.c new file +10 -0
+	} else {
+		/* No extra info available. Flush the icache on all cores that
+		   are online */
+#ifdef CONFIG_SMP
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_online(i) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");
+	}

You can avoid the entire #ifdef CONFIG_SMP mess with for_each_online_cpu().

For some workloads IPIs can be performance limiting. You can avoid them entirely if the mm that is being flush out of the CPU is not active on the remote processor by simply setting the remote's context for that mm to zero. This means the remote CPU will allocate a new context. That's a matter of a few instructions as long as the remote's ASID counter doesn't overflow that is 255 out of 256 times.

The price to pay is to accept that both the vtag'ed I-cache and the TLB of the remote need to be reloaded which seems relativly harmless compared to the alternatives.

arch/mips/mm/c-octeon.c line 138

Quoted 12 lines
arch/mips/mm/c-octeon.c new file +12 -0
+/**
+ * Flush the icache for a trampoline. These are used for interrupt
+ * and exception hooking.
+ *
+ * @param addr   Address to flush
+ */
+static void octeon_flush_cache_sigtramp(unsigned long addr)
+{
+	/* Only flush trampolines on the current core */
+	mb();
+	asm volatile ("synci 0(%0)\n" : : "r" (addr));
+}

Bug - unless Cavium SYNCI syncs all cores? The probability is not so high for typical apps but it's entirely possibly that on a preemptable kernel the thread that wrote the trampoline code gets rescheduled to another CPU before the flush is executed. Or after the SYNCI happened on the one core the thread is rescheduled to another CPU which then may try to return with an inconsistent I-cache. Boom.

arch/mips/mm/c-octeon.c line 167

Quoted 12 lines
arch/mips/mm/c-octeon.c new file +12 -0
+/**
+ * Flush a specific page of a vma
+ *
+ * @param vma    VMA to flush page for
+ * @param page   Page to flush
+ * @param pfn
+ */
+static void octeon_flush_cache_page(struct vm_area_struct *vma,
+				    unsigned long page, unsigned long pfn)
+{
+	if (vma->vm_flags & (VM_EXEC|VM_EXECUTABLE))
+		octeon_flush_icache_all_cores(vma);

Drop all references to VM_EXECUTABLE - this flag is dead. At this low level all that matters is VM_EXEC really.

Ok otherwise I think though in the long run we should figure out how to fold c-cavium.c into c-r4k.c. Life got a lot better since we eleminated all the various of cache code we historically used to have.

Ralf

#64 lore raw

Re: [PATCH 04/36] Add Cavium OCTEON processor support files to arch/mips/mm.

Quoted 36 lines · Ralf Baechle
Quoted 34 lines · David Daney
 arch/mips/mm/c-octeon.c |  309 +++++++++++++++++++++++++++++++++++++++++++++++
 arch/mips/mm/cex-oct.S  |   70 +++++++++++
 2 files changed, 379 insertions(+), 0 deletions(-)
 create mode 100644 arch/mips/mm/c-octeon.c
 create mode 100644 arch/mips/mm/cex-oct.S
arch/mips/mm/c-octeon.c new file +22 -0
new file mode 100644
index 0000000..6c96c1a
@@ -0,0 +1,309 @@
+/*
+ * 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) 2005-2007 Cavium Networks
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/bitops.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
+
+#include <asm/bcache.h>
+#include <asm/bootinfo.h>
+#include <asm/cacheops.h>
+#include <asm/cpu-features.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/r4kcache.h>
Quoted 9 lines

arch/mips/mm/c-octeon.c line 26

Quoted 4 lines
arch/mips/mm/c-octeon.c new file +4 -0
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/war.h>
+#include "../cavium-octeon/hal.h"

You probably want to move that header to arch/mips/include/asm/mach-cavium-octeon so you can get away without the "../" kludge.

Right, I was thinking the same thing. Consider it done.

Quoted 27 lines
Quoted 27 lines
arch/mips/mm/c-octeon.c new file +27 -0
+static void octeon_flush_icache_all_cores(struct vm_area_struct *vma)
+{
+	extern struct plat_smp_ops *mp_ops;	/* private */
+#ifdef CONFIG_SMP
+	int i;
+	int cpu;
+#endif
+
+	preempt_disable();
+#ifdef CONFIG_SMP
+	cpu = smp_processor_id();
+#endif
+	mb();
+
+	/* If we have a vma structure, we only need to worry about cores it
+	   has been used on */
+	if (vma) {
+#ifdef CONFIG_SMP
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_isset(i, vma->vm_mm->cpu_vm_mask) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");
+	} else {
+		/* No extra info available. Flush the icache on all cores that
+		   are online */
+#ifdef CONFIG_SMP
Quoted 9 lines

arch/mips/mm/c-octeon.c line 88

Quoted 6 lines
arch/mips/mm/c-octeon.c new file +6 -0
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_online(i) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");
+	}

You can avoid the entire #ifdef CONFIG_SMP mess with for_each_online_cpu().

I already rewrote that whole part, but...

Quoted 11 lines

For some workloads IPIs can be performance limiting. You can avoid them entirely if the mm that is being flush out of the CPU is not active on the remote processor by simply setting the remote's context for that mm to zero. This means the remote CPU will allocate a new context. That's a matter of a few instructions as long as the remote's ASID counter doesn't overflow that is 255 out of 256 times.

The price to pay is to accept that both the vtag'ed I-cache and the TLB of the remote need to be reloaded which seems relativly harmless compared to the alternatives.

... I will investigate doing this instead.

Quoted 6 lines
Quoted 6 lines
arch/mips/mm/c-octeon.c new file +6 -0
+/**
+ * Flush the icache for a trampoline. These are used for interrupt
+ * and exception hooking.
+ *
+ * @param addr   Address to flush
+ */
Quoted 8 lines

arch/mips/mm/c-octeon.c line 138

Quoted 6 lines
arch/mips/mm/c-octeon.c new file +6 -0
+static void octeon_flush_cache_sigtramp(unsigned long addr)
+{
+	/* Only flush trampolines on the current core */
+	mb();
+	asm volatile ("synci 0(%0)\n" : : "r" (addr));
+}

Bug - unless Cavium SYNCI syncs all cores?

It doesn't.

Quoted 6 lines

The probability is not so high
for typical apps but it's entirely possibly that on a preemptable kernel the thread that wrote the trampoline code gets rescheduled to another CPU before the flush is executed. Or after the SYNCI happened on the one core the thread is rescheduled to another CPU which then may try to return with an inconsistent I-cache. Boom.

This is the problem I mentioned yesterday on IRC. I had come to the same conclusion and think we need to invalidate the icache on all cores here.

The real solution to this problem is to place the signal trampolines in a VDSO. But that is a project for another day.

Quoted 16 lines

arch/mips/mm/c-octeon.c line 167

Quoted 13 lines
arch/mips/mm/c-octeon.c new file +12 -0
+/**
+ * Flush a specific page of a vma
+ *
+ * @param vma    VMA to flush page for
+ * @param page   Page to flush
+ * @param pfn
+ */
+static void octeon_flush_cache_page(struct vm_area_struct *vma,
+				    unsigned long page, unsigned long pfn)
+{
+	if (vma->vm_flags & (VM_EXEC|VM_EXECUTABLE))
+		octeon_flush_icache_all_cores(vma);

Drop all references to VM_EXECUTABLE - this flag is dead. At this low level all that matters is VM_EXEC really.

Consider it done.

David Daney

#65 lore raw

Re: [PATCH 04/36] Add Cavium OCTEON processor support files to arch/mips/mm.

Quoted 8 lines · David Daney
Quoted 6 lines

The probability is not so high
for typical apps but it's entirely possibly that on a preemptable kernel the thread that wrote the trampoline code gets rescheduled to another CPU before the flush is executed. Or after the SYNCI happened on the one core the thread is rescheduled to another CPU which then may try to return with an inconsistent I-cache. Boom.

Quoted 6 lines

This is the problem I mentioned yesterday on IRC. I had come to the same conclusion and think we need to invalidate the icache on all cores here.

The real solution to this problem is to place the signal trampolines in a VDSO. But that is a project for another day.

Or we once more rely on abusing the address error exception. Place an address in the kernel space into $ra before jumping to the signal handler. Once finished the signal handler then will trigger an address error. Ugly. Efficient. And it would get rid of all the fun
"Don't let your children do this ..." stunts of sigreturn.

Ralf

#66 lore raw

Re: [PATCH 04/36] Add Cavium OCTEON processor support files to arch/mips/mm.

In reply to Ralf Baechle
Quoted 1 line · Ralf Baechle

On Mon, Oct 27, 2008 at 05:02:36PM -0700, David Daney wrote:

[...]

Quoted 43 lines
Quoted 23 lines
arch/mips/mm/c-octeon.c new file +23 -0
+static void octeon_flush_icache_all_cores(struct vm_area_struct *vma)
+{
+	extern struct plat_smp_ops *mp_ops;	/* private */
+#ifdef CONFIG_SMP
+	int i;
+	int cpu;
+#endif
+
+	preempt_disable();
+#ifdef CONFIG_SMP
+	cpu = smp_processor_id();
+#endif
+	mb();
+
+	/* If we have a vma structure, we only need to worry about cores it
+	   has been used on */
+	if (vma) {
+#ifdef CONFIG_SMP
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_isset(i, vma->vm_mm->cpu_vm_mask) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");

arch/mips/mm/c-octeon.c line 88

Quoted 10 lines
arch/mips/mm/c-octeon.c new file +10 -0
+	} else {
+		/* No extra info available. Flush the icache on all cores that
+		   are online */
+#ifdef CONFIG_SMP
+		for (i = 0; i < NR_CPUS; i++)
+			if (cpu_online(i) && i != cpu)
+				mp_ops->send_ipi_single(i, SMP_ICACHE_FLUSH);
+#endif
+		asm volatile ("synci 0($0)\n");
+	}

You can avoid the entire #ifdef CONFIG_SMP mess with for_each_online_cpu().

For some workloads IPIs can be performance limiting. You can avoid them entirely if the mm that is being flush out of the CPU is not active on the remote processor by simply setting the remote's context for that mm to zero. This means the remote CPU will allocate a new context. That's a matter of a few instructions as long as the remote's ASID counter doesn't overflow that is 255 out of 256 times.

Quoted 4 lines

The price to pay is to accept that both the vtag'ed I-cache and the TLB of the remote need to be reloaded which seems relativly harmless compared to the alternatives.

Unfortunately, I don't think that will work. In order to do the optimization you must check some things in the mm. To do this in a race free manner, you need to hold the mmap_sem. flush_icache_all is sometimes called without acquiring the mmap_sem, and I have not figured out how to acquire it in such a manner that the system doesn't crash.

David Daney

#67 lore raw

Re: [PATCH 02/36] Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

In reply to David Daney

arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h line 26

Quoted 7 lines · David Daney
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h new file +7 -0
+#ifdef CONFIG_SMP
+#define cpu_has_llsc		1
+#else
+/* Disable LL/SC on non SMP systems. It is faster to disable interrupts for
+   atomic access than a LL/SC */
+#define cpu_has_llsc		0
+#endif

It also means the resulting kernel won't have support for futex which essentially means you're cut off from modern libcs.

It is possible to get this to work - but nobody bothered so far; ll/sc-less R2000 class processors are very rare these days. My recommendation is to keep cpu_has_llsc as 1 until you've fixed up the futex implementation, if you deciede so.

arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h line 50

Quoted 9 lines
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h new file +9 -0
+static inline int read_current_timer(unsigned long *result)
+{
+	asm volatile ("rdhwr %0,$31\n"
+#ifndef CONFIG_64BIT
+		      "sll %0, 0\n"
+#endif
+		      : "=r" (*result));
+	return 0;
+}

This function is unused. And anyway, this header file wasn't meant as the place for random code but only a way to describe the procesors a system may feature as tightly as possible.

Quoted 7 lines
arch/mips/include/asm/mach-cavium-octeon/irq.h new file +7 -0
+#ifndef __OCTEON_IRQ_H__
+#define __OCTEON_IRQ_H__
+
+#define NR_IRQS OCTEON_IRQ_LAST
+#define MIPS_CPU_IRQ_BASE 0
+
+/* 0 - 7 represent the 8 MIPS standard interrupt sources */

[...]

Quoted 8 lines
arch/mips/include/asm/mach-cavium-octeon/irq.h new file +8 -0
+/* 144 - 151 represent the i8259 master */
+#define OCTEON_IRQ_I8259M0      144
+#define OCTEON_IRQ_I8259M1      145
+#define OCTEON_IRQ_I8259M2      146
+#define OCTEON_IRQ_I8259M3      147
+#define OCTEON_IRQ_I8259M4      148
+#define OCTEON_IRQ_I8259M5      149
+#define OCTEON_IRQ_I8259M6      150

arch/mips/include/asm/mach-cavium-octeon/irq.h line 181

Quoted 10 lines
arch/mips/include/asm/mach-cavium-octeon/irq.h new file +10 -0
+#define OCTEON_IRQ_I8259M7      151
+/* 152 - 159 represent the i8259 slave */
+#define OCTEON_IRQ_I8259S0      152
+#define OCTEON_IRQ_I8259S1      153
+#define OCTEON_IRQ_I8259S2      154
+#define OCTEON_IRQ_I8259S3      155
+#define OCTEON_IRQ_I8259S4      156
+#define OCTEON_IRQ_I8259S5      157
+#define OCTEON_IRQ_I8259S6      158
+#define OCTEON_IRQ_I8259S7      159

You have some code for an i8259. Since ISA interrupts are well known numbers which are even hardcoded in drivers, manuals, printed on PCBs etc. I recommend to renumber interrupts such that i8259 interrupts are interrupts 0..15 and everything else follows after. Oh the pleassures of ISA cruft.

Quoted 6 lines

+/**
+ * Write a 32bit value to the Octeon NPI register space
+ *
+ * @param address Address to write to
+ * @param val Value to write
+ */

Linux coding style - comments are:

/*
* blah frobnicate zumbitso
*/

sed is your friend to fix this.

Ralf

#68 lore raw

Re: [PATCH 02/36] Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

Hello.

Quoted 8 lines · Ralf Baechle
Quoted 7 lines

+/**
+ * Write a 32bit value to the Octeon NPI register space
+ *
+ * @param address Address to write to
+ * @param val Value to write
+ */

Quoted 8 lines

Linux coding style - comments are:

/*
* blah frobnicate zumbitso
*/

sed is your friend to fix this.

This is kernel-doc style but looking wrong anyway. It should be:

/**
* octeon_npi_write32 - write a 32bit value to the Octeon NPI register space *
* @address: address to write to
* @val : value to write
*/

WBR, Sergei

#69 lore raw

Re: [PATCH 02/36] Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

In reply to Ralf Baechle
Quoted 16 lines · Ralf Baechle
Quoted 16 lines
arch/mips/include/asm/mach-cavium-octeon/irq.h new file +16 -0
+/* 144 - 151 represent the i8259 master */
+#define OCTEON_IRQ_I8259M0      144
+#define OCTEON_IRQ_I8259M1      145
+#define OCTEON_IRQ_I8259M2      146
+#define OCTEON_IRQ_I8259M3      147
+#define OCTEON_IRQ_I8259M4      148
+#define OCTEON_IRQ_I8259M5      149
+#define OCTEON_IRQ_I8259M6      150
+#define OCTEON_IRQ_I8259M7      151
+/* 152 - 159 represent the i8259 slave */
+#define OCTEON_IRQ_I8259S0      152
+#define OCTEON_IRQ_I8259S1      153
+#define OCTEON_IRQ_I8259S2      154
+#define OCTEON_IRQ_I8259S3      155
+#define OCTEON_IRQ_I8259S4      156
+#define OCTEON_IRQ_I8259S5      157
Quoted 8 lines

arch/mips/include/asm/mach-cavium-octeon/irq.h line 181

Quoted 2 lines
arch/mips/include/asm/mach-cavium-octeon/irq.h new file +2 -0
+#define OCTEON_IRQ_I8259S6      158
+#define OCTEON_IRQ_I8259S7      159

You have some code for an i8259. Since ISA interrupts are well known numbers which are even hardcoded in drivers, manuals, printed on PCBs etc. I recommend to renumber interrupts such that i8259 interrupts are interrupts 0..15 and everything else follows after. Oh the pleassures of ISA cruft.

I have long had plans to lift this stupid assumption and if I finally
lose my patience, I may even actually do it one day. ;)

Maciej

#70 lore raw

Re: [PATCH 02/36] Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

Quoted 25 lines · Maciej W. Rozycki
Quoted 16 lines
Quoted 16 lines
arch/mips/include/asm/mach-cavium-octeon/irq.h new file +16 -0
+/* 144 - 151 represent the i8259 master */
+#define OCTEON_IRQ_I8259M0      144
+#define OCTEON_IRQ_I8259M1      145
+#define OCTEON_IRQ_I8259M2      146
+#define OCTEON_IRQ_I8259M3      147
+#define OCTEON_IRQ_I8259M4      148
+#define OCTEON_IRQ_I8259M5      149
+#define OCTEON_IRQ_I8259M6      150
+#define OCTEON_IRQ_I8259M7      151
+/* 152 - 159 represent the i8259 slave */
+#define OCTEON_IRQ_I8259S0      152
+#define OCTEON_IRQ_I8259S1      153
+#define OCTEON_IRQ_I8259S2      154
+#define OCTEON_IRQ_I8259S3      155
+#define OCTEON_IRQ_I8259S4      156
+#define OCTEON_IRQ_I8259S5      157
Quoted 8 lines

arch/mips/include/asm/mach-cavium-octeon/irq.h line 181

Quoted 2 lines
arch/mips/include/asm/mach-cavium-octeon/irq.h new file +2 -0
+#define OCTEON_IRQ_I8259S6      158
+#define OCTEON_IRQ_I8259S7      159

You have some code for an i8259. Since ISA interrupts are well known numbers which are even hardcoded in drivers, manuals, printed on PCBs etc. I recommend to renumber interrupts such that i8259 interrupts are interrupts 0..15 and everything else follows after. Oh the pleassures of ISA cruft.

Quoted 2 lines

I have long had plans to lift this stupid assumption and if I finally
lose my patience, I may even actually do it one day. ;)

If we're talking about actual ISA cards - I don't think we should even try to remove the restriction. Interrupt numbers are printed on PCBs and the sysadmin has to jumper the bloody board so for sanity and consistency we rather stick to 0..15 for these systems.

It's different for systems that only have on-board ISA-peripherals with no jumpers - but making that difference only makes it more complicated again ...

Ralf

#71 lore raw

Re: [PATCH 02/36] Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

Quoted 7 lines · Ralf Baechle
Quoted 2 lines

I have long had plans to lift this stupid assumption and if I finally
lose my patience, I may even actually do it one day. ;)

If we're talking about actual ISA cards - I don't think we should even try to remove the restriction. Interrupt numbers are printed on PCBs and the sysadmin has to jumper the bloody board so for sanity and consistency we rather stick to 0..15 for these systems.

I have thought of some sort of a simple translation layer. Module
parameters, etc. would stay the same for sanity's sake if nothing else. Unsure about /proc/interrupts, but if drivers printed the translation at initialisation, that shouldn't be that much of a problem.

I recall x86 maintainers contemplating a switch to the use of interrupt
vectors as received by the CPU rather that the current interrrupt lines (which are often artificial anyway). That would make the whole thing on that platform consistent with MSIs which do not have a "line" at all (how do *we* handle MSIs, BTW?).

I do not think ISA deserves to be treated in a special way these days
anymore. It's merely yet another kind of a bus which may be buried in a system somewhere down there behind a number of bridges. There may be more than one too -- think about that USB-to-ISA bridge someone used to sell. ;) I bet there is someone making PCI-to-ISA option cards these days too.

Thus I am more and more convinced for the ISA interrupts to get "freed".
Just not enough yet to find some time to actually do it. ;)

Maciej

#72 lore raw

Re: [PATCH 02/36] Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

In reply to Ralf Baechle
Quoted 13 lines · Ralf Baechle

arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h line 26

Quoted 7 lines · David Daney
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h new file +7 -0
+#ifdef CONFIG_SMP
+#define cpu_has_llsc		1
+#else
+/* Disable LL/SC on non SMP systems. It is faster to disable interrupts for
+   atomic access than a LL/SC */
+#define cpu_has_llsc		0
+#endif

It also means the resulting kernel won't have support for futex which essentially means you're cut off from modern libcs.

Quoted 4 lines

It is possible to get this to work - but nobody bothered so far; ll/sc-less R2000 class processors are very rare these days. My recommendation is to keep cpu_has_llsc as 1 until you've fixed up the futex implementation, if you deciede so.

Someone should tell ip32 w/ R5000 this. It seems that it is broken too.

This could explain why my R5000 O2 does weird things with glibc 2.8...

David Daney

#73 lore raw

Re: [PATCH 02/36] Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon

Quoted 11 lines · David Daney
Quoted 7 lines

It also means the resulting kernel won't have support for futex which essentially means you're cut off from modern libcs.

It is possible to get this to work - but nobody bothered so far; ll/sc-less R2000 class processors are very rare these days. My recommendation is to keep cpu_has_llsc as 1 until you've fixed up the futex implementation, if you deciede so.

Someone should tell ip32 w/ R5000 this. It seems that it is broken too.

This could explain why my R5000 O2 does weird things with glibc 2.8...

The R5000 has a hardware bug with LL/SC on XKPHYS addresses so we can't ...

Ralf

#74 lore raw

PATCH 30/36 Don't clobber spinlocks in 8250.

In reply to David Daney

In serial8250_isa_init_ports(), the port's lock is initialized. We should not overwrite it. Only copy in the fields we need.

---
 drivers/serial/8250.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)
drivers/serial/8250.c +13 -2
index 303272a..8e28750 100644
@@ -2752,12 +2752,23 @@ static struct uart_driver serial8250_reg = {
  */
 int __init early_serial_setup(struct uart_port *port)
 {
+	struct uart_port *p;
+
 	if (port->line >= ARRAY_SIZE(serial8250_ports))
 		return -ENODEV;
 
 	serial8250_isa_init_ports();
-	serial8250_ports[port->line].port	= *port;
-	serial8250_ports[port->line].port.ops	= &serial8250_pops;
+	p = &serial8250_ports[port->line].port;
+	p->iobase       = port->iobase;
+	p->membase      = port->membase;
+	p->irq          = port->irq;
+	p->uartclk      = port->uartclk;
+	p->fifosize     = port->fifosize;
+	p->regshift     = port->regshift;
+	p->iotype       = port->iotype;
+	p->flags        = port->flags;
+	p->mapbase      = port->mapbase;
+	p->private_data = port->private_data;
 	return 0;
 }
 
Signature · 1 line
1.5.6.5
#75 lore raw

PATCH 31/36 Generic 8250 serial driver changes to support future OCTEON serial patches.

In order to use Cavium OCTEON specific serial i/o drivers, we first patch the 8250 driver to use replaceable i/o functions.

---
 drivers/serial/8250.c       |  192 ++++++++++++++++++++++++++++++-------------
 include/linux/serial_8250.h |    2 +
 include/linux/serial_core.h |    2 +
 3 files changed, 138 insertions(+), 58 deletions(-)
drivers/serial/8250.c +134 -58
index 8e28750..410478f 100644
@@ -303,16 +303,16 @@ static const u8 au_io_out_map[] = {
 };
 
 /* sane hardware needs no mapping */
-static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
 {
-	if (up->port.iotype != UPIO_AU)
+	if (p->iotype != UPIO_AU)
 		return offset;
 	return au_io_in_map[offset];
 }
 
-static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
 {
-	if (up->port.iotype != UPIO_AU)
+	if (p->iotype != UPIO_AU)
 		return offset;
 	return au_io_out_map[offset];
 }
@@ -341,16 +341,16 @@ static const u8
 		[UART_SCR]	= 0x2c
 	};
 
-static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
 {
-	if (up->port.iotype != UPIO_RM9000)
+	if (p->iotype != UPIO_RM9000)
 		return offset;
 	return regmap_in[offset];
 }
 
-static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
 {
-	if (up->port.iotype != UPIO_RM9000)
+	if (p->iotype != UPIO_RM9000)
 		return offset;
 	return regmap_out[offset];
 }
@@ -363,108 +363,170 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
 
 #endif
 
-static unsigned int serial_in(struct uart_8250_port *up, int offset)
+static unsigned int hub6_serial_in_fn(struct uart_port *p, int offset)
 {
-	unsigned int tmp;
-	offset = map_8250_in_reg(up, offset) << up->port.regshift;
+	offset = map_8250_in_reg(p, offset) << p->regshift;
+	outb(p->hub6 - 1 + offset, p->iobase);
+	return inb(p->iobase + 1);
+}
 
-	switch (up->port.iotype) {
-	case UPIO_HUB6:
-		outb(up->port.hub6 - 1 + offset, up->port.iobase);
-		return inb(up->port.iobase + 1);
+static void hub6_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	outb(p->hub6 - 1 + offset, p->iobase);
+	outb(value, p->iobase + 1);
+}
 
-	case UPIO_MEM:
-	case UPIO_DWAPB:
-		return readb(up->port.membase + offset);
+static unsigned int mem_serial_in_fn(struct uart_port *p, int offset)
+{
+	offset = map_8250_in_reg(p, offset) << p->regshift;
+	return readb(p->membase + offset);
+}
 
-	case UPIO_RM9000:
-	case UPIO_MEM32:
-		return readl(up->port.membase + offset);
+static void mem_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	writeb(value, p->membase + offset);
+}
+
+static void mem32_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	writel(value, p->membase + offset);
+}
+
+static unsigned int mem32_serial_in_fn(struct uart_port *p, int offset)
+{
+	offset = map_8250_in_reg(p, offset) << p->regshift;
+	return readl(p->membase + offset);
+}
 
 #ifdef CONFIG_SERIAL_8250_AU1X00
-	case UPIO_AU:
-		return __raw_readl(up->port.membase + offset);
+static unsigned int au_serial_in_fn(struct uart_port *p, int offset)
+{
+	offset = map_8250_in_reg(p, offset) << p->regshift;
+	return __raw_readl(p->membase + offset);
+}
+
+static void au_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	__raw_writel(value, p->membase + offset);
+}
 #endif
 
-	case UPIO_TSI:
-		if (offset == UART_IIR) {
-			tmp = readl(up->port.membase + (UART_IIR & ~3));
-			return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
-		} else
-			return readb(up->port.membase + offset);
+static unsigned int tsi_serial_in_fn(struct uart_port *p, int offset)
+{
+	unsigned int tmp;
+	offset = map_8250_in_reg(p, offset) << p->regshift;
+	if (offset == UART_IIR) {
+		tmp = readl(p->membase + (UART_IIR & ~3));
+		return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+	} else
+		return readb(p->membase + offset);
+}
 
-	default:
-		return inb(up->port.iobase + offset);
-	}
+static void tsi_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+		writeb(value, p->membase + offset);
 }
 
-static void
-serial_out(struct uart_8250_port *up, int offset, int value)
+static void dwapb_serial_out_fn(struct uart_port *p, int offset, int value)
 {
-	/* Save the offset before it's remapped */
 	int save_offset = offset;
-	offset = map_8250_out_reg(up, offset) << up->port.regshift;
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	/* Save the LCR value so it can be re-written when a
+	 * Busy Detect interrupt occurs. */
+	if (save_offset == UART_LCR) {
+		struct uart_8250_port *up = (struct uart_8250_port *)p;
+		up->lcr = value;
+	}
+	writeb(value, p->membase + offset);
+	/* Read the IER to ensure any interrupt is cleared before
+	 * returning from ISR. */
+	if (save_offset == UART_TX || save_offset == UART_IER)
+		value = p->serial_in_fn(p, UART_IER);
+}
 
-	switch (up->port.iotype) {
+static unsigned int io_serial_in_fn(struct uart_port *p, int offset)
+{
+	offset = map_8250_in_reg(p, offset) << p->regshift;
+	return inb(p->iobase + offset);
+}
+
+static void io_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+	offset = map_8250_out_reg(p, offset) << p->regshift;
+	outb(value, p->iobase + offset);
+}
+
+static void set_io_fns_from_upio(struct uart_port *p)
+{
+	switch (p->iotype) {
 	case UPIO_HUB6:
-		outb(up->port.hub6 - 1 + offset, up->port.iobase);
-		outb(value, up->port.iobase + 1);
+		p->serial_in_fn = hub6_serial_in_fn;
+		p->serial_out_fn = hub6_serial_out_fn;
 		break;
 
 	case UPIO_MEM:
-		writeb(value, up->port.membase + offset);
+		p->serial_in_fn = mem_serial_in_fn;
+		p->serial_out_fn = mem_serial_out_fn;
 		break;
 
 	case UPIO_RM9000:
 	case UPIO_MEM32:
-		writel(value, up->port.membase + offset);
+		p->serial_in_fn = mem32_serial_in_fn;
+		p->serial_out_fn = mem32_serial_out_fn;
 		break;
 
 #ifdef CONFIG_SERIAL_8250_AU1X00
 	case UPIO_AU:
-		__raw_writel(value, up->port.membase + offset);
+		p->serial_in_fn = au_serial_in_fn;
+		p->serial_out_fn = au_serial_out_fn;
 		break;
 #endif
 	case UPIO_TSI:
-		if (!((offset == UART_IER) && (value & UART_IER_UUE)))
-			writeb(value, up->port.membase + offset);
+		p->serial_in_fn = tsi_serial_in_fn;
+		p->serial_out_fn = tsi_serial_out_fn;
 		break;
 
 	case UPIO_DWAPB:
-		/* Save the LCR value so it can be re-written when a
-		 * Busy Detect interrupt occurs. */
-		if (save_offset == UART_LCR)
-			up->lcr = value;
-		writeb(value, up->port.membase + offset);
-		/* Read the IER to ensure any interrupt is cleared before
-		 * returning from ISR. */
-		if (save_offset == UART_TX || save_offset == UART_IER)
-			value = serial_in(up, UART_IER);
+		p->serial_in_fn = mem_serial_in_fn;
+		p->serial_out_fn = dwapb_serial_out_fn;
 		break;
 
 	default:
-		outb(value, up->port.iobase + offset);
+		p->serial_in_fn = io_serial_in_fn;
+		p->serial_out_fn = io_serial_out_fn;
+		break;
 	}
 }
 
 static void
 serial_out_sync(struct uart_8250_port *up, int offset, int value)
 {
-	switch (up->port.iotype) {
+	struct uart_port *p = &up->port;
+	switch (p->iotype) {
 	case UPIO_MEM:
 	case UPIO_MEM32:
 #ifdef CONFIG_SERIAL_8250_AU1X00
 	case UPIO_AU:
 #endif
 	case UPIO_DWAPB:
-		serial_out(up, offset, value);
-		serial_in(up, UART_LCR);	/* safe, no side-effects */
+		p->serial_out_fn(p, offset, value);
+		p->serial_in_fn(p, UART_LCR);	/* safe, no side-effects */
 		break;
 	default:
-		serial_out(up, offset, value);
+		p->serial_out_fn(p, offset, value);
 	}
 }
 
+#define serial_in(up, offset)		\
+	(up->port.serial_in_fn(&(up)->port, (offset)))
+#define serial_out(up, offset, value)	\
+	(up->port.serial_out_fn(&(up)->port, (offset), (value)))
 /*
  * We used to support using pause I/O for certain machines.  We
  * haven't supported this for a while, but just in case it's badly
@@ -2576,6 +2638,7 @@ static void __init serial8250_isa_init_ports(void)
 		up->port.membase  = old_serial_port[i].iomem_base;
 		up->port.iotype   = old_serial_port[i].io_type;
 		up->port.regshift = old_serial_port[i].iomem_reg_shift;
+		set_io_fns_from_upio(&up->port);
 		if (share_irqs)
 			up->port.flags |= UPF_SHARE_IRQ;
 	}
@@ -2769,6 +2832,13 @@ int __init early_serial_setup(struct uart_port *port)
 	p->flags        = port->flags;
 	p->mapbase      = port->mapbase;
 	p->private_data = port->private_data;
+
+	set_io_fns_from_upio(p);
+	if (port->serial_in_fn)
+		p->serial_in_fn = port->serial_in_fn;
+	if (port->serial_out_fn)
+		p->serial_out_fn = port->serial_out_fn;
+
 	return 0;
 }
 
@@ -2986,6 +3056,12 @@ int serial8250_register_port(struct uart_port *port)
 		uart->port.private_data = port->private_data;
 		if (port->dev)
 			uart->port.dev = port->dev;
+		set_io_fns_from_upio(&uart->port);
+		/* Possibly override default I/O functions.  */
+		if (port->serial_in_fn)
+			uart->port.serial_in_fn = port->serial_in_fn;
+		if (port->serial_out_fn)
+			uart->port.serial_out_fn = port->serial_out_fn;
 
 		ret = uart_add_one_port(&serial8250_reg, &uart->port);
 		if (ret == 0)
include/linux/serial_8250.h +2 -0
index 3d37c94..eb08b04 100644
@@ -28,6 +28,8 @@ struct plat_serial8250_port {
 	unsigned char	iotype;		/* UPIO_* */
 	unsigned char	hub6;
 	upf_t		flags;		/* UPF_* flags */
+	unsigned int	(*serial_in_fn)(struct uart_port *, int);
+	void		(*serial_out_fn)(struct uart_port *, int, int);
 };
 
 /*
include/linux/serial_core.h +2 -0
index e27f216..40509b0 100644
@@ -243,6 +243,8 @@ struct uart_port {
 	spinlock_t		lock;			/* port lock */
 	unsigned long		iobase;			/* in/out[bwl] */
 	unsigned char __iomem	*membase;		/* read/write[bwl] */
+	unsigned int		(*serial_in_fn)(struct uart_port *, int);
+	void			(*serial_out_fn)(struct uart_port *, int, int);
 	unsigned int		irq;			/* irq number */
 	unsigned int		uartclk;		/* base uart clock */
 	unsigned int		fifosize;		/* tx fifo size */
Signature · 1 line
1.5.6.5
#76 lore raw

PATCH 32/36 Allow port type to be specified when calling serial8250_register_port.

Add flag value UPF_FIXED_TYPE which specifies that the UART type is known and should not be probed. For this case the UARTs properties are just copied out of the uart_config entry.

---
 drivers/serial/8250.c        |    8 ++++++++
 drivers/serial/serial_core.c |    7 +++++--
 include/linux/serial_core.h  |    2 ++
 3 files changed, 15 insertions(+), 2 deletions(-)
drivers/serial/8250.c +8 -0
index 410478f..9d16abb 100644
@@ -3056,6 +3056,14 @@ int serial8250_register_port(struct uart_port *port)
 		uart->port.private_data = port->private_data;
 		if (port->dev)
 			uart->port.dev = port->dev;
+
+		if (port->flags & UPF_FIXED_TYPE) {
+			uart->port.type = port->type;
+			uart->port.fifosize = uart_config[port->type].fifo_size;
+			uart->capabilities = uart_config[port->type].flags;
+			uart->tx_loadsz = uart_config[port->type].tx_loadsz;
+		}
+
 		set_io_fns_from_upio(&uart->port);
 		/* Possibly override default I/O functions.  */
 		if (port->serial_in_fn)
drivers/serial/serial_core.c +5 -2
index 874786a..7fef45e 100644
@@ -2198,11 +2198,14 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
 	 * Now do the auto configuration stuff.  Note that config_port
 	 * is expected to claim the resources and map the port for us.
 	 */
-	flags = UART_CONFIG_TYPE;
+	flags = 0;
 	if (port->flags & UPF_AUTO_IRQ)
 		flags |= UART_CONFIG_IRQ;
 	if (port->flags & UPF_BOOT_AUTOCONF) {
-		port->type = PORT_UNKNOWN;
+		if (!(port->flags & UPF_FIXED_TYPE)) {
+			port->type = PORT_UNKNOWN;
+			flags |= UART_CONFIG_TYPE;
+		}
 		port->ops->config_port(port, flags);
 	}
 
include/linux/serial_core.h +2 -0
index 40509b0..54e0dce 100644
@@ -290,6 +290,8 @@ struct uart_port {
 #define UPF_MAGIC_MULTIPLIER	((__force upf_t) (1 << 16))
 #define UPF_CONS_FLOW		((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ		((__force upf_t) (1 << 24))
+/* The exact UART type is known and should not be probed.  */
+#define UPF_FIXED_TYPE		((__force upf_t) (1 << 27))
 #define UPF_BOOT_AUTOCONF	((__force upf_t) (1 << 28))
 #define UPF_FIXED_PORT		((__force upf_t) (1 << 29))
 #define UPF_DEAD		((__force upf_t) (1 << 30))
Signature · 1 line
1.5.6.5
#77 lore raw

PATCH 33/36 Allow port type to specify bugs that are not probed for.

Add a bugs field to the serial8250_config and propagate it to the port's bugs field when the port is registered and configured.

---
 drivers/serial/8250.c |    2 ++
 drivers/serial/8250.h |    1 +
 2 files changed, 3 insertions(+), 0 deletions(-)
drivers/serial/8250.c +2 -0
index 9d16abb..474ab89 100644
@@ -1212,6 +1212,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 	up->port.fifosize = uart_config[up->port.type].fifo_size;
 	up->capabilities = uart_config[up->port.type].flags;
 	up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+	up->bugs |= uart_config[up->port.type].bugs;
 
 	if (up->port.type == PORT_UNKNOWN)
 		goto out;
@@ -3062,6 +3063,7 @@ int serial8250_register_port(struct uart_port *port)
 			uart->port.fifosize = uart_config[port->type].fifo_size;
 			uart->capabilities = uart_config[port->type].flags;
 			uart->tx_loadsz = uart_config[port->type].tx_loadsz;
+			uart->bugs = uart_config[port->type].bugs;
 		}
 
 		set_io_fns_from_upio(&uart->port);
drivers/serial/8250.h +1 -0
index 5202603..c9b3002 100644
@@ -34,6 +34,7 @@ struct serial8250_config {
 	const char	*name;
 	unsigned short	fifo_size;
 	unsigned short	tx_loadsz;
+	unsigned short	bugs;
 	unsigned char	fcr;
 	unsigned int	flags;
 };
Signature · 1 line
1.5.6.5
#78 lore raw

PATCH 34/36 8250 serial driver changes for Cavium OCTEON.

Cavium UART implementation won't work with the standard 8250 driver as-is. Define a new uart_config (PORT_OCTEON) and use it to enable special handling required by the OCTEON's serial port.

---
 drivers/serial/8250.c       |   16 +++++++++++++++-
 drivers/serial/8250.h       |    2 ++
 include/linux/serial_core.h |    3 ++-
 include/linux/serial_reg.h  |    6 ++++++
 4 files changed, 25 insertions(+), 2 deletions(-)
drivers/serial/8250.c +15 -1
index 474ab89..f274e94 100644
@@ -279,6 +279,14 @@ static const struct serial8250_config uart_config[] = {
 		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
 		.flags		= UART_CAP_FIFO,
 	},
+	[PORT_OCTEON] = {
+		.name		= "OCTEON",
+		.fifo_size	= 64,
+		.tx_loadsz	= 64,
+		.bugs		= UART_BUG_TIMEOUT | UART_BUG_OCTEON_IIR,
+		.fcr		= UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+		.flags		= UART_CAP_FIFO,
+	},
 };
 
 #if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -1554,6 +1562,12 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
 		up = list_entry(l, struct uart_8250_port, list);
 
 		iir = serial_in(up, UART_IIR);
+		if ((up->bugs & UART_BUG_OCTEON_IIR) && (iir & 0xf) == 7) {
+			/* Busy interrupt */
+			serial_in(up, UART_OCTEON_USR);
+			iir = serial_in(up, UART_IIR);
+		}
+
 		if (!(iir & UART_IIR_NO_INT)) {
 			serial8250_handle_port(up);
 
@@ -1714,7 +1728,7 @@ static void serial8250_timeout(unsigned long data)
 	unsigned int iir;
 
 	iir = serial_in(up, UART_IIR);
-	if (!(iir & UART_IIR_NO_INT))
+	if (!(iir & UART_IIR_NO_INT) || (up->bugs & UART_BUG_TIMEOUT))
 		serial8250_handle_port(up);
 	mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
 }
drivers/serial/8250.h +2 -0
index c9b3002..56b3cb7 100644
@@ -49,6 +49,8 @@ struct serial8250_config {
 #define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */
 #define UART_BUG_NOMSR	(1 << 2)	/* UART has buggy MSR status bits (Au1x00) */
 #define UART_BUG_THRE	(1 << 3)	/* UART has buggy THRE reassertion */
+#define UART_BUG_TIMEOUT (1 << 4)	/* UART should always handle timeout */
+#define UART_BUG_OCTEON_IIR (1 << 5)	/* UART OCTEON IIR workaround */
 
 #define PROBE_RSA	(1 << 0)
 #define PROBE_ANY	(~0)
include/linux/serial_core.h +2 -1
index 54e0dce..c6c7faa 100644
@@ -40,7 +40,8 @@
 #define PORT_NS16550A	14
 #define PORT_XSCALE	15
 #define PORT_RM9000	16	/* PMC-Sierra RM9xxx internal UART */
-#define PORT_MAX_8250	16	/* max port ID */
+#define PORT_OCTEON	17	/* Cavium OCTEON internal UART */
+#define PORT_MAX_8250	17	/* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
include/linux/serial_reg.h +6 -0
index 96c0d93..a96bd50 100644
@@ -324,5 +324,11 @@
 #define UART_OMAP_SYSC		0x15	/* System configuration register */
 #define UART_OMAP_SYSS		0x16	/* System status register */
 
+/*
+ * Extra serial register definitions for the internal UARTs in Cavium
+ * Networks OCTEON processors.
+ */
+#define UART_OCTEON_USR		0x27	/* UART Status Register */
+
 #endif /* _LINUX_SERIAL_REG_H */
 
Signature · 1 line
1.5.6.5
#79 lore raw

PATCH 35/36 Adjust the dma-common.c platform hooks.

In reply to David Daney

With our impending patch set to add Cavium OCTEON CPU support, we would like to adjust the platform hooks in dma-common.c.

Other than add a dev parameter to plat_unmap_dma_mem(), and hooks for plat_dma_supported() and plat_extra_sync_for_device() which should be nop changes for all existing targets, the only real change is to call plat_unmap_dma_mem() from dma_free_{,non}coherent(). This is a nop for all targets except jazz, and I expect that it is needed there. Really if you map the memory in dma_alloc*, you should unmap it in dma_free*.

---
 arch/mips/include/asm/mach-generic/dma-coherence.h |   26 +++++++++++++++++++-
 arch/mips/include/asm/mach-ip27/dma-coherence.h    |   26 +++++++++++++++++++-
 arch/mips/include/asm/mach-ip32/dma-coherence.h    |   26 +++++++++++++++++++-
 arch/mips/include/asm/mach-jazz/dma-coherence.h    |   26 +++++++++++++++++++-
 arch/mips/include/asm/mach-lemote/dma-coherence.h  |   26 +++++++++++++++++++-
 arch/mips/mm/dma-default.c                         |   24 ++++++++----------
 6 files changed, 136 insertions(+), 18 deletions(-)
arch/mips/include/asm/mach-generic/dma-coherence.h +25 -1
index 76e04e7..36c611b 100644
@@ -28,10 +28,34 @@ static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
 	return dma_addr;
 }
 
-static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
 {
 }
 
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < DMA_BIT_MASK(24))
+		return 0;
+
+	return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+	return;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+					 dma_addr_t dma_addr)
+{
+	return 0;
+}
+
 static inline int plat_device_is_coherent(struct device *dev)
 {
 #ifdef CONFIG_DMA_COHERENT
arch/mips/include/asm/mach-ip27/dma-coherence.h +25 -1
index ed7e622..4c21bfc 100644
@@ -38,10 +38,34 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
 	return dma_addr & ~(0xffUL << 56);
 }
 
-static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
 {
 }
 
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < DMA_BIT_MASK(24))
+		return 0;
+
+	return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+	return;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+					 dma_addr_t dma_addr)
+{
+	return 0;
+}
+
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 1;		/* IP27 non-cohernet mode is unsupported */
arch/mips/include/asm/mach-ip32/dma-coherence.h +25 -1
index a5511eb..7ae40f4 100644
@@ -60,10 +60,34 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
 	return addr;
 }
 
-static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
 {
 }
 
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < DMA_BIT_MASK(24))
+		return 0;
+
+	return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+	return;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+					 dma_addr_t dma_addr)
+{
+	return 0;
+}
+
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 0;		/* IP32 is non-cohernet */
arch/mips/include/asm/mach-jazz/dma-coherence.h +25 -1
index d66979a..1c7cd27 100644
@@ -27,11 +27,35 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
 	return vdma_log2phys(dma_addr);
 }
 
-static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+static void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
 {
 	vdma_free(dma_addr);
 }
 
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < DMA_BIT_MASK(24))
+		return 0;
+
+	return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+	return;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+					 dma_addr_t dma_addr)
+{
+	return 0;
+}
+
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 0;
arch/mips/include/asm/mach-lemote/dma-coherence.h +25 -1
index 7e91477..38fad7d 100644
@@ -30,10 +30,34 @@ static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
 	return dma_addr & 0x7fffffff;
 }
 
-static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
 {
 }
 
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < DMA_BIT_MASK(24))
+		return 0;
+
+	return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+	return;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+					 dma_addr_t dma_addr)
+{
+	return 0;
+}
+
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 0;
arch/mips/mm/dma-default.c +11 -13
index 5b98d0e..546e697 100644
@@ -111,6 +111,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
 void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
 	dma_addr_t dma_handle)
 {
+	plat_unmap_dma_mem(dev, dma_handle);
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
@@ -121,6 +122,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
 {
 	unsigned long addr = (unsigned long) vaddr;
 
+	plat_unmap_dma_mem(dev, dma_handle);
+
 	if (!plat_device_is_coherent(dev))
 		addr = CAC_ADDR(addr);
 
@@ -170,7 +173,7 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		__dma_sync(dma_addr_to_virt(dma_addr), size,
 		           direction);
 
-	plat_unmap_dma_mem(dma_addr);
+	plat_unmap_dma_mem(dev, dma_addr);
 }
 
 EXPORT_SYMBOL(dma_unmap_single);
@@ -226,7 +229,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
 		dma_cache_wback_inv(addr, size);
 	}
 
-	plat_unmap_dma_mem(dma_address);
+	plat_unmap_dma_mem(dev, dma_address);
 }
 
 EXPORT_SYMBOL(dma_unmap_page);
@@ -246,7 +249,7 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 			if (addr)
 				__dma_sync(addr, sg->length, direction);
 		}
-		plat_unmap_dma_mem(sg->dma_address);
+		plat_unmap_dma_mem(dev, sg->dma_address);
 	}
 }
 
@@ -272,6 +275,7 @@ void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
 {
 	BUG_ON(direction == DMA_NONE);
 
+	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev)) {
 		unsigned long addr;
 
@@ -302,6 +306,7 @@ void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
 {
 	BUG_ON(direction == DMA_NONE);
 
+	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev)) {
 		unsigned long addr;
 
@@ -348,22 +353,14 @@ EXPORT_SYMBOL(dma_sync_sg_for_device);
 
 int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-	return 0;
+	return plat_dma_mapping_error(dev, dma_addr);
 }
 
 EXPORT_SYMBOL(dma_mapping_error);
 
 int dma_supported(struct device *dev, u64 mask)
 {
-	/*
-	 * we fall back to GFP_DMA when the mask isn't all 1s,
-	 * so we can't guarantee allocations that must be
-	 * within a tighter range than GFP_DMA..
-	 */
-	if (mask < DMA_BIT_MASK(24))
-		return 0;
-
-	return 1;
+	return plat_dma_supported(dev, mask);
 }
 
 EXPORT_SYMBOL(dma_supported);
@@ -380,6 +377,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 {
 	BUG_ON(direction == DMA_NONE);
 
+	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev))
 		__dma_sync((unsigned long)vaddr, size, direction);
 }
Signature · 1 line
1.5.6.5