aboutsummaryrefslogtreecommitdiff
path: root/cvmx-access-native.h
diff options
context:
space:
mode:
Diffstat (limited to 'cvmx-access-native.h')
-rw-r--r--cvmx-access-native.h667
1 files changed, 667 insertions, 0 deletions
diff --git a/cvmx-access-native.h b/cvmx-access-native.h
new file mode 100644
index 000000000000..c16ca9e96a2e
--- /dev/null
+++ b/cvmx-access-native.h
@@ -0,0 +1,667 @@
+/***********************license start***************
+ * Copyright (c) 2003-2009 Cavium Networks (support@cavium.com). All rights
+ * reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * * Neither the name of Cavium Networks nor the names of
+ * its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
+ * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
+ * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
+ * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
+ * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
+ * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
+ * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
+ * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT
+ * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+ *
+ *
+ * For any questions regarding licensing please contact marketing@caviumnetworks.com
+ *
+ ***********************license end**************************************/
+
+/**
+ * @file
+ * Functions for accessing memory and CSRs on Octeon when we are compiling
+ * natively.
+ *
+ * <hr>$Revision: 38306 $<hr>
+*/
+#ifndef __CVMX_ACCESS_NATIVE_H__
+#define __CVMX_ACCESS_NATIVE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns the Octeon processor ID.
+ *
+ * @return Octeon processor ID from COP0
+ */
+static inline uint32_t cvmx_get_proc_id(void)
+{
+#ifdef CVMX_BUILD_FOR_LINUX_USER
+ extern uint32_t cvmx_app_init_processor_id;
+ return cvmx_app_init_processor_id;
+#else
+ uint32_t id;
+ asm ("mfc0 %0, $15,0" : "=r" (id));
+ return id;
+#endif
+}
+
+/**
+ * Convert a memory pointer (void*) into a hardware compatable
+ * memory address (uint64_t). Octeon hardware widgets don't
+ * understand logical addresses.
+ *
+ * @param ptr C style memory pointer
+ * @return Hardware physical address
+ */
+static inline uint64_t cvmx_ptr_to_phys(void *ptr)
+{
+ if (CVMX_ENABLE_PARAMETER_CHECKING)
+ cvmx_warn_if(ptr==NULL, "cvmx_ptr_to_phys() passed a NULL pointer\n");
+
+#ifdef CVMX_BUILD_FOR_UBOOT
+ /* U-boot is a special case, as it is running in error level, which disables the TLB completely.
+ ** U-boot may use kseg0 addresses, or may directly use physical addresses already */
+ return(CAST64(ptr) & 0x7FFFFFFF);
+#endif
+
+#ifdef __linux__
+ if (sizeof(void*) == 8)
+ {
+ /* We're running in 64 bit mode. Normally this means that we can use
+ 40 bits of address space (the hardware limit). Unfortunately there
+ is one case were we need to limit this to 30 bits, sign extended
+ 32 bit. Although these are 64 bits wide, only 30 bits can be used */
+ if ((CAST64(ptr) >> 62) == 3)
+ return CAST64(ptr) & cvmx_build_mask(30);
+ else
+ return CAST64(ptr) & cvmx_build_mask(40);
+ }
+ else
+ {
+#ifdef __KERNEL__
+ return (long)(ptr) & 0x1fffffff;
+#else
+ extern uint64_t linux_mem32_offset;
+ if (cvmx_likely(ptr))
+ return CAST64(ptr) - linux_mem32_offset;
+ else
+ return 0;
+#endif
+ }
+#elif defined(_WRS_KERNEL)
+ return (long)(ptr) & 0x7fffffff;
+#elif defined(VXWORKS_USER_MAPPINGS)
+ /* This mapping mode is used in vxWorks 5.5 to support 2GB of ram. The
+ 2nd 256MB is mapped at 0x10000000 and the rest of memory is 1:1 */
+ uint64_t address = (long)ptr;
+ if (address & 0x80000000)
+ return address & 0x1fffffff; /* KSEG pointers directly map the lower 256MB and bootbus */
+ else if ((address >= 0x10000000) && (address < 0x20000000))
+ return address + 0x400000000ull; /* 256MB-512MB is a virtual mapping for the 2nd 256MB */
+ else
+ return address; /* Looks to be a 1:1 mapped userspace pointer */
+#else
+#if CVMX_USE_1_TO_1_TLB_MAPPINGS
+ /* We are assumung we're running the Simple Executive standalone. In this
+ mode the TLB is setup to perform 1:1 mapping and 32 bit sign extended
+ addresses are never used. Since we know all this, save the masking
+ cycles and do nothing */
+ return CAST64(ptr);
+#else
+
+ if (sizeof(void*) == 8)
+ {
+ /* We're running in 64 bit mode. Normally this means that we can use
+ 40 bits of address space (the hardware limit). Unfortunately there
+ is one case were we need to limit this to 30 bits, sign extended
+ 32 bit. Although these are 64 bits wide, only 30 bits can be used */
+ if ((CAST64(ptr) >> 62) == 3)
+ return CAST64(ptr) & cvmx_build_mask(30);
+ else
+ return CAST64(ptr) & cvmx_build_mask(40);
+ }
+ else
+ return (long)(ptr) & 0x7fffffff;
+
+#endif
+#endif
+}
+
+
+/**
+ * Convert a hardware physical address (uint64_t) into a
+ * memory pointer (void *).
+ *
+ * @param physical_address
+ * Hardware physical address to memory
+ * @return Pointer to memory
+ */
+static inline void *cvmx_phys_to_ptr(uint64_t physical_address)
+{
+ if (CVMX_ENABLE_PARAMETER_CHECKING)
+ cvmx_warn_if(physical_address==0, "cvmx_phys_to_ptr() passed a zero address\n");
+
+#ifdef CVMX_BUILD_FOR_UBOOT
+ /* U-boot is a special case, as it is running in error level, which disables the TLB completely.
+ ** U-boot may use kseg0 addresses, or may directly use physical addresses already */
+ if (physical_address >= 0x80000000)
+ return NULL;
+ else
+ return CASTPTR(void, (physical_address & 0x7FFFFFFF));
+#endif
+
+#ifdef __linux__
+ if (sizeof(void*) == 8)
+ {
+ /* Just set the top bit, avoiding any TLB uglyness */
+ return CASTPTR(void, CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, physical_address));
+ }
+ else
+ {
+#ifdef __KERNEL__
+ return CASTPTR(void, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, physical_address));
+#else
+ extern uint64_t linux_mem32_offset;
+ if (cvmx_likely(physical_address))
+ return CASTPTR(void, physical_address + linux_mem32_offset);
+ else
+ return NULL;
+#endif
+ }
+#elif defined(_WRS_KERNEL)
+ return CASTPTR(void, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, physical_address));
+#elif defined(VXWORKS_USER_MAPPINGS)
+ /* This mapping mode is used in vxWorks 5.5 to support 2GB of ram. The
+ 2nd 256MB is mapped at 0x10000000 and the rest of memory is 1:1 */
+ if ((physical_address >= 0x10000000) && (physical_address < 0x20000000))
+ return CASTPTR(void, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, physical_address));
+ else if ((physical_address >= 0x410000000ull) && (physical_address < 0x420000000ull))
+ return CASTPTR(void, physical_address - 0x400000000ull);
+ else
+ return CASTPTR(void, physical_address);
+#else
+
+#if CVMX_USE_1_TO_1_TLB_MAPPINGS
+ /* We are assumung we're running the Simple Executive standalone. In this
+ mode the TLB is setup to perform 1:1 mapping and 32 bit sign extended
+ addresses are never used. Since we know all this, save bit insert
+ cycles and do nothing */
+ return CASTPTR(void, physical_address);
+#else
+ /* Set the XKPHYS/KSEG0 bit as appropriate based on ABI */
+ if (sizeof(void*) == 8)
+ return CASTPTR(void, CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, physical_address));
+ else
+ return CASTPTR(void, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, physical_address));
+
+#endif
+
+#endif
+}
+
+
+/* The following #if controls the definition of the macro
+ CVMX_BUILD_WRITE64. This macro is used to build a store operation to
+ a full 64bit address. With a 64bit ABI, this can be done with a simple
+ pointer access. 32bit ABIs require more complicated assembly */
+#if defined(CVMX_ABI_N64) || defined(CVMX_ABI_EABI)
+
+/* We have a full 64bit ABI. Writing to a 64bit address can be done with
+ a simple volatile pointer */
+#define CVMX_BUILD_WRITE64(TYPE, ST) \
+static inline void cvmx_write64_##TYPE(uint64_t addr, TYPE##_t val) \
+{ \
+ *CASTPTR(volatile TYPE##_t, addr) = val; \
+}
+
+#elif defined(CVMX_ABI_N32)
+
+/* The N32 ABI passes all 64bit quantities in a single register, so it is
+ possible to use the arguments directly. We have to use inline assembly
+ for the actual store since a pointer would truncate the address */
+#define CVMX_BUILD_WRITE64(TYPE, ST) \
+static inline void cvmx_write64_##TYPE(uint64_t addr, TYPE##_t val) \
+{ \
+ asm volatile (ST " %[v], 0(%[c])" ::[v] "r" (val), [c] "r" (addr)); \
+}
+
+#elif defined(CVMX_ABI_O32)
+
+#ifdef __KERNEL__
+#define CVMX_BUILD_WRITE64(TYPE, LT) extern void cvmx_write64_##TYPE(uint64_t csr_addr, TYPE##_t val);
+#else
+
+/* Ok, now the ugly stuff starts. O32 splits 64bit quantities into two
+ separate registers. Assembly must be used to put them back together
+ before they're used. What should be a simple store becomes a
+ convoluted mess of shifts and ors */
+#define CVMX_BUILD_WRITE64(TYPE, ST) \
+static inline void cvmx_write64_##TYPE(uint64_t csr_addr, TYPE##_t val) \
+{ \
+ if (sizeof(TYPE##_t) == 8) \
+ { \
+ uint32_t csr_addrh = csr_addr>>32; \
+ uint32_t csr_addrl = csr_addr; \
+ uint32_t valh = (uint64_t)val>>32; \
+ uint32_t vall = val; \
+ uint32_t tmp1; \
+ uint32_t tmp2; \
+ uint32_t tmp3; \
+ \
+ asm volatile ( \
+ ".set push\n" \
+ ".set mips64\n" \
+ "dsll %[tmp1], %[valh], 32\n" \
+ "dsll %[tmp2], %[csrh], 32\n" \
+ "dsll %[tmp3], %[vall], 32\n" \
+ "dsrl %[tmp3], %[tmp3], 32\n" \
+ "or %[tmp1], %[tmp1], %[tmp3]\n" \
+ "dsll %[tmp3], %[csrl], 32\n" \
+ "dsrl %[tmp3], %[tmp3], 32\n" \
+ "or %[tmp2], %[tmp2], %[tmp3]\n" \
+ ST " %[tmp1], 0(%[tmp2])\n" \
+ ".set pop\n" \
+ : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3)\
+ : [valh] "r" (valh), [vall] "r" (vall), \
+ [csrh] "r" (csr_addrh), [csrl] "r" (csr_addrl) \
+ ); \
+ } \
+ else \
+ { \
+ uint32_t csr_addrh = csr_addr>>32; \
+ uint32_t csr_addrl = csr_addr; \
+ uint32_t tmp1; \
+ uint32_t tmp2; \
+ \
+ asm volatile ( \
+ ".set push\n" \
+ ".set mips64\n" \
+ "dsll %[tmp1], %[csrh], 32\n" \
+ "dsll %[tmp2], %[csrl], 32\n" \
+ "dsrl %[tmp2], %[tmp2], 32\n" \
+ "or %[tmp1], %[tmp1], %[tmp2]\n" \
+ ST " %[val], 0(%[tmp1])\n" \
+ ".set pop\n" \
+ : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2) \
+ : [val] "r" (val), [csrh] "r" (csr_addrh), \
+ [csrl] "r" (csr_addrl) \
+ ); \
+ } \
+}
+
+#endif
+
+#else
+
+/* cvmx-abi.h didn't recognize the ABI. Force the compile to fail. */
+#error: Unsupported ABI
+
+#endif
+
+/* The following #if controls the definition of the macro
+ CVMX_BUILD_READ64. This macro is used to build a load operation from
+ a full 64bit address. With a 64bit ABI, this can be done with a simple
+ pointer access. 32bit ABIs require more complicated assembly */
+#if defined(CVMX_ABI_N64) || defined(CVMX_ABI_EABI)
+
+/* We have a full 64bit ABI. Writing to a 64bit address can be done with
+ a simple volatile pointer */
+#define CVMX_BUILD_READ64(TYPE, LT) \
+static inline TYPE##_t cvmx_read64_##TYPE(uint64_t addr) \
+{ \
+ return *CASTPTR(volatile TYPE##_t, addr); \
+}
+
+#elif defined(CVMX_ABI_N32)
+
+/* The N32 ABI passes all 64bit quantities in a single register, so it is
+ possible to use the arguments directly. We have to use inline assembly
+ for the actual store since a pointer would truncate the address */
+#define CVMX_BUILD_READ64(TYPE, LT) \
+static inline TYPE##_t cvmx_read64_##TYPE(uint64_t addr) \
+{ \
+ TYPE##_t val; \
+ asm volatile (LT " %[v], 0(%[c])": [v] "=r" (val) : [c] "r" (addr));\
+ return val; \
+}
+
+#elif defined(CVMX_ABI_O32)
+
+#ifdef __KERNEL__
+#define CVMX_BUILD_READ64(TYPE, LT) extern TYPE##_t cvmx_read64_##TYPE(uint64_t csr_addr);
+#else
+
+/* Ok, now the ugly stuff starts. O32 splits 64bit quantities into two
+ separate registers. Assembly must be used to put them back together
+ before they're used. What should be a simple load becomes a
+ convoluted mess of shifts and ors */
+#define CVMX_BUILD_READ64(TYPE, LT) \
+static inline TYPE##_t cvmx_read64_##TYPE(uint64_t csr_addr) \
+{ \
+ if (sizeof(TYPE##_t) == 8) \
+ { \
+ uint32_t csr_addrh = csr_addr>>32; \
+ uint32_t csr_addrl = csr_addr; \
+ uint32_t valh; \
+ uint32_t vall; \
+ \
+ asm volatile ( \
+ ".set push\n" \
+ ".set mips64\n" \
+ "dsll %[valh], %[csrh], 32\n" \
+ "dsll %[vall], %[csrl], 32\n" \
+ "dsrl %[vall], %[vall], 32\n" \
+ "or %[valh], %[valh], %[vall]\n" \
+ LT " %[vall], 0(%[valh])\n" \
+ "dsrl %[valh], %[vall], 32\n" \
+ "sll %[vall], 0\n" \
+ "sll %[valh], 0\n" \
+ ".set pop\n" \
+ : [valh] "=&r" (valh), [vall] "=&r" (vall) \
+ : [csrh] "r" (csr_addrh), [csrl] "r" (csr_addrl) \
+ ); \
+ return ((uint64_t)valh<<32) | vall; \
+ } \
+ else \
+ { \
+ uint32_t csr_addrh = csr_addr>>32; \
+ uint32_t csr_addrl = csr_addr; \
+ TYPE##_t val; \
+ uint32_t tmp; \
+ \
+ asm volatile ( \
+ ".set push\n" \
+ ".set mips64\n" \
+ "dsll %[val], %[csrh], 32\n" \
+ "dsll %[tmp], %[csrl], 32\n" \
+ "dsrl %[tmp], %[tmp], 32\n" \
+ "or %[val], %[val], %[tmp]\n" \
+ LT " %[val], 0(%[val])\n" \
+ ".set pop\n" \
+ : [val] "=&r" (val), [tmp] "=&r" (tmp) \
+ : [csrh] "r" (csr_addrh), [csrl] "r" (csr_addrl) \
+ ); \
+ return val; \
+ } \
+}
+
+#endif /* __KERNEL__ */
+
+#else
+
+/* cvmx-abi.h didn't recognize the ABI. Force the compile to fail. */
+#error: Unsupported ABI
+
+#endif
+
+/* The following defines 8 functions for writing to a 64bit address. Each
+ takes two arguments, the address and the value to write.
+ cvmx_write64_int64 cvmx_write64_uint64
+ cvmx_write64_int32 cvmx_write64_uint32
+ cvmx_write64_int16 cvmx_write64_uint16
+ cvmx_write64_int8 cvmx_write64_uint8 */
+CVMX_BUILD_WRITE64(int64, "sd");
+CVMX_BUILD_WRITE64(int32, "sw");
+CVMX_BUILD_WRITE64(int16, "sh");
+CVMX_BUILD_WRITE64(int8, "sb");
+CVMX_BUILD_WRITE64(uint64, "sd");
+CVMX_BUILD_WRITE64(uint32, "sw");
+CVMX_BUILD_WRITE64(uint16, "sh");
+CVMX_BUILD_WRITE64(uint8, "sb");
+
+/* The following defines 8 functions for reading from a 64bit address. Each
+ takes the address as the only argument
+ cvmx_read64_int64 cvmx_read64_uint64
+ cvmx_read64_int32 cvmx_read64_uint32
+ cvmx_read64_int16 cvmx_read64_uint16
+ cvmx_read64_int8 cvmx_read64_uint8 */
+CVMX_BUILD_READ64(int64, "ld");
+CVMX_BUILD_READ64(int32, "lw");
+CVMX_BUILD_READ64(int16, "lh");
+CVMX_BUILD_READ64(int8, "lb");
+CVMX_BUILD_READ64(uint64, "ld");
+CVMX_BUILD_READ64(uint32, "lw");
+CVMX_BUILD_READ64(uint16, "lhu");
+CVMX_BUILD_READ64(uint8, "lbu");
+
+static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val)
+{
+ cvmx_write64_uint64(csr_addr, val);
+
+ /* Perform an immediate read after every write to an RSL register to force
+ the write to complete. It doesn't matter what RSL read we do, so we
+ choose CVMX_MIO_BOOT_BIST_STAT because it is fast and harmless */
+ if ((csr_addr >> 40) == (0x800118))
+ cvmx_read64_uint64(CVMX_MIO_BOOT_BIST_STAT);
+}
+
+static inline void cvmx_write_io(uint64_t io_addr, uint64_t val)
+{
+ cvmx_write64_uint64(io_addr, val);
+}
+
+static inline uint64_t cvmx_read_csr(uint64_t csr_addr)
+{
+ return cvmx_read64_uint64(csr_addr);
+}
+
+static inline void cvmx_send_single(uint64_t data)
+{
+ const uint64_t CVMX_IOBDMA_SENDSINGLE = 0xffffffffffffa200ull;
+ cvmx_write64_uint64(CVMX_IOBDMA_SENDSINGLE, data);
+}
+
+static inline void cvmx_read_csr_async(uint64_t scraddr, uint64_t csr_addr)
+{
+ union
+ {
+ uint64_t u64;
+ struct {
+ uint64_t scraddr : 8;
+ uint64_t len : 8;
+ uint64_t addr :48;
+ } s;
+ } addr;
+ addr.u64 = csr_addr;
+ addr.s.scraddr = scraddr >> 3;
+ addr.s.len = 1;
+ cvmx_send_single(addr.u64);
+}
+
+
+/**
+ * Number of the Core on which the program is currently running.
+ *
+ * @return Number of cores
+ */
+static inline unsigned int cvmx_get_core_num(void)
+{
+ unsigned int core_num;
+ CVMX_RDHWRNV(core_num, 0);
+ return core_num;
+}
+
+
+/**
+ * Returns the number of bits set in the provided value.
+ * Simple wrapper for POP instruction.
+ *
+ * @param val 32 bit value to count set bits in
+ *
+ * @return Number of bits set
+ */
+static inline uint32_t cvmx_pop(uint32_t val)
+{
+ uint32_t pop;
+ CVMX_POP(pop, val);
+ return pop;
+}
+
+
+/**
+ * Returns the number of bits set in the provided value.
+ * Simple wrapper for DPOP instruction.
+ *
+ * @param val 64 bit value to count set bits in
+ *
+ * @return Number of bits set
+ */
+static inline int cvmx_dpop(uint64_t val)
+{
+ int pop;
+ CVMX_DPOP(pop, val);
+ return pop;
+}
+
+
+/**
+ * Provide current cycle counter as a return value
+ *
+ * @return current cycle counter
+ */
+static inline uint64_t cvmx_get_cycle(void)
+{
+#if defined(CVMX_ABI_O32)
+ uint32_t tmp_low, tmp_hi;
+
+ asm volatile (
+ " .set push \n"
+ " .set mips64r2 \n"
+ " .set noreorder \n"
+ " rdhwr %[tmpl], $31 \n"
+ " dsrl %[tmph], %[tmpl], 32 \n"
+ " sll %[tmpl], 0 \n"
+ " sll %[tmph], 0 \n"
+ " .set pop \n"
+ : [tmpl] "=&r" (tmp_low), [tmph] "=&r" (tmp_hi) : );
+
+ return(((uint64_t)tmp_hi << 32) + tmp_low);
+#else
+ uint64_t cycle;
+ CVMX_RDHWR(cycle, 31);
+ return(cycle);
+#endif
+}
+
+
+/**
+ * Reads a chip global cycle counter. This counts CPU cycles since
+ * chip reset. The counter is 64 bit.
+ * This register does not exist on CN38XX pass 1 silicion
+ *
+ * @return Global chip cycle count since chip reset.
+ */
+static inline uint64_t cvmx_get_cycle_global(void)
+{
+ if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1))
+ return 0;
+ else
+ return cvmx_read64_uint64(CVMX_IPD_CLK_COUNT);
+}
+
+
+/**
+ * Wait for the specified number of cycle
+ *
+ * @param cycles
+ */
+static inline void cvmx_wait(uint64_t cycles)
+{
+ uint64_t done = cvmx_get_cycle() + cycles;
+
+ while (cvmx_get_cycle() < done)
+ {
+ /* Spin */
+ }
+}
+
+
+/**
+ * Wait for the specified number of micro seconds
+ *
+ * @param usec micro seconds to wait
+ */
+static inline void cvmx_wait_usec(uint64_t usec)
+{
+ uint64_t done = cvmx_get_cycle() + usec * cvmx_sysinfo_get()->cpu_clock_hz / 1000000;
+ while (cvmx_get_cycle() < done)
+ {
+ /* Spin */
+ }
+}
+
+
+/**
+ * Perform a soft reset of Octeon
+ *
+ * @return
+ */
+static inline void cvmx_reset_octeon(void)
+{
+ cvmx_ciu_soft_rst_t ciu_soft_rst;
+ ciu_soft_rst.u64 = 0;
+ ciu_soft_rst.s.soft_rst = 1;
+ cvmx_write_csr(CVMX_CIU_SOFT_RST, ciu_soft_rst.u64);
+}
+
+
+/**
+ * Read a byte of fuse data
+ * @param byte_addr address to read
+ *
+ * @return fuse value: 0 or 1
+ */
+static inline uint8_t cvmx_fuse_read_byte(int byte_addr)
+{
+ cvmx_mio_fus_rcmd_t read_cmd;
+
+ read_cmd.u64 = 0;
+ read_cmd.s.addr = byte_addr;
+ read_cmd.s.pend = 1;
+ cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64);
+ while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD)) && read_cmd.s.pend)
+ ;
+ return(read_cmd.s.dat);
+}
+
+
+/**
+ * Read a single fuse bit
+ *
+ * @param fuse Fuse number (0-1024)
+ *
+ * @return fuse value: 0 or 1
+ */
+static inline int cvmx_fuse_read(int fuse)
+{
+ return((cvmx_fuse_read_byte(fuse >> 3) >> (fuse & 0x7)) & 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CVMX_ACCESS_NATIVE_H__ */
+