18c2ecf20Sopenharmony_ci/***********************license start*************** 28c2ecf20Sopenharmony_ci * Author: Cavium Networks 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Contact: support@caviumnetworks.com 58c2ecf20Sopenharmony_ci * This file is part of the OCTEON SDK 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2017 Cavium, Inc. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 118c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 168c2ecf20Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more 178c2ecf20Sopenharmony_ci * details. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 208c2ecf20Sopenharmony_ci * along with this file; if not, write to the Free Software 218c2ecf20Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 228c2ecf20Sopenharmony_ci * or visit http://www.gnu.org/licenses/. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * This file may also be available under a different license from Cavium. 258c2ecf20Sopenharmony_ci * Contact Cavium Networks for more information 268c2ecf20Sopenharmony_ci ***********************license end**************************************/ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#ifndef __CVMX_H__ 298c2ecf20Sopenharmony_ci#define __CVMX_H__ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <linux/kernel.h> 328c2ecf20Sopenharmony_ci#include <linux/string.h> 338c2ecf20Sopenharmony_ci#include <linux/delay.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cienum cvmx_mips_space { 368c2ecf20Sopenharmony_ci CVMX_MIPS_SPACE_XKSEG = 3LL, 378c2ecf20Sopenharmony_ci CVMX_MIPS_SPACE_XKPHYS = 2LL, 388c2ecf20Sopenharmony_ci CVMX_MIPS_SPACE_XSSEG = 1LL, 398c2ecf20Sopenharmony_ci CVMX_MIPS_SPACE_XUSEG = 0LL 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* These macros for use when using 32 bit pointers. */ 438c2ecf20Sopenharmony_ci#define CVMX_MIPS32_SPACE_KSEG0 1l 448c2ecf20Sopenharmony_ci#define CVMX_ADD_SEG32(segment, add) \ 458c2ecf20Sopenharmony_ci (((int32_t)segment << 31) | (int32_t)(add)) 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define CVMX_IO_SEG CVMX_MIPS_SPACE_XKPHYS 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* These macros simplify the process of creating common IO addresses */ 508c2ecf20Sopenharmony_ci#define CVMX_ADD_SEG(segment, add) \ 518c2ecf20Sopenharmony_ci ((((uint64_t)segment) << 62) | (add)) 528c2ecf20Sopenharmony_ci#ifndef CVMX_ADD_IO_SEG 538c2ecf20Sopenharmony_ci#define CVMX_ADD_IO_SEG(add) CVMX_ADD_SEG(CVMX_IO_SEG, (add)) 548c2ecf20Sopenharmony_ci#endif 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-asm.h> 578c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-packet.h> 588c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-sysinfo.h> 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-ciu-defs.h> 618c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-ciu3-defs.h> 628c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-gpio-defs.h> 638c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-iob-defs.h> 648c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-ipd-defs.h> 658c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-l2c-defs.h> 668c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-l2d-defs.h> 678c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-l2t-defs.h> 688c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-led-defs.h> 698c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-mio-defs.h> 708c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-pow-defs.h> 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-bootinfo.h> 738c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-bootmem.h> 748c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-l2c.h> 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#ifndef CVMX_ENABLE_DEBUG_PRINTS 778c2ecf20Sopenharmony_ci#define CVMX_ENABLE_DEBUG_PRINTS 1 788c2ecf20Sopenharmony_ci#endif 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#if CVMX_ENABLE_DEBUG_PRINTS 818c2ecf20Sopenharmony_ci#define cvmx_dprintf printk 828c2ecf20Sopenharmony_ci#else 838c2ecf20Sopenharmony_ci#define cvmx_dprintf(...) {} 848c2ecf20Sopenharmony_ci#endif 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define CVMX_MAX_CORES (16) 878c2ecf20Sopenharmony_ci#define CVMX_CACHE_LINE_SIZE (128) /* In bytes */ 888c2ecf20Sopenharmony_ci#define CVMX_CACHE_LINE_MASK (CVMX_CACHE_LINE_SIZE - 1) /* In bytes */ 898c2ecf20Sopenharmony_ci#define CVMX_CACHE_LINE_ALIGNED __attribute__ ((aligned(CVMX_CACHE_LINE_SIZE))) 908c2ecf20Sopenharmony_ci#define CAST64(v) ((long long)(long)(v)) 918c2ecf20Sopenharmony_ci#define CASTPTR(type, v) ((type *)(long)(v)) 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci/* 948c2ecf20Sopenharmony_ci * Returns processor ID, different Linux and simple exec versions 958c2ecf20Sopenharmony_ci * provided in the cvmx-app-init*.c files. 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_cistatic inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure)); 988c2ecf20Sopenharmony_cistatic inline uint32_t cvmx_get_proc_id(void) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci uint32_t id; 1018c2ecf20Sopenharmony_ci asm("mfc0 %0, $15,0" : "=r"(id)); 1028c2ecf20Sopenharmony_ci return id; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* turn the variable name into a string */ 1068c2ecf20Sopenharmony_ci#define CVMX_TMP_STR(x) CVMX_TMP_STR2(x) 1078c2ecf20Sopenharmony_ci#define CVMX_TMP_STR2(x) #x 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/** 1108c2ecf20Sopenharmony_ci * Builds a bit mask given the required size in bits. 1118c2ecf20Sopenharmony_ci * 1128c2ecf20Sopenharmony_ci * @bits: Number of bits in the mask 1138c2ecf20Sopenharmony_ci * Returns The mask 1148c2ecf20Sopenharmony_ci */ static inline uint64_t cvmx_build_mask(uint64_t bits) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci return ~((~0x0ull) << bits); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/** 1208c2ecf20Sopenharmony_ci * Builds a memory address for I/O based on the Major and Sub DID. 1218c2ecf20Sopenharmony_ci * 1228c2ecf20Sopenharmony_ci * @major_did: 5 bit major did 1238c2ecf20Sopenharmony_ci * @sub_did: 3 bit sub did 1248c2ecf20Sopenharmony_ci * Returns I/O base address 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_build_io_address(uint64_t major_did, 1278c2ecf20Sopenharmony_ci uint64_t sub_did) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci return (0x1ull << 48) | (major_did << 43) | (sub_did << 40); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/** 1338c2ecf20Sopenharmony_ci * Perform mask and shift to place the supplied value into 1348c2ecf20Sopenharmony_ci * the supplied bit rage. 1358c2ecf20Sopenharmony_ci * 1368c2ecf20Sopenharmony_ci * Example: cvmx_build_bits(39,24,value) 1378c2ecf20Sopenharmony_ci * <pre> 1388c2ecf20Sopenharmony_ci * 6 5 4 3 3 2 1 1398c2ecf20Sopenharmony_ci * 3 5 7 9 1 3 5 7 0 1408c2ecf20Sopenharmony_ci * +-------+-------+-------+-------+-------+-------+-------+------+ 1418c2ecf20Sopenharmony_ci * 000000000000000000000000___________value000000000000000000000000 1428c2ecf20Sopenharmony_ci * </pre> 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * @high_bit: Highest bit value can occupy (inclusive) 0-63 1458c2ecf20Sopenharmony_ci * @low_bit: Lowest bit value can occupy inclusive 0-high_bit 1468c2ecf20Sopenharmony_ci * @value: Value to use 1478c2ecf20Sopenharmony_ci * Returns Value masked and shifted 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_build_bits(uint64_t high_bit, 1508c2ecf20Sopenharmony_ci uint64_t low_bit, uint64_t value) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci return (value & cvmx_build_mask(high_bit - low_bit + 1)) << low_bit; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/** 1568c2ecf20Sopenharmony_ci * Convert a memory pointer (void*) into a hardware compatible 1578c2ecf20Sopenharmony_ci * memory address (uint64_t). Octeon hardware widgets don't 1588c2ecf20Sopenharmony_ci * understand logical addresses. 1598c2ecf20Sopenharmony_ci * 1608c2ecf20Sopenharmony_ci * @ptr: C style memory pointer 1618c2ecf20Sopenharmony_ci * Returns Hardware physical address 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_ptr_to_phys(void *ptr) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci if (sizeof(void *) == 8) { 1668c2ecf20Sopenharmony_ci /* 1678c2ecf20Sopenharmony_ci * We're running in 64 bit mode. Normally this means 1688c2ecf20Sopenharmony_ci * that we can use 40 bits of address space (the 1698c2ecf20Sopenharmony_ci * hardware limit). Unfortunately there is one case 1708c2ecf20Sopenharmony_ci * were we need to limit this to 30 bits, sign 1718c2ecf20Sopenharmony_ci * extended 32 bit. Although these are 64 bits wide, 1728c2ecf20Sopenharmony_ci * only 30 bits can be used. 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_ci if ((CAST64(ptr) >> 62) == 3) 1758c2ecf20Sopenharmony_ci return CAST64(ptr) & cvmx_build_mask(30); 1768c2ecf20Sopenharmony_ci else 1778c2ecf20Sopenharmony_ci return CAST64(ptr) & cvmx_build_mask(40); 1788c2ecf20Sopenharmony_ci } else { 1798c2ecf20Sopenharmony_ci return (long)(ptr) & 0x1fffffff; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/** 1848c2ecf20Sopenharmony_ci * Convert a hardware physical address (uint64_t) into a 1858c2ecf20Sopenharmony_ci * memory pointer (void *). 1868c2ecf20Sopenharmony_ci * 1878c2ecf20Sopenharmony_ci * @physical_address: 1888c2ecf20Sopenharmony_ci * Hardware physical address to memory 1898c2ecf20Sopenharmony_ci * Returns Pointer to memory 1908c2ecf20Sopenharmony_ci */ 1918c2ecf20Sopenharmony_cistatic inline void *cvmx_phys_to_ptr(uint64_t physical_address) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci if (sizeof(void *) == 8) { 1948c2ecf20Sopenharmony_ci /* Just set the top bit, avoiding any TLB ugliness */ 1958c2ecf20Sopenharmony_ci return CASTPTR(void, 1968c2ecf20Sopenharmony_ci CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, 1978c2ecf20Sopenharmony_ci physical_address)); 1988c2ecf20Sopenharmony_ci } else { 1998c2ecf20Sopenharmony_ci return CASTPTR(void, 2008c2ecf20Sopenharmony_ci CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, 2018c2ecf20Sopenharmony_ci physical_address)); 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci/* The following #if controls the definition of the macro 2068c2ecf20Sopenharmony_ci CVMX_BUILD_WRITE64. This macro is used to build a store operation to 2078c2ecf20Sopenharmony_ci a full 64bit address. With a 64bit ABI, this can be done with a simple 2088c2ecf20Sopenharmony_ci pointer access. 32bit ABIs require more complicated assembly */ 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci/* We have a full 64bit ABI. Writing to a 64bit address can be done with 2118c2ecf20Sopenharmony_ci a simple volatile pointer */ 2128c2ecf20Sopenharmony_ci#define CVMX_BUILD_WRITE64(TYPE, ST) \ 2138c2ecf20Sopenharmony_cistatic inline void cvmx_write64_##TYPE(uint64_t addr, TYPE##_t val) \ 2148c2ecf20Sopenharmony_ci{ \ 2158c2ecf20Sopenharmony_ci *CASTPTR(volatile TYPE##_t, addr) = val; \ 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* The following #if controls the definition of the macro 2208c2ecf20Sopenharmony_ci CVMX_BUILD_READ64. This macro is used to build a load operation from 2218c2ecf20Sopenharmony_ci a full 64bit address. With a 64bit ABI, this can be done with a simple 2228c2ecf20Sopenharmony_ci pointer access. 32bit ABIs require more complicated assembly */ 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci/* We have a full 64bit ABI. Writing to a 64bit address can be done with 2258c2ecf20Sopenharmony_ci a simple volatile pointer */ 2268c2ecf20Sopenharmony_ci#define CVMX_BUILD_READ64(TYPE, LT) \ 2278c2ecf20Sopenharmony_cistatic inline TYPE##_t cvmx_read64_##TYPE(uint64_t addr) \ 2288c2ecf20Sopenharmony_ci{ \ 2298c2ecf20Sopenharmony_ci return *CASTPTR(volatile TYPE##_t, addr); \ 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci/* The following defines 8 functions for writing to a 64bit address. Each 2348c2ecf20Sopenharmony_ci takes two arguments, the address and the value to write. 2358c2ecf20Sopenharmony_ci cvmx_write64_int64 cvmx_write64_uint64 2368c2ecf20Sopenharmony_ci cvmx_write64_int32 cvmx_write64_uint32 2378c2ecf20Sopenharmony_ci cvmx_write64_int16 cvmx_write64_uint16 2388c2ecf20Sopenharmony_ci cvmx_write64_int8 cvmx_write64_uint8 */ 2398c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(int64, "sd"); 2408c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(int32, "sw"); 2418c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(int16, "sh"); 2428c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(int8, "sb"); 2438c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(uint64, "sd"); 2448c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(uint32, "sw"); 2458c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(uint16, "sh"); 2468c2ecf20Sopenharmony_ciCVMX_BUILD_WRITE64(uint8, "sb"); 2478c2ecf20Sopenharmony_ci#define cvmx_write64 cvmx_write64_uint64 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/* The following defines 8 functions for reading from a 64bit address. Each 2508c2ecf20Sopenharmony_ci takes the address as the only argument 2518c2ecf20Sopenharmony_ci cvmx_read64_int64 cvmx_read64_uint64 2528c2ecf20Sopenharmony_ci cvmx_read64_int32 cvmx_read64_uint32 2538c2ecf20Sopenharmony_ci cvmx_read64_int16 cvmx_read64_uint16 2548c2ecf20Sopenharmony_ci cvmx_read64_int8 cvmx_read64_uint8 */ 2558c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(int64, "ld"); 2568c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(int32, "lw"); 2578c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(int16, "lh"); 2588c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(int8, "lb"); 2598c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(uint64, "ld"); 2608c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(uint32, "lw"); 2618c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(uint16, "lhu"); 2628c2ecf20Sopenharmony_ciCVMX_BUILD_READ64(uint8, "lbu"); 2638c2ecf20Sopenharmony_ci#define cvmx_read64 cvmx_read64_uint64 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci cvmx_write64(csr_addr, val); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /* 2718c2ecf20Sopenharmony_ci * Perform an immediate read after every write to an RSL 2728c2ecf20Sopenharmony_ci * register to force the write to complete. It doesn't matter 2738c2ecf20Sopenharmony_ci * what RSL read we do, so we choose CVMX_MIO_BOOT_BIST_STAT 2748c2ecf20Sopenharmony_ci * because it is fast and harmless. 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci if (((csr_addr >> 40) & 0x7ffff) == (0x118)) 2778c2ecf20Sopenharmony_ci cvmx_read64(CVMX_MIO_BOOT_BIST_STAT); 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic inline void cvmx_writeq_csr(void __iomem *csr_addr, uint64_t val) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci cvmx_write_csr((__force uint64_t)csr_addr, val); 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic inline void cvmx_write_io(uint64_t io_addr, uint64_t val) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci cvmx_write64(io_addr, val); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_read_csr(uint64_t csr_addr) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci uint64_t val = cvmx_read64(csr_addr); 2948c2ecf20Sopenharmony_ci return val; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_readq_csr(void __iomem *csr_addr) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci return cvmx_read_csr((__force uint64_t) csr_addr); 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic inline void cvmx_send_single(uint64_t data) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci const uint64_t CVMX_IOBDMA_SENDSINGLE = 0xffffffffffffa200ull; 3058c2ecf20Sopenharmony_ci cvmx_write64(CVMX_IOBDMA_SENDSINGLE, data); 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic inline void cvmx_read_csr_async(uint64_t scraddr, uint64_t csr_addr) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci union { 3118c2ecf20Sopenharmony_ci uint64_t u64; 3128c2ecf20Sopenharmony_ci struct { 3138c2ecf20Sopenharmony_ci uint64_t scraddr:8; 3148c2ecf20Sopenharmony_ci uint64_t len:8; 3158c2ecf20Sopenharmony_ci uint64_t addr:48; 3168c2ecf20Sopenharmony_ci } s; 3178c2ecf20Sopenharmony_ci } addr; 3188c2ecf20Sopenharmony_ci addr.u64 = csr_addr; 3198c2ecf20Sopenharmony_ci addr.s.scraddr = scraddr >> 3; 3208c2ecf20Sopenharmony_ci addr.s.len = 1; 3218c2ecf20Sopenharmony_ci cvmx_send_single(addr.u64); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci/* Return true if Octeon is CN38XX pass 1 */ 3258c2ecf20Sopenharmony_cistatic inline int cvmx_octeon_is_pass1(void) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci#if OCTEON_IS_COMMON_BINARY() 3288c2ecf20Sopenharmony_ci return 0; /* Pass 1 isn't supported for common binaries */ 3298c2ecf20Sopenharmony_ci#else 3308c2ecf20Sopenharmony_ci/* Now that we know we're built for a specific model, only check CN38XX */ 3318c2ecf20Sopenharmony_ci#if OCTEON_IS_MODEL(OCTEON_CN38XX) 3328c2ecf20Sopenharmony_ci return cvmx_get_proc_id() == OCTEON_CN38XX_PASS1; 3338c2ecf20Sopenharmony_ci#else 3348c2ecf20Sopenharmony_ci return 0; /* Built for non CN38XX chip, we're not CN38XX pass1 */ 3358c2ecf20Sopenharmony_ci#endif 3368c2ecf20Sopenharmony_ci#endif 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistatic inline unsigned int cvmx_get_core_num(void) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci unsigned int core_num; 3428c2ecf20Sopenharmony_ci CVMX_RDHWRNV(core_num, 0); 3438c2ecf20Sopenharmony_ci return core_num; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci/* Maximum # of bits to define core in node */ 3478c2ecf20Sopenharmony_ci#define CVMX_NODE_NO_SHIFT 7 3488c2ecf20Sopenharmony_ci#define CVMX_NODE_MASK 0x3 3498c2ecf20Sopenharmony_cistatic inline unsigned int cvmx_get_node_num(void) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci unsigned int core_num = cvmx_get_core_num(); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci return (core_num >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic inline unsigned int cvmx_get_local_core_num(void) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci return cvmx_get_core_num() & ((1 << CVMX_NODE_NO_SHIFT) - 1); 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci#define CVMX_NODE_BITS (2) /* Number of bits to define a node */ 3628c2ecf20Sopenharmony_ci#define CVMX_MAX_NODES (1 << CVMX_NODE_BITS) 3638c2ecf20Sopenharmony_ci#define CVMX_NODE_IO_SHIFT (36) 3648c2ecf20Sopenharmony_ci#define CVMX_NODE_MEM_SHIFT (40) 3658c2ecf20Sopenharmony_ci#define CVMX_NODE_IO_MASK ((uint64_t)CVMX_NODE_MASK << CVMX_NODE_IO_SHIFT) 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic inline void cvmx_write_csr_node(uint64_t node, uint64_t csr_addr, 3688c2ecf20Sopenharmony_ci uint64_t val) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci uint64_t composite_csr_addr, node_addr; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci node_addr = (node & CVMX_NODE_MASK) << CVMX_NODE_IO_SHIFT; 3738c2ecf20Sopenharmony_ci composite_csr_addr = (csr_addr & ~CVMX_NODE_IO_MASK) | node_addr; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci cvmx_write64_uint64(composite_csr_addr, val); 3768c2ecf20Sopenharmony_ci if (((csr_addr >> 40) & 0x7ffff) == (0x118)) 3778c2ecf20Sopenharmony_ci cvmx_read64_uint64(CVMX_MIO_BOOT_BIST_STAT | node_addr); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_read_csr_node(uint64_t node, uint64_t csr_addr) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci uint64_t node_addr; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci node_addr = (csr_addr & ~CVMX_NODE_IO_MASK) | 3858c2ecf20Sopenharmony_ci (node & CVMX_NODE_MASK) << CVMX_NODE_IO_SHIFT; 3868c2ecf20Sopenharmony_ci return cvmx_read_csr(node_addr); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci/** 3908c2ecf20Sopenharmony_ci * Returns the number of bits set in the provided value. 3918c2ecf20Sopenharmony_ci * Simple wrapper for POP instruction. 3928c2ecf20Sopenharmony_ci * 3938c2ecf20Sopenharmony_ci * @val: 32 bit value to count set bits in 3948c2ecf20Sopenharmony_ci * 3958c2ecf20Sopenharmony_ci * Returns Number of bits set 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_cistatic inline uint32_t cvmx_pop(uint32_t val) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci uint32_t pop; 4008c2ecf20Sopenharmony_ci CVMX_POP(pop, val); 4018c2ecf20Sopenharmony_ci return pop; 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci/** 4058c2ecf20Sopenharmony_ci * Returns the number of bits set in the provided value. 4068c2ecf20Sopenharmony_ci * Simple wrapper for DPOP instruction. 4078c2ecf20Sopenharmony_ci * 4088c2ecf20Sopenharmony_ci * @val: 64 bit value to count set bits in 4098c2ecf20Sopenharmony_ci * 4108c2ecf20Sopenharmony_ci * Returns Number of bits set 4118c2ecf20Sopenharmony_ci */ 4128c2ecf20Sopenharmony_cistatic inline int cvmx_dpop(uint64_t val) 4138c2ecf20Sopenharmony_ci{ 4148c2ecf20Sopenharmony_ci int pop; 4158c2ecf20Sopenharmony_ci CVMX_DPOP(pop, val); 4168c2ecf20Sopenharmony_ci return pop; 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci/** 4208c2ecf20Sopenharmony_ci * Provide current cycle counter as a return value 4218c2ecf20Sopenharmony_ci * 4228c2ecf20Sopenharmony_ci * Returns current cycle counter 4238c2ecf20Sopenharmony_ci */ 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_get_cycle(void) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci uint64_t cycle; 4288c2ecf20Sopenharmony_ci CVMX_RDHWR(cycle, 31); 4298c2ecf20Sopenharmony_ci return cycle; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci/** 4338c2ecf20Sopenharmony_ci * Reads a chip global cycle counter. This counts CPU cycles since 4348c2ecf20Sopenharmony_ci * chip reset. The counter is 64 bit. 4358c2ecf20Sopenharmony_ci * This register does not exist on CN38XX pass 1 silicion 4368c2ecf20Sopenharmony_ci * 4378c2ecf20Sopenharmony_ci * Returns Global chip cycle count since chip reset. 4388c2ecf20Sopenharmony_ci */ 4398c2ecf20Sopenharmony_cistatic inline uint64_t cvmx_get_cycle_global(void) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci if (cvmx_octeon_is_pass1()) 4428c2ecf20Sopenharmony_ci return 0; 4438c2ecf20Sopenharmony_ci else 4448c2ecf20Sopenharmony_ci return cvmx_read64(CVMX_IPD_CLK_COUNT); 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci/** 4488c2ecf20Sopenharmony_ci * This macro spins on a field waiting for it to reach a value. It 4498c2ecf20Sopenharmony_ci * is common in code to need to wait for a specific field in a CSR 4508c2ecf20Sopenharmony_ci * to match a specific value. Conceptually this macro expands to: 4518c2ecf20Sopenharmony_ci * 4528c2ecf20Sopenharmony_ci * 1) read csr at "address" with a csr typedef of "type" 4538c2ecf20Sopenharmony_ci * 2) Check if ("type".s."field" "op" "value") 4548c2ecf20Sopenharmony_ci * 3) If #2 isn't true loop to #1 unless too much time has passed. 4558c2ecf20Sopenharmony_ci */ 4568c2ecf20Sopenharmony_ci#define CVMX_WAIT_FOR_FIELD64(address, type, field, op, value, timeout_usec)\ 4578c2ecf20Sopenharmony_ci ( \ 4588c2ecf20Sopenharmony_ci{ \ 4598c2ecf20Sopenharmony_ci int result; \ 4608c2ecf20Sopenharmony_ci do { \ 4618c2ecf20Sopenharmony_ci uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \ 4628c2ecf20Sopenharmony_ci cvmx_sysinfo_get()->cpu_clock_hz / 1000000; \ 4638c2ecf20Sopenharmony_ci type c; \ 4648c2ecf20Sopenharmony_ci while (1) { \ 4658c2ecf20Sopenharmony_ci c.u64 = cvmx_read_csr(address); \ 4668c2ecf20Sopenharmony_ci if ((c.s.field) op(value)) { \ 4678c2ecf20Sopenharmony_ci result = 0; \ 4688c2ecf20Sopenharmony_ci break; \ 4698c2ecf20Sopenharmony_ci } else if (cvmx_get_cycle() > done) { \ 4708c2ecf20Sopenharmony_ci result = -1; \ 4718c2ecf20Sopenharmony_ci break; \ 4728c2ecf20Sopenharmony_ci } else \ 4738c2ecf20Sopenharmony_ci __delay(100); \ 4748c2ecf20Sopenharmony_ci } \ 4758c2ecf20Sopenharmony_ci } while (0); \ 4768c2ecf20Sopenharmony_ci result; \ 4778c2ecf20Sopenharmony_ci}) 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci/***************************************************************************/ 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci/* Return the number of cores available in the chip */ 4828c2ecf20Sopenharmony_cistatic inline uint32_t cvmx_octeon_num_cores(void) 4838c2ecf20Sopenharmony_ci{ 4848c2ecf20Sopenharmony_ci u64 ciu_fuse_reg; 4858c2ecf20Sopenharmony_ci u64 ciu_fuse; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX)) 4888c2ecf20Sopenharmony_ci ciu_fuse_reg = CVMX_CIU3_FUSE; 4898c2ecf20Sopenharmony_ci else 4908c2ecf20Sopenharmony_ci ciu_fuse_reg = CVMX_CIU_FUSE; 4918c2ecf20Sopenharmony_ci ciu_fuse = cvmx_read_csr(ciu_fuse_reg); 4928c2ecf20Sopenharmony_ci return cvmx_dpop(ciu_fuse); 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci#endif /* __CVMX_H__ */ 496