coprocessor.h 5.1 KB
Newer Older
1
/*
2
 * include/asm-xtensa/coprocessor.h
3 4 5 6 7
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
8
 * Copyright (C) 2003 - 2007 Tensilica Inc.
9 10
 */

11

12 13 14
#ifndef _XTENSA_COPROCESSOR_H
#define _XTENSA_COPROCESSOR_H

15
#include <linux/stringify.h>
16
#include <variant/core.h>
17
#include <variant/tie.h>
18 19 20
#include <asm/types.h>

#ifdef __ASSEMBLY__
21
# include <variant/tie-asm.h>
22 23 24 25 26 27 28 29 30 31 32 33 34

.macro	xchal_sa_start  a b
	.set .Lxchal_pofs_, 0
	.set .Lxchal_ofs_, 0
.endm

.macro	xchal_sa_align  ptr minofs maxofs ofsalign totalign
	.set	.Lxchal_ofs_, .Lxchal_ofs_ + .Lxchal_pofs_ + \totalign - 1
	.set	.Lxchal_ofs_, (.Lxchal_ofs_ & -\totalign) - .Lxchal_pofs_
.endm

#define _SELECT	(  XTHAL_SAS_TIE | XTHAL_SAS_OPT \
		 | XTHAL_SAS_CC \
35
		 | XTHAL_SAS_CALR | XTHAL_SAS_CALE )
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

.macro save_xtregs_opt ptr clb at1 at2 at3 at4 offset
	.if XTREGS_OPT_SIZE > 0
		addi	\clb, \ptr, \offset
		xchal_ncp_store \clb \at1 \at2 \at3 \at4 select=_SELECT
	.endif
.endm

.macro load_xtregs_opt ptr clb at1 at2 at3 at4 offset
	.if XTREGS_OPT_SIZE > 0
		addi	\clb, \ptr, \offset
		xchal_ncp_load \clb \at1 \at2 \at3 \at4 select=_SELECT
	.endif
.endm
#undef _SELECT

#define _SELECT	(  XTHAL_SAS_TIE | XTHAL_SAS_OPT \
		 | XTHAL_SAS_NOCC \
		 | XTHAL_SAS_CALR | XTHAL_SAS_CALE | XTHAL_SAS_GLOB )

.macro save_xtregs_user ptr clb at1 at2 at3 at4 offset
	.if XTREGS_USER_SIZE > 0
		addi	\clb, \ptr, \offset
		xchal_ncp_store \clb \at1 \at2 \at3 \at4 select=_SELECT
	.endif
.endm

.macro load_xtregs_user ptr clb at1 at2 at3 at4 offset
	.if XTREGS_USER_SIZE > 0
		addi	\clb, \ptr, \offset
		xchal_ncp_load \clb \at1 \at2 \at3 \at4 select=_SELECT
	.endif
.endm
#undef _SELECT



#endif	/* __ASSEMBLY__ */
74

75
/*
76 77 78 79
 * XTENSA_HAVE_COPROCESSOR(x) returns 1 if coprocessor x is configured.
 *
 * XTENSA_HAVE_IO_PORT(x) returns 1 if io-port x is configured.
 *
80 81
 */

82 83 84 85 86 87 88 89
#define XTENSA_HAVE_COPROCESSOR(x)					\
	((XCHAL_CP_MASK ^ XCHAL_CP_PORT_MASK) & (1 << (x)))
#define XTENSA_HAVE_COPROCESSORS					\
	(XCHAL_CP_MASK ^ XCHAL_CP_PORT_MASK)
#define XTENSA_HAVE_IO_PORT(x)						\
	(XCHAL_CP_PORT_MASK & (1 << (x)))
#define XTENSA_HAVE_IO_PORTS						\
	XCHAL_CP_PORT_MASK
90 91 92

#ifndef __ASSEMBLY__

93

94
#if XCHAL_HAVE_CP
95

96 97 98 99 100 101 102
#define RSR_CPENABLE(x)	do {						  \
	__asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \
	} while(0);
#define WSR_CPENABLE(x)	do {						  \
  	__asm__ __volatile__("wsr %0," __stringify(CPENABLE) "; rsync" 	  \
	    		     :: "a" (x));				  \
	} while(0);
103

104 105 106 107 108 109 110 111 112 113 114 115
#endif /* XCHAL_HAVE_CP */


/*
 * Additional registers.
 * We define three types of additional registers:
 *  ext: extra registers that are used by the compiler
 *  cpn: optional registers that can be used by a user application
 *  cpX: coprocessor registers that can only be used if the corresponding
 *       CPENABLE bit is set.
 */

116 117 118 119 120 121
#define XCHAL_SA_REG(list,cc,abi,type,y,name,z,align,size,...)	\
	__REG ## list (cc, abi, type, name, size, align)

#define __REG0(cc,abi,t,name,s,a)	__REG0_ ## cc (abi,name)
#define __REG1(cc,abi,t,name,s,a)	__REG1_ ## cc (name)
#define __REG2(cc,abi,type,...)		__REG2_ ## type (__VA_ARGS__)
122

123 124 125 126 127
#define __REG0_0(abi,name)
#define __REG0_1(abi,name)		__REG0_1 ## abi (name)
#define __REG0_10(name)	__u32 name;
#define __REG0_11(name)	__u32 name;
#define __REG0_12(name)
128 129 130

#define __REG1_0(name)	__u32 name;
#define __REG1_1(name)
131

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
#define __REG2_0(n,s,a)	__u32 name;
#define __REG2_1(n,s,a)	unsigned char n[s] __attribute__ ((aligned(a)));
#define __REG2_2(n,s,a) unsigned char n[s] __attribute__ ((aligned(a)));

typedef struct { XCHAL_NCP_SA_LIST(0) } xtregs_opt_t
	__attribute__ ((aligned (XCHAL_NCP_SA_ALIGN)));
typedef struct { XCHAL_NCP_SA_LIST(1) } xtregs_user_t
	__attribute__ ((aligned (XCHAL_NCP_SA_ALIGN)));

#if XTENSA_HAVE_COPROCESSORS

typedef struct { XCHAL_CP0_SA_LIST(2) } xtregs_cp0_t
	__attribute__ ((aligned (XCHAL_CP0_SA_ALIGN)));
typedef struct { XCHAL_CP1_SA_LIST(2) } xtregs_cp1_t
	__attribute__ ((aligned (XCHAL_CP1_SA_ALIGN)));
typedef struct { XCHAL_CP2_SA_LIST(2) } xtregs_cp2_t
	__attribute__ ((aligned (XCHAL_CP2_SA_ALIGN)));
typedef struct { XCHAL_CP3_SA_LIST(2) } xtregs_cp3_t
	__attribute__ ((aligned (XCHAL_CP3_SA_ALIGN)));
typedef struct { XCHAL_CP4_SA_LIST(2) } xtregs_cp4_t
	__attribute__ ((aligned (XCHAL_CP4_SA_ALIGN)));
typedef struct { XCHAL_CP5_SA_LIST(2) } xtregs_cp5_t
	__attribute__ ((aligned (XCHAL_CP5_SA_ALIGN)));
typedef struct { XCHAL_CP6_SA_LIST(2) } xtregs_cp6_t
	__attribute__ ((aligned (XCHAL_CP6_SA_ALIGN)));
typedef struct { XCHAL_CP7_SA_LIST(2) } xtregs_cp7_t
	__attribute__ ((aligned (XCHAL_CP7_SA_ALIGN)));

extern struct thread_info* coprocessor_owner[XCHAL_CP_MAX];
extern void coprocessor_save(void*, int);
extern void coprocessor_load(void*, int);
extern void coprocessor_flush(struct thread_info*, int);
extern void coprocessor_restore(struct thread_info*, int);

extern void coprocessor_release_all(struct thread_info*);
extern void coprocessor_flush_all(struct thread_info*);

static inline void coprocessor_clear_cpenable(void)
{
	unsigned long i = 0;
	WSR_CPENABLE(i);
}

#endif	/* XTENSA_HAVE_COPROCESSORS */

#endif	/* !__ASSEMBLY__ */
178
#endif	/* _XTENSA_COPROCESSOR_H */