From owner-svn-src-projects@FreeBSD.ORG Sun Jun 14 06:01:46 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C3B1C106566B; Sun, 14 Jun 2009 06:01:46 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B11128FC12; Sun, 14 Jun 2009 06:01:46 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n5E61k0d036951; Sun, 14 Jun 2009 06:01:46 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n5E61kcC036950; Sun, 14 Jun 2009 06:01:46 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <200906140601.n5E61kcC036950@svn.freebsd.org> From: Warner Losh Date: Sun, 14 Jun 2009 06:01:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r194157 - in projects/mips/sys/mips: include octeon1 X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 14 Jun 2009 06:01:47 -0000 Author: imp Date: Sun Jun 14 06:01:46 2009 New Revision: 194157 URL: http://svn.freebsd.org/changeset/base/194157 Log: Move this to a more approrpiate plae. Added: projects/mips/sys/mips/octeon1/octeon_pcmap_regs.h (props changed) - copied unchanged from r194156, projects/mips/sys/mips/include/octeon_pcmap_regs.h Deleted: projects/mips/sys/mips/include/octeon_pcmap_regs.h Copied: projects/mips/sys/mips/octeon1/octeon_pcmap_regs.h (from r194156, projects/mips/sys/mips/include/octeon_pcmap_regs.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mips/sys/mips/octeon1/octeon_pcmap_regs.h Sun Jun 14 06:01:46 2009 (r194157, copy of r194156, projects/mips/sys/mips/include/octeon_pcmap_regs.h) @@ -0,0 +1,1104 @@ +/* + * This product includes software developed by the University of + * California, Berkeley and its contributors." +*/ + +#ifndef __OCTEON_PCMAP_REGS_H__ +#define __OCTEON_PCMAP_REGS_H__ + + +#define OCTEON_CACHE_LINE_SIZE 0x80 /* 128 bytes cache line size */ +#define IS_OCTEON_ALIGNED(p) (!((u_long)(p) & 0x7f)) +#define OCTEON_ALIGN(p) (((u_long)(p) + ((OCTEON_CACHE_LINE_SIZE) - 1)) & ~((OCTEON_CACHE_LINE_SIZE) - 1)) + +#ifndef LOCORE + +/* + * Utility inlines & macros + */ + +/* turn the variable name into a string */ +#define OCTEON_TMP_STR(x) OCTEON_TMP_STR2(x) +#define OCTEON_TMP_STR2(x) #x + +#define OCTEON_PREFETCH_PREF0(address, offset) \ + __asm __volatile ( ".set mips64\n" \ + ".set noreorder\n" \ + "pref 0, " OCTEON_TMP_STR(offset) "(%0)\n" \ + ".set reorder\n" \ + ".set mips0\n" \ + : \ + : "r" (address) ); + +#define OCTEON_PREFETCH(address, offset) OCTEON_PREFETCH_PREF0(address,offset) + +#define OCTEON_PREFETCH0(address) OCTEON_PREFETCH(address, 0) +#define OCTEON_PREFETCH128(address) OCTEON_PREFETCH(address, 128) + +#define OCTEON_SYNCIOBDMA __asm __volatile (".word 0x8f" : : :"memory") + +#define OCTEON_SYNCW __asm __volatile (".word 0x10f" : : ) +#define OCTEON_SYNCW __asm __volatile (".word 0x10f" : : ) +#define OCTEON_SYNCWS __asm __volatile (".word 0x14f" : : ) + +//#if defined(__mips_n32) || defined(__mips_n64) +#if defined(__not_used) + +static inline void oct_write64 (uint64_t csr_addr, uint64_t val64) +{ + uint64_t *ptr = (uint64_t *) csr_addr; + *ptr = val64; +} + +static inline void oct_write64_int64 (uint64_t csr_addr, int64_t val64i) +{ + int64_t *ptr = (int64_t *) csr_addr; + *ptr = val64i; +} + +static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8) +{ + uint64_t *ptr = (uint64_t *) csr_addr; + *ptr = (uint64_t) val8; +} + +static inline void oct_write8 (uint64_t csr_addr, uint8_t val8) +{ + oct_write64(csr_addr, (uint64_t) val8); +} + +static inline void oct_write16 (uint64_t csr_addr, uint16_t val16) +{ + oct_write64(csr_addr, (uint64_t) val16); +} + +static inline void oct_write32 (uint64_t csr_addr, uint32_t val32) +{ + oct_write64(csr_addr, (uint64_t) val32); +} + +static inline uint8_t oct_read8 (uint64_t csr_addr) +{ + uint8_t *ptr = (uint8_t *) csr_addr; + return (*ptr); +} + +static inline uint8_t oct_read16 (uint64_t csr_addr) +{ + uint16_t *ptr = (uint16_t *) csr_addr; + return (*ptr); +} + + +static inline uint32_t oct_read32 (uint64_t csr_addr) +{ + uint32_t *ptr = (uint32_t *) csr_addr; + return (*ptr); +} + +static inline uint64_t oct_read64 (uint64_t csr_addr) +{ + uint64_t *ptr = (uint64_t *) csr_addr; + return (*ptr); +} + +static inline int32_t oct_readint32 (uint64_t csr_addr) +{ + int32_t *ptr = (int32_t *) csr_addr; + return (*ptr); +} + + + +#else + + +/* ABI o32 */ + + +/* + * Read/write functions + */ +static inline void oct_write64 (uint64_t csr_addr, uint64_t val64) +{ + uint32_t csr_addrh = csr_addr >> 32; + uint32_t csr_addrl = csr_addr; + uint32_t valh = (uint64_t)val64 >> 32; + uint32_t vall = val64; + uint32_t tmp1; + uint32_t tmp2; + uint32_t tmp3; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %3, 32\n" + "dsll %1, %5, 32\n" + "dsll %2, %4, 32\n" + "dsrl %2, %2, 32\n" + "or %0, %0, %2\n" + "dsll %2, %6, 32\n" + "dsrl %2, %2, 32\n" + "or %1, %1, %2\n" + "sd %0, 0(%1)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3) + : "r" (valh), "r" (vall), + "r" (csr_addrh), "r" (csr_addrl) + ); +} + +static inline void oct_write64_int64 (uint64_t csr_addr, int64_t val64i) +{ + uint32_t csr_addrh = csr_addr >> 32; + uint32_t csr_addrl = csr_addr; + int32_t valh = (uint64_t)val64i >> 32; + int32_t vall = val64i; + uint32_t tmp1; + uint32_t tmp2; + uint32_t tmp3; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %3, 32\n" + "dsll %1, %5, 32\n" + "dsll %2, %4, 32\n" + "dsrl %2, %2, 32\n" + "or %0, %0, %2\n" + "dsll %2, %6, 32\n" + "dsrl %2, %2, 32\n" + "or %1, %1, %2\n" + "sd %0, 0(%1)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3) + : "r" (valh), "r" (vall), + "r" (csr_addrh), "r" (csr_addrl) + ); +} + + +/* + * oct_write8_x8 + * + * 8 bit data write into IO Space. Written using an 8 bit bus io transaction + */ +static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8) +{ + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + uint32_t tmp1; + uint32_t tmp2; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %3, 32\n" + "dsll %1, %4, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "sb %2, 0(%0)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (val8), "r" (csr_addrh), "r" (csr_addrl) ); +} + +/* + * oct_write8 + * + * 8 bit data write into IO Space. Written using a 64 bit bus io transaction + */ +static inline void oct_write8 (uint64_t csr_addr, uint8_t val8) +{ +#if 1 + oct_write64(csr_addr, (uint64_t) val8); +#else + + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + uint32_t tmp1; + uint32_t tmp2; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %3, 32\n" + "dsll %1, %4, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "sb %2, 0(%0)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (val8), "r" (csr_addrh), "r" (csr_addrl) ); +#endif +} + +static inline void oct_write16 (uint64_t csr_addr, uint16_t val16) +{ +#if 1 + oct_write64(csr_addr, (uint64_t) val16); + +#else + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + uint32_t tmp1; + uint32_t tmp2; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %3, 32\n" + "dsll %1, %4, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "sh %2, 0(%0)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (val16), "r" (csr_addrh), "r" (csr_addrl) ); +#endif +} + +static inline void oct_write32 (uint64_t csr_addr, uint32_t val32) +{ +#if 1 + oct_write64(csr_addr, (uint64_t) val32); +#else + + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + uint32_t tmp1; + uint32_t tmp2; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %3, 32\n" + "dsll %1, %4, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "sw %2, 0(%0)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (val32), "r" (csr_addrh), "r" (csr_addrl) ); +#endif +} + + + +static inline uint8_t oct_read8 (uint64_t csr_addr) +{ + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + uint32_t tmp1, tmp2; + + __asm __volatile ( + ".set mips64\n" + "dsll %1, %2, 32\n" + "dsll %0, %3, 32\n" + "dsrl %0, %0, 32\n" + "or %1, %1, %0\n" + "lb %1, 0(%1)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (csr_addrh), "r" (csr_addrl) ); + return ((uint8_t) tmp2); +} + +static inline uint8_t oct_read16 (uint64_t csr_addr) +{ + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + uint32_t tmp1, tmp2; + + __asm __volatile ( + ".set mips64\n" + "dsll %1, %2, 32\n" + "dsll %0, %3, 32\n" + "dsrl %0, %0, 32\n" + "or %1, %1, %0\n" + "lh %1, 0(%1)\n" + ".set mips0\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (csr_addrh), "r" (csr_addrl) ); + return ((uint16_t) tmp2); +} + + +static inline uint32_t oct_read32 (uint64_t csr_addr) +{ + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + uint32_t val32; + uint32_t tmp; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %2, 32\n" + "dsll %1, %3, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "lw %0, 0(%0)\n" + ".set mips0\n" + : "=&r" (val32), "=&r" (tmp) + : "r" (csr_addrh), "r" (csr_addrl) ); + return (val32); +} + + +static inline uint64_t oct_read64 (uint64_t csr_addr) +{ + uint32_t csr_addrh = csr_addr >> 32; + uint32_t csr_addrl = csr_addr; + uint32_t valh; + uint32_t vall; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %2, 32\n" + "dsll %1, %3, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "ld %1, 0(%0)\n" + "dsrl %0, %1, 32\n" + "dsll %1, %1, 32\n" + "dsrl %1, %1, 32\n" + ".set mips0\n" + : "=&r" (valh), "=&r" (vall) + : "r" (csr_addrh), "r" (csr_addrl) + ); + return ((uint64_t)valh << 32) | vall; +} + + +static inline int32_t oct_readint32 (uint64_t csr_addr) +{ + uint32_t csr_addrh = csr_addr>>32; + uint32_t csr_addrl = csr_addr; + int32_t val32; + uint32_t tmp; + + __asm __volatile ( + ".set mips64\n" + "dsll %0, %2, 32\n" + "dsll %1, %3, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "lw %0, 0(%0)\n" + : "=&r" (val32), "=&r" (tmp) + : "r" (csr_addrh), "r" (csr_addrl) ); + return (val32); +} + + +#endif + + +#define OCTEON_HW_BASE ((volatile uint64_t *) 0L) +#define OCTEON_REG_OFFSET (-4 * 1024ll) /* local scratchpad reg base */ +#define OCTEON_SCRATCH_BASE ((volatile uint8_t *)(OCTEON_HW_BASE + \ + OCTEON_REG_OFFSET)) + +#define OCTEON_SCR_SCRATCH 8 +#define OCTEON_SCRATCH_0 16 +#define OCTEON_SCRATCH_1 24 +#define OCTEON_SCRATCH_2 32 + + +static inline uint64_t oct_mf_chord (void) +{ + uint64_t dest; + + __asm __volatile ( ".set push\n" + ".set noreorder\n" + ".set noat\n" + ".set mips64\n" + "dmfc2 $1, 0x400\n" + "move %0, $1\n" + ".set pop\n" + : "=r" (dest) : : "$1"); + return dest; +} + + +#define MIPS64_DMFCz(cop,regnum,cp0reg,select) \ + .word (0x40200000 | (cop << 25) | (regnum << 16) | (cp0reg << 11) | select) + + +#define mips64_getcpz_xstr(s) mips64_getcpz_str(s) +#define mips64_getcpz_str(s) #s + +#define mips64_dgetcpz(cop,cpzreg,sel,val_ptr) \ + ({ __asm __volatile( \ + ".set push\n" \ + ".set mips3\n" \ + ".set noreorder\n" \ + ".set noat\n" \ + mips64_getcpz_xstr(MIPS64_DMFCz(cop,1,cpzreg,sel)) "\n" \ + "nop\n" \ + "nop\n" \ + "nop\n" \ + "nop\n" \ + "sd $1,0(%0)\n" \ + ".set pop" \ + : /* no outputs */ : "r" (val_ptr) : "$1"); \ + }) + + +#define mips64_dgetcp2(cp2reg,sel,retval_ptr) \ + mips64_dgetcpz(2,cp2reg,sel,retval_ptr) + + +#define OCTEON_MF_CHORD(dest) mips64_dgetcp2(0x400, 0, &dest) + + + +#define OCTEON_RDHWR(result, regstr) \ + __asm __volatile ( \ + ".set mips3\n" \ + "rdhwr %0,$" OCTEON_TMP_STR(regstr) "\n" \ + ".set mips\n" \ + : "=d" (result)); + +#define CVMX_MF_CHORD(dest) OCTEON_RDHWR(dest, 30) + +#define OCTEON_CHORD_HEX(dest_ptr) \ + ({ __asm __volatile( \ + ".set push\n" \ + ".set mips3\n" \ + ".set noreorder\n" \ + ".set noat\n" \ + ".word 0x7c02f03b \n"\ + "nop\n" \ + "nop\n" \ + "nop\n" \ + "nop\n" \ + "sd $2,0(%0)\n" \ + ".set pop" \ + : /* no outputs */ : "r" (dest_ptr) : "$2"); \ + }) + + + +#define OCTEON_MF_CHORD_BAD(dest) \ + __asm __volatile ( \ + ".set mips3\n" \ + "dmfc2 %0, 0x400\n" \ + ".set mips0\n" \ + : "=&r" (dest) : ) + +static inline uint64_t oct_scratch_read64 (uint64_t address) +{ + return(*((volatile uint64_t *)(OCTEON_SCRATCH_BASE + address))); +} + +static inline void oct_scratch_write64 (uint64_t address, uint64_t value) +{ + *((volatile uint64_t *)(OCTEON_SCRATCH_BASE + address)) = value; +} + + +#define OCTEON_READ_CSR32(addr, val) \ + addr_ptr = addr; \ + oct_read_32_ptr(&addr_ptr, &val); + +#define OCTEON_WRITE_CSR32(addr, val, val_dummy) \ + addr_ptr = addr; \ + oct_write_32_ptr(&addr_ptr, &val); \ + oct_read64(OCTEON_MIO_BOOT_BIST_STAT); + + + +/* + * Octeon Address Space Definitions + */ +typedef enum { + OCTEON_MIPS_SPACE_XKSEG = 3LL, + OCTEON_MIPS_SPACE_XKPHYS = 2LL, + OCTEON_MIPS_SPACE_XSSEG = 1LL, + OCTEON_MIPS_SPACE_XUSEG = 0LL +} octeon_mips_space_t; + +typedef enum { + OCTEON_MIPS_XKSEG_SPACE_KSEG0 = 0LL, + OCTEON_MIPS_XKSEG_SPACE_KSEG1 = 1LL, + OCTEON_MIPS_XKSEG_SPACE_SSEG = 2LL, + OCTEON_MIPS_XKSEG_SPACE_KSEG3 = 3LL +} octeon_mips_xkseg_space_t; + + +/* +*********************************************************************** + * 32 bit mode alert + * The kseg0 calc below might fail in xkphys. + */ + +/* + * We limit the allocated device physical blocks to low mem. So use Kseg0 + */ + +#ifndef AVOID_CODE_NOT_64_BIT /* #ifdef PTR_SIZE == sizeof(u_int32) */ +//#define OCTEON_PHYS2PTR(addr) ((void *) (((uint32_t) addr) | 0x80000000)) +#define OCTEON_PHYS2PTR(addr) ((void *) (((vm_offset_t) addr) | MIPS_KSEG0_START)) +#endif + +#ifdef IN_FUTURE_64_BIT +#ifdef PTR_SIZE == sizeof(u_int64) +#define OCTEON_PHYS2PTR(addr) ((void *) (((uint64_t) addr) | (1ul << 63)) +#endif +#endif + +/* + * Need to go back to kernel to find v->p mappings & vice-versa + * We are getting non 1-1 mappings. + * #define OCTEON_PTR2PHYS(addr) ((unsigned long) addr & 0x7fffffff) + */ +#define OCTEON_PTR2PHYS(addr) octeon_ptr_to_phys(addr) + + + +/* PTR_SIZE == sizeof(uint32_t) */ + +#define mipsx_addr_size uint32_t // u_int64 +#define MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT 30 // 62 +#define MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED 0x1fffffff // 0x1fffffff + + +#ifdef CODE_FOR_64_BIT_NEEDED +#ifdef PTR_SIZE == sizeof(uint64_t) +#define mipsx_addr_size uint64_t +#define MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT 62 +#define MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED 0x1fffffff ffff ffff +#endif +#endif + + +#define octeon_ptr_to_phys(ptr) \ + ((((mipsx_addr_size) ptr) >> MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT) == 2) ? \ + ((mipsx_addr_size) ptr & MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED) : \ + (vtophys(ptr)) + + +#ifdef CODE_FOR_64_BIT_NEEDED +static inline mipsx_addr_size octeon_ptr_to_phys (void *ptr) +{ + if ((((mipsx_addr_size) ptr) >> MIPSX_ADDR_SIZE_KSEGX_BIT_SHIFT) == 2) { + /* + * KSEG0 based address ? + */ + return ((mipsx_addr_size) ptr & MIPSX_ADDR_SIZE_KSEGX_MASK_REMOVED); + } else { + /* + * Ask kernel/vm to give us the phys translation. + */ + return (vtophys(ptr)); + } +} +#endif + +#define OCTEON_IO_SEG OCTEON_MIPS_SPACE_XKPHYS + + +#define OCTEON_ADD_SEG(segment, add) ((((uint64_t)segment) << 62) | (add)) + +#define OCTEON_ADD_IO_SEG(add) OCTEON_ADD_SEG(OCTEON_IO_SEG, (add)) +#define OCTEON_ADDR_DID(did) (OCTEON_ADDR_DIDSPACE(did) << 40) +#define OCTEON_ADDR_DIDSPACE(did) (((OCTEON_IO_SEG) << 22) | ((1ULL) << 8) | (did)) +#define OCTEON_ADDR_FULL_DID(did,subdid) (((did) << 3) | (subdid)) + + +#define OCTEON_CIU_PP_RST OCTEON_ADD_IO_SEG(0x0001070000000700ull) +#define OCTEON_OCTEON_DID_TAG 12ULL + + + + +/* + * octeon_addr_t + */ +typedef union { + uint64_t word64; + + struct { + octeon_mips_space_t R : 2; + uint64_t offset :62; + } sva; // mapped or unmapped virtual address + + struct { + uint64_t zeroes :33; + uint64_t offset :31; + } suseg; // mapped USEG virtual addresses (typically) + + struct { + uint64_t ones :33; + octeon_mips_xkseg_space_t sp : 2; + uint64_t offset :29; + } sxkseg; // mapped or unmapped virtual address + + struct { + octeon_mips_space_t R :2; // CVMX_MIPS_SPACE_XKPHYS in this case + uint64_t cca : 3; // ignored by octeon + uint64_t mbz :10; + uint64_t pa :49; // physical address + } sxkphys; // physical address accessed through xkphys unmapped virtual address + + struct { + uint64_t mbz :15; + uint64_t is_io : 1; // if set, the address is uncached and resides on MCB bus + uint64_t did : 8; // the hardware ignores this field when is_io==0, else device ID + uint64_t unaddr: 4; // the hardware ignores <39:36> in Octeon I + uint64_t offset :36; + } sphys; // physical address + + struct { + uint64_t zeroes :24; // techically, <47:40> are dont-cares + uint64_t unaddr: 4; // the hardware ignores <39:36> in Octeon I + uint64_t offset :36; + } smem; // physical mem address + + struct { + uint64_t mem_region :2; + uint64_t mbz :13; + uint64_t is_io : 1; // 1 in this case + uint64_t did : 8; // the hardware ignores this field when is_io==0, else device ID + uint64_t unaddr: 4; // the hardware ignores <39:36> in Octeon I + uint64_t offset :36; + } sio; // physical IO address + + struct { + uint64_t didspace : 24; + uint64_t unused : 40; + } sfilldidspace; + +} octeon_addr_t; + + +typedef union { + uint64_t word64; + struct { + uint32_t word32hi; + uint32_t word32lo; + } bits; +} octeon_word_t; + + + + +/* + * octeon_build_io_address + * + * Builds a memory address for I/O based on the Major 5bits and Sub DID 3bits + */ +static inline uint64_t octeon_build_io_address (uint64_t major_did, + uint64_t sub_did) +{ + return ((0x1ull << 48) | (major_did << 43) | (sub_did << 40)); +} + +/* + * octeon_build_mask + * + * Builds a bit mask given the required size in bits. + * + * @param bits Number of bits in the mask + * @return The mask + */ +static inline uint64_t octeon_build_mask (uint64_t bits) +{ + return ~((~0x0ull) << bits); +} + +/* + * octeon_build_bits + * + * Perform mask and shift to place the supplied value into + * the supplied bit rage. + * + * Example: octeon_build_bits(39,24,value) + *
+ * 6       5       4       3       3       2       1
+ * 3       5       7       9       1       3       5       7      0
+ * +-------+-------+-------+-------+-------+-------+-------+------+
+ * 000000000000000000000000___________value000000000000000000000000
+ * 
+ * + * @param high_bit Highest bit value can occupy (inclusive) 0-63 + * @param low_bit Lowest bit value can occupy inclusive 0-high_bit + * @param value Value to use + * @return Value masked and shifted + */ +static inline uint64_t octeon_build_bits (uint64_t high_bit, uint64_t low_bit, + uint64_t value) +{ + return ((value & octeon_build_mask(high_bit - low_bit + 1)) << low_bit); +} + + +/********************** simple spinlocks ***************/ +typedef struct { + volatile uint32_t value; +} octeon_spinlock_t; + +// note - macros not expanded in inline ASM, so values hardcoded +#define OCTEON_SPINLOCK_UNLOCKED_VAL 0 +#define OCTEON_SPINLOCK_LOCKED_VAL 1 + +/** + * Initialize a spinlock + * + * @param lock Lock to initialize + */ +static inline void octeon_spinlock_init(octeon_spinlock_t *lock) +{ + lock->value = OCTEON_SPINLOCK_UNLOCKED_VAL; +} +/** + * Releases lock + * + * @param lock pointer to lock structure + */ +static inline void octeon_spinlock_unlock(octeon_spinlock_t *lock) +{ + OCTEON_SYNCWS; + + lock->value = 0; + OCTEON_SYNCWS; +} + +/** + * Gets lock, spins until lock is taken + * + * @param lock pointer to lock structure + */ +static inline void octeon_spinlock_lock(octeon_spinlock_t *lock) +{ + unsigned int tmp; + __asm __volatile( + ".set noreorder \n" + "1: ll %1, %0 \n" + " bnez %1, 1b \n" + " li %1, 1 \n" + " sc %1, %0 \n" + " beqz %1, 1b \n" + " nop \n" + ".set reorder \n" + : "+m" (lock->value), "=&r" (tmp ) + : + : "memory"); +} + +/********************** end simple spinlocks ***************/ + + + +/* ------------------------------------------------------------------- * + * octeon_get_chipid() * + * ------------------------------------------------------------------- */ +#define OCTEON_CN31XX_CHIP 0x000d0100 +#define OCTEON_CN30XX_CHIP 0x000d0200 +#define OCTEON_CN3020_CHIP 0x000d0112 +#define OCTEON_CN5020_CHIP 0x000d0601 + +static inline uint32_t octeon_get_chipid(void) +{ + uint32_t id; + + __asm __volatile ("mfc0 %0, $15,0" : "=r" (id)); + + return (id); +} + + +static inline uint32_t octeon_get_except_base_reg (void) +{ + uint32_t tmp; + + __asm volatile ( + " .set mips64r2 \n" + " .set noreorder \n" + " mfc0 %0, $15, 1 \n" + " .set reorder \n" + : "=&r" (tmp) : ); + + return(tmp); +} + + + + +static inline unsigned int get_coremask (void) +{ + return(~(oct_read64(OCTEON_CIU_PP_RST)) & 0xffff); +} + + +static inline uint32_t octeon_get_core_num (void) +{ + + return (0x3FF & octeon_get_except_base_reg()); +} + + +static inline uint64_t octeon_get_cycle(void) +{ + +/* ABI == 32 */ + + uint32_t tmp_low, tmp_hi; + + __asm __volatile ( + " .set push \n" + " .set mips64r2 \n" + " .set noreorder \n" + " rdhwr %[tmpl], $31 \n" + " dadd %[tmph], %[tmpl], $0 \n" + " dsrl %[tmph], 32 \n" + " dsll %[tmpl], 32 \n" + " dsrl %[tmpl], 32 \n" + " .set pop \n" + : [tmpl] "=&r" (tmp_low), [tmph] "=&r" (tmp_hi) : ); + + return(((uint64_t)tmp_hi << 32) + tmp_low); +} + + +/** + * Wait for the specified number of cycle + * + * @param cycles + */ +static inline void octeon_wait (uint64_t cycles) +{ + uint64_t done = octeon_get_cycle() + cycles; + + while (octeon_get_cycle() < done) + { + /* Spin */ + } +} + + + +/* + * octeon_machdep.c + * + * Direct to Board Support level. + */ +extern void octeon_led_write_char(int char_position, char val); +extern void octeon_led_write_hexchar(int char_position, char hexval); +extern void octeon_led_write_hex(uint32_t wl); +extern void octeon_led_write_string(const char *str); +extern void octeon_reset(void); +extern void octeon_uart_write_byte(int uart_index, uint8_t ch); +extern void octeon_uart_write_string(int uart_index, const char *str); +extern void octeon_uart_write_hex(uint32_t wl); +extern void octeon_uart_write_hex2(uint32_t wl, uint32_t wh); +extern void octeon_wait_uart_flush(int uart_index, uint8_t ch); +extern void octeon_uart_write_byte0(uint8_t ch); +extern void octeon_led_write_char0(char val); +extern void octeon_led_run_wheel(int *pos, int led_position); +extern void octeon_debug_symbol(void); +extern void mips_disable_interrupt_controls(void); +extern uint32_t octeon_cpu_clock; +extern uint64_t octeon_dram; +extern uint32_t octeon_bd_ver, octeon_board_rev_major, octeon_board_rev_minor, octeon_board_type; +extern uint8_t octeon_mac_addr[6]; +extern int octeon_core_mask, octeon_mac_addr_count, octeon_chip_rev_major, octeon_chip_rev_minor, octeon_chip_type; +extern void bzero_64(void *str, size_t len); +extern void bzero_32(void *str, size_t len); +extern void bzero_16(void *str, size_t len); +extern void bzero_old(void *str, size_t len); +extern void octeon_ciu_reset(void); +extern void ciu_disable_intr(int core_num, int intx, int enx); +extern void ciu_enable_interrupts (int core_num, int intx, int enx, uint64_t set_these_interrupt_bits, int ciu_ip); +extern void ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits); +extern uint64_t ciu_get_int_summary(int core_num, int intx, int enx); +extern void octeon_ciu_start_gtimer(int timer, u_int one_shot, uint64_t time_cycles); +extern void octeon_ciu_stop_gtimer(int timer); +extern int octeon_board_real(void); + + + +typedef union { + uint64_t word64; + struct { + uint64_t reserved : 27; /* Not used */ + uint64_t one_shot : 1; /* Oneshot ? */ + uint64_t len : 36; /* len of timer in clock cycles - 1 */ + } bits; +} octeon_ciu_gentimer; + + + +#endif /* LOCORE */ + + +/* + * R4K Address space definitions + */ +#define ADRSPC_K0BASE (0x80000000) +#define ADRSPC_K0SIZE (0x20000000) +#define ADRSPC_K1BASE (0xA0000000) +#define ADRSPC_K1SIZE (0x20000000) +#define ADRSPC_KSBASE (0xC0000000) +#define ADRSPC_KSSIZE (0x20000000) +#define ADRSPC_K3BASE (0xE0000000) +#define ADRSPC_K3SIZE (0x20000000) +#define ADRSPC_KUBASE (0x00000000) +#define ADRSPC_KUSIZE (0x80000000) +#define KSEG_MSB_ADDR 0xFFFFFFFF + + + +#define OCTEON_CLOCK_DEFAULT (500 * 1000 * 1000) + + +/* + * Octeon Boot Bus BIST Status + * Mostly used for dummy read to ensure all prev I/Os are write-complete. + */ +#define OCTEON_MIO_BOOT_BIST_STAT 0x80011800000000F8ull + +/* + * Octeon UART unit + */ +#define OCTEON_MIO_UART0_THR 0x8001180000000840ull +#define OCTEON_MIO_UART1_THR 0x8001180000000C40ull +#define OCTEON_MIO_UART0_LSR 0x8001180000000828ull +#define OCTEON_MIO_UART1_LSR 0x8001180000000C28ull +#define OCTEON_MIO_UART0_RBR 0x8001180000000800ull +#define OCTEON_MIO_UART1_RBR 0x8001180000000C00ull +#define OCTEON_MIO_UART0_USR 0x8001180000000938ull +#define OCTEON_MIO_UART1_USR 0x8001180000000D38ull +#define OCTEON_MIO_ADDR_HI24 0x800118 + + +/* + * EBT3000 LED Unit + */ +#define OCTEON_CHAR_LED_BASE_ADDR (0x1d020000 | (0x1ffffffffull << 31)) + +#define OCTEON_FPA_QUEUES 8 + +/* + * Octeon FPA I/O Registers + */ +#define OCTEON_FPA_CTL_STATUS 0x8001180028000050ull +#define OCTEON_FPA_FPF_SIZE 0x8001180028000058ull +#define OCTEON_FPA_FPF_MARKS 0x8001180028000000ull +#define OCTEON_FPA_INT_SUMMARY 0x8001180028000040ull +#define OCTEON_FPA_INT_ENABLE 0x8001180028000048ull +#define OCTEON_FPA_QUEUE_AVAILABLE 0x8001180028000098ull +#define OCTEON_FPA_PAGE_INDEX 0x80011800280000f0ull + +/* + * Octeon PKO Unit + */ +#define OCTEON_PKO_REG_FLAGS 0x8001180050000000ull +#define OCTEON_PKO_REG_READ_IDX 0x8001180050000008ull +#define OCTEON_PKO_CMD_BUF 0x8001180050000010ull +#define OCTEON_PKO_GMX_PORT_MODE 0x8001180050000018ull +#define OCTEON_PKO_REG_CRC_ENABLE 0x8001180050000020ull +#define OCTEON_PKO_QUEUE_MODE 0x8001180050000048ull +#define OCTEON_PKO_MEM_QUEUE_PTRS 0x8001180050001000ull +#define OCTEON_PKO_MEM_COUNT0 0x8001180050001080ull *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***