/*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * NETLOGIC_BSD */ #ifndef __NLM_HAL_COP2_H__ #define __NLM_HAL_COP2_H__ #define COP2_TX_BUF 0 #define COP2_RX_BUF 1 #define COP2_TXMSGSTATUS 2 #define COP2_RXMSGSTATUS 3 #define COP2_MSGSTATUS1 4 #define COP2_MSGCONFIG 5 #define COP2_MSGERROR 6 #define CROSSTHR_POPQ_EN 0x01 #define VC0_POPQ_EN 0x02 #define VC1_POPQ_EN 0x04 #define VC2_POPQ_EN 0x08 #define VC3_POPQ_EN 0x10 #define ALL_VC_POPQ_EN 0x1E #define ALL_VC_CT_POPQ_EN 0x1F struct nlm_fmn_msg { uint64_t msg[4]; }; #define NLM_DEFINE_COP2_ACCESSORS32(name, reg, sel) \ static inline uint32_t nlm_read_c2_##name(void) \ { \ uint32_t __rv; \ __asm__ __volatile__ ( \ ".set push\n" \ ".set noreorder\n" \ ".set mips64\n" \ "mfc2 %0, $%1, %2\n" \ ".set pop\n" \ : "=r" (__rv) \ : "i" (reg), "i" (sel)); \ return __rv; \ } \ \ static inline void nlm_write_c2_##name(uint32_t val) \ { \ __asm__ __volatile__( \ ".set push\n" \ ".set noreorder\n" \ ".set mips64\n" \ "mtc2 %0, $%1, %2\n" \ ".set pop\n" \ : : "r" (val), "i" (reg), "i" (sel)); \ } struct __hack #if (__mips == 64) #define NLM_DEFINE_COP2_ACCESSORS64(name, reg, sel) \ static inline uint64_t nlm_read_c2_##name(void) \ { \ uint64_t __rv; \ __asm__ __volatile__ ( \ ".set push\n" \ ".set noreorder\n" \ ".set mips64\n" \ "dmfc2 %0, $%1, %2\n" \ ".set pop\n" \ : "=r" (__rv) \ : "i" (reg), "i" (sel)); \ return __rv; \ } \ \ static inline void nlm_write_c2_##name(uint64_t val) \ { \ __asm__ __volatile__ ( \ ".set push\n" \ ".set noreorder\n" \ ".set mips64\n" \ "dmtc2 %0, $%1, %2\n" \ ".set pop\n" \ : : "r" (val), "i" (reg), "i" (sel)); \ } struct __hack #else #define NLM_DEFINE_COP2_ACCESSORS64(name, reg, sel) \ static inline uint64_t nlm_read_c2_##name(void) \ { \ uint32_t __high, __low; \ __asm__ __volatile__ ( \ ".set push\n" \ ".set noreorder\n" \ ".set mips64\n" \ "dmfc2 $8, $%2, %3\n" \ "dsra32 %0, $8, 0\n" \ "sll %1, $8, 0\n" \ ".set pop\n" \ : "=r"(__high), "=r"(__low) \ : "i"(reg), "i"(sel) \ : "$8"); \ \ return ((uint64_t)__high << 32) | __low; \ } \ \ static inline void nlm_write_c2_##name(uint64_t val) \ { \ uint32_t __high = val >> 32; \ uint32_t __low = val & 0xffffffff; \ __asm__ __volatile__ ( \ ".set push\n" \ ".set noreorder\n" \ ".set mips64\n" \ "dsll32 $8, %1, 0\n" \ "dsll32 $9, %0, 0\n" \ "dsrl32 $8, $8, 0\n" \ "or $8, $8, $9\n" \ "dmtc2 $8, $%2, %3\n" \ ".set pop\n" \ : : "r"(__high), "r"(__low), "i"(reg), "i"(sel) \ : "$8", "$9"); \ } struct __hack #endif NLM_DEFINE_COP2_ACCESSORS64(txbuf0, COP2_TX_BUF, 0); NLM_DEFINE_COP2_ACCESSORS64(txbuf1, COP2_TX_BUF, 1); NLM_DEFINE_COP2_ACCESSORS64(txbuf2, COP2_TX_BUF, 2); NLM_DEFINE_COP2_ACCESSORS64(txbuf3, COP2_TX_BUF, 3); NLM_DEFINE_COP2_ACCESSORS64(rxbuf0, COP2_RX_BUF, 0); NLM_DEFINE_COP2_ACCESSORS64(rxbuf1, COP2_RX_BUF, 1); NLM_DEFINE_COP2_ACCESSORS64(rxbuf2, COP2_RX_BUF, 2); NLM_DEFINE_COP2_ACCESSORS64(rxbuf3, COP2_RX_BUF, 3); NLM_DEFINE_COP2_ACCESSORS32(txmsgstatus, COP2_TXMSGSTATUS, 0); NLM_DEFINE_COP2_ACCESSORS32(rxmsgstatus, COP2_RXMSGSTATUS, 0); NLM_DEFINE_COP2_ACCESSORS32(msgstatus1, COP2_MSGSTATUS1, 0); NLM_DEFINE_COP2_ACCESSORS32(msgconfig, COP2_MSGCONFIG, 0); NLM_DEFINE_COP2_ACCESSORS32(msgerror0, COP2_MSGERROR, 0); NLM_DEFINE_COP2_ACCESSORS32(msgerror1, COP2_MSGERROR, 1); NLM_DEFINE_COP2_ACCESSORS32(msgerror2, COP2_MSGERROR, 2); NLM_DEFINE_COP2_ACCESSORS32(msgerror3, COP2_MSGERROR, 3); /* successful completion returns 1, else 0 */ static inline int nlm_msgsend(int val) { int result; __asm__ volatile ( ".set push\n" ".set noreorder\n" ".set mips64\n" "move $8, %1\n" "sync\n" "/* msgsnds $9, $8 */\n" ".word 0x4a084801\n" "move %0, $9\n" ".set pop\n" : "=r" (result) : "r" (val) : "$8", "$9"); return result; } static inline int nlm_msgld(int vc) { int val; __asm__ volatile ( ".set push\n" ".set noreorder\n" ".set mips64\n" "move $8, %1\n" "/* msgld $9, $8 */\n" ".word 0x4a084802\n" "move %0, $9\n" ".set pop\n" : "=r" (val) : "r" (vc) : "$8", "$9"); return val; } static inline void nlm_msgwait(int vc) { __asm__ volatile ( ".set push\n" ".set noreorder\n" ".set mips64\n" "move $8, %0\n" "/* msgwait $8 */\n" ".word 0x4a080003\n" ".set pop\n" : : "r" (vc) : "$8"); } static inline int nlm_fmn_msgsend(int dstid, int size, int swcode, struct nlm_fmn_msg *m) { uint32_t flags, status; int rv; size -= 1; flags = nlm_save_flags_cop2(); switch (size) { case 3: nlm_write_c2_txbuf3(m->msg[3]); case 2: nlm_write_c2_txbuf2(m->msg[2]); case 1: nlm_write_c2_txbuf1(m->msg[1]); case 0: nlm_write_c2_txbuf0(m->msg[0]); } dstid |= ((swcode << 24) | (size << 16)); status = nlm_msgsend(dstid); rv = !status; if (rv != 0) rv = nlm_read_c2_txmsgstatus(); nlm_restore_flags(flags); return rv; } static inline int nlm_fmn_msgrcv(int vc, int *srcid, int *size, int *code, struct nlm_fmn_msg *m) { uint32_t status; uint32_t msg_status, flags; int tmp_sz, rv; flags = nlm_save_flags_cop2(); status = nlm_msgld(vc); /* will return 0, if error */ rv = !status; if (rv == 0) { msg_status = nlm_read_c2_rxmsgstatus(); *size = ((msg_status >> 26) & 0x3) + 1; *code = (msg_status >> 18) & 0xff; *srcid = (msg_status >> 4) & 0xfff; tmp_sz = *size - 1; switch (tmp_sz) { case 3: m->msg[3] = nlm_read_c2_rxbuf3(); case 2: m->msg[2] = nlm_read_c2_rxbuf2(); case 1: m->msg[1] = nlm_read_c2_rxbuf1(); case 0: m->msg[0] = nlm_read_c2_rxbuf0(); } } nlm_restore_flags(flags); return rv; } static inline void nlm_fmn_cpu_init(int int_vec, int ecc_en, int v0pe, int v1pe, int v2pe, int v3pe) { uint32_t val = nlm_read_c2_msgconfig(); /* Note: in XLP PRM 0.8.1, the int_vec bits are un-documented * in msgconfig register of cop2. * As per chip/cpu RTL, [16:20] bits consist of int_vec. */ val |= (((int_vec & 0x1f) << 16) | ((ecc_en & 0x1) << 8) | ((v3pe & 0x1) << 4) | ((v2pe & 0x1) << 3) | ((v1pe & 0x1) << 2) | ((v0pe & 0x1) << 1)); nlm_write_c2_msgconfig(val); } #endif