452f22c389
* Update message station (CMS) code, read queue ids from PCI header. * Use interrupts to wakeup message handling threads on 3XX * Update PIC code, read interrupt information from PCI header instead of using fixed values. * Update PCI interrupt handling for the PIC change. * Update code for getting chip frequency, new code support XLP 3XX * Misc style(9) fixes In collaboration with: prabhath at netlogicmicro com (CMS/PIC) venkatesh at netlogicmicro.com (PCI)
303 lines
7.6 KiB
C
303 lines
7.6 KiB
C
/*-
|
|
* 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
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#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
|